Path: blob/master/src/applications/fact/engine/PhabricatorManiphestTaskFactEngine.php
12256 views
<?php12final class PhabricatorManiphestTaskFactEngine3extends PhabricatorTransactionFactEngine {45public function newFacts() {6return array(7id(new PhabricatorCountFact())8->setKey('tasks.count.create'),910id(new PhabricatorCountFact())11->setKey('tasks.open-count.create'),12id(new PhabricatorCountFact())13->setKey('tasks.open-count.status'),1415id(new PhabricatorCountFact())16->setKey('tasks.count.create.project'),17id(new PhabricatorCountFact())18->setKey('tasks.count.assign.project'),19id(new PhabricatorCountFact())20->setKey('tasks.open-count.create.project'),21id(new PhabricatorCountFact())22->setKey('tasks.open-count.status.project'),23id(new PhabricatorCountFact())24->setKey('tasks.open-count.assign.project'),2526id(new PhabricatorCountFact())27->setKey('tasks.count.create.owner'),28id(new PhabricatorCountFact())29->setKey('tasks.count.assign.owner'),30id(new PhabricatorCountFact())31->setKey('tasks.open-count.create.owner'),32id(new PhabricatorCountFact())33->setKey('tasks.open-count.status.owner'),34id(new PhabricatorCountFact())35->setKey('tasks.open-count.assign.owner'),3637id(new PhabricatorPointsFact())38->setKey('tasks.points.create'),39id(new PhabricatorPointsFact())40->setKey('tasks.points.score'),4142id(new PhabricatorPointsFact())43->setKey('tasks.open-points.create'),44id(new PhabricatorPointsFact())45->setKey('tasks.open-points.status'),46id(new PhabricatorPointsFact())47->setKey('tasks.open-points.score'),4849id(new PhabricatorPointsFact())50->setKey('tasks.points.create.project'),51id(new PhabricatorPointsFact())52->setKey('tasks.points.assign.project'),53id(new PhabricatorPointsFact())54->setKey('tasks.points.score.project'),55id(new PhabricatorPointsFact())56->setKey('tasks.open-points.create.project'),57id(new PhabricatorPointsFact())58->setKey('tasks.open-points.status.project'),59id(new PhabricatorPointsFact())60->setKey('tasks.open-points.score.project'),61id(new PhabricatorPointsFact())62->setKey('tasks.open-points.assign.project'),6364id(new PhabricatorPointsFact())65->setKey('tasks.points.create.owner'),66id(new PhabricatorPointsFact())67->setKey('tasks.points.assign.owner'),68id(new PhabricatorPointsFact())69->setKey('tasks.points.score.owner'),70id(new PhabricatorPointsFact())71->setKey('tasks.open-points.create.owner'),72id(new PhabricatorPointsFact())73->setKey('tasks.open-points.status.owner'),74id(new PhabricatorPointsFact())75->setKey('tasks.open-points.score.owner'),76id(new PhabricatorPointsFact())77->setKey('tasks.open-points.assign.owner'),78);79}8081public function supportsDatapointsForObject(PhabricatorLiskDAO $object) {82return ($object instanceof ManiphestTask);83}8485public function newDatapointsForObject(PhabricatorLiskDAO $object) {86$xaction_groups = $this->newTransactionGroupsForObject($object);8788$old_open = false;89$old_points = 0;90$old_owner = null;91$project_map = array();92$object_phid = $object->getPHID();93$is_create = true;9495$specs = array();96$datapoints = array();97foreach ($xaction_groups as $xaction_group) {98$add_projects = array();99$rem_projects = array();100101$new_open = $old_open;102$new_points = $old_points;103$new_owner = $old_owner;104105if ($is_create) {106// Assume tasks start open.107// TODO: This might be a questionable assumption?108$new_open = true;109}110111$group_epoch = last($xaction_group)->getDateCreated();112foreach ($xaction_group as $xaction) {113$old_value = $xaction->getOldValue();114$new_value = $xaction->getNewValue();115switch ($xaction->getTransactionType()) {116case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:117$new_open = !ManiphestTaskStatus::isClosedStatus($new_value);118break;119case ManiphestTaskMergedIntoTransaction::TRANSACTIONTYPE:120// When a task is merged into another task, it is changed to a121// closed status without generating a separate status transaction.122$new_open = false;123break;124case ManiphestTaskPointsTransaction::TRANSACTIONTYPE:125$new_points = (int)$xaction->getNewValue();126break;127case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:128$new_owner = $xaction->getNewValue();129break;130case PhabricatorTransactions::TYPE_EDGE:131$edge_type = $xaction->getMetadataValue('edge:type');132switch ($edge_type) {133case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST:134$record = PhabricatorEdgeChangeRecord::newFromTransaction(135$xaction);136$add_projects += array_fuse($record->getAddedPHIDs());137$rem_projects += array_fuse($record->getRemovedPHIDs());138break;139}140break;141}142}143144// If a project was both added and removed, moot it.145$mix_projects = array_intersect_key($add_projects, $rem_projects);146$add_projects = array_diff_key($add_projects, $mix_projects);147$rem_projects = array_diff_key($rem_projects, $mix_projects);148149$project_sets = array(150array(151'phids' => $rem_projects,152'scale' => -1,153),154array(155'phids' => $add_projects,156'scale' => 1,157),158);159160if ($is_create) {161$action = 'create';162$action_points = $new_points;163$include_open = $new_open;164} else {165$action = 'assign';166$action_points = $old_points;167$include_open = $old_open;168}169170foreach ($project_sets as $project_set) {171$scale = $project_set['scale'];172foreach ($project_set['phids'] as $project_phid) {173if ($include_open) {174$specs[] = array(175"tasks.open-count.{$action}.project",1761 * $scale,177$project_phid,178);179180$specs[] = array(181"tasks.open-points.{$action}.project",182$action_points * $scale,183$project_phid,184);185}186187$specs[] = array(188"tasks.count.{$action}.project",1891 * $scale,190$project_phid,191);192193$specs[] = array(194"tasks.points.{$action}.project",195$action_points * $scale,196$project_phid,197);198199if ($scale < 0) {200unset($project_map[$project_phid]);201} else {202$project_map[$project_phid] = $project_phid;203}204}205}206207if ($new_owner !== $old_owner) {208$owner_sets = array(209array(210'phid' => $old_owner,211'scale' => -1,212),213array(214'phid' => $new_owner,215'scale' => 1,216),217);218219foreach ($owner_sets as $owner_set) {220$owner_phid = $owner_set['phid'];221if ($owner_phid === null) {222continue;223}224225$scale = $owner_set['scale'];226227if ($old_open != $new_open) {228$specs[] = array(229"tasks.open-count.{$action}.owner",2301 * $scale,231$owner_phid,232);233234$specs[] = array(235"tasks.open-points.{$action}.owner",236$action_points * $scale,237$owner_phid,238);239}240241$specs[] = array(242"tasks.count.{$action}.owner",2431 * $scale,244$owner_phid,245);246247if ($action_points) {248$specs[] = array(249"tasks.points.{$action}.owner",250$action_points * $scale,251$owner_phid,252);253}254}255}256257if ($is_create) {258$specs[] = array(259'tasks.count.create',2601,261);262263$specs[] = array(264'tasks.points.create',265$new_points,266);267268if ($new_open) {269$specs[] = array(270'tasks.open-count.create',2711,272);273$specs[] = array(274'tasks.open-points.create',275$new_points,276);277}278} else if ($new_open !== $old_open) {279if ($new_open) {280$scale = 1;281} else {282$scale = -1;283}284285$specs[] = array(286'tasks.open-count.status',2871 * $scale,288);289290$specs[] = array(291'tasks.open-points.status',292$action_points * $scale,293);294295if ($new_owner !== null) {296$specs[] = array(297'tasks.open-count.status.owner',2981 * $scale,299$new_owner,300);301$specs[] = array(302'tasks.open-points.status.owner',303$action_points * $scale,304$new_owner,305);306}307308foreach ($project_map as $project_phid) {309$specs[] = array(310'tasks.open-count.status.project',3111 * $scale,312$project_phid,313);314$specs[] = array(315'tasks.open-points.status.project',316$action_points * $scale,317$project_phid,318);319}320}321322// The "score" facts only apply to rescoring tasks which already323// exist, so we skip them if the task is being created.324if (($new_points !== $old_points) && !$is_create) {325$delta = ($new_points - $old_points);326327$specs[] = array(328'tasks.points.score',329$delta,330);331332foreach ($project_map as $project_phid) {333$specs[] = array(334'tasks.points.score.project',335$delta,336$project_phid,337);338339if ($old_open && $new_open) {340$specs[] = array(341'tasks.open-points.score.project',342$delta,343$project_phid,344);345}346}347348if ($new_owner !== null) {349$specs[] = array(350'tasks.points.score.owner',351$delta,352$new_owner,353);354355if ($old_open && $new_open) {356$specs[] = array(357'tasks.open-points.score.owner',358$delta,359$new_owner,360);361}362}363364if ($old_open && $new_open) {365$specs[] = array(366'tasks.open-points.score',367$delta,368);369}370}371372$old_points = $new_points;373$old_open = $new_open;374$old_owner = $new_owner;375376foreach ($specs as $spec) {377$spec_key = $spec[0];378$spec_value = $spec[1];379380// Don't write any facts with a value of 0. The "count" facts never381// have a value of 0, and the "points" facts aren't meaningful if382// they have a value of 0.383if ($spec_value == 0) {384continue;385}386387$datapoint = $this->getFact($spec_key)388->newDatapoint();389390$datapoint391->setObjectPHID($object_phid)392->setValue($spec_value)393->setEpoch($group_epoch);394395if (isset($spec[2])) {396$datapoint->setDimensionPHID($spec[2]);397}398399$datapoints[] = $datapoint;400}401402$specs = array();403$is_create = false;404}405406return $datapoints;407}408409410}411412413