Path: blob/master/src/applications/fact/controller/PhabricatorFactObjectController.php
12256 views
<?php12final class PhabricatorFactObjectController3extends PhabricatorFactController {45public function handleRequest(AphrontRequest $request) {6$viewer = $request->getViewer();78$phid = $request->getURIData('phid');9$object = id(new PhabricatorObjectQuery())10->setViewer($viewer)11->withNames(array($phid))12->executeOne();13if (!$object) {14return new Aphront404Response();15}1617$engines = PhabricatorFactEngine::loadAllEngines();18foreach ($engines as $key => $engine) {19$engine = id(clone $engine)20->setViewer($viewer);21$engines[$key] = $engine;2223if (!$engine->supportsDatapointsForObject($object)) {24unset($engines[$key]);25}26}2728if (!$engines) {29return $this->newDialog()30->setTitle(pht('No Engines'))31->appendParagraph(32pht(33'No fact engines support generating facts for this object.'))34->addCancelButton($this->getApplicationURI());35}3637$key_dimension = new PhabricatorFactKeyDimension();38$object_phid = $object->getPHID();3940$facts = array();41$generated_datapoints = array();42$timings = array();43foreach ($engines as $key => $engine) {44$engine_facts = $engine->newFacts();45$engine_facts = mpull($engine_facts, null, 'getKey');46$facts[$key] = $engine_facts;4748$t_start = microtime(true);49$generated_datapoints[$key] = $engine->newDatapointsForObject($object);50$t_end = microtime(true);5152$timings[$key] = ($t_end - $t_start);53}5455$object_id = id(new PhabricatorFactObjectDimension())56->newDimensionID($object_phid, true);5758$stored_datapoints = id(new PhabricatorFactDatapointQuery())59->withFacts(array_mergev($facts))60->withObjectPHIDs(array($object_phid))61->needVectors(true)62->execute();6364$stored_groups = array();65foreach ($stored_datapoints as $stored_datapoint) {66$stored_groups[$stored_datapoint['key']][] = $stored_datapoint;67}6869$stored_map = array();70foreach ($engines as $key => $engine) {71$stored_map[$key] = array();72foreach ($facts[$key] as $fact) {73$fact_datapoints = idx($stored_groups, $fact->getKey(), array());74$fact_datapoints = igroup($fact_datapoints, 'vector');75$stored_map[$key] += $fact_datapoints;76}77}7879$handle_phids = array();80$handle_phids[] = $object->getPHID();81foreach ($generated_datapoints as $key => $datapoint_set) {82foreach ($datapoint_set as $datapoint) {83$dimension_phid = $datapoint->getDimensionPHID();84if ($dimension_phid !== null) {85$handle_phids[$dimension_phid] = $dimension_phid;86}87}88}8990foreach ($stored_map as $key => $stored_datapoints) {91foreach ($stored_datapoints as $vector_key => $datapoints) {92foreach ($datapoints as $datapoint) {93$dimension_phid = $datapoint['dimensionPHID'];94if ($dimension_phid !== null) {95$handle_phids[$dimension_phid] = $dimension_phid;96}97}98}99}100101$handles = $viewer->loadHandles($handle_phids);102103$dimension_map = id(new PhabricatorFactObjectDimension())104->newDimensionMap($handle_phids, true);105106$content = array();107108$object_list = id(new PHUIPropertyListView())109->setViewer($viewer)110->addProperty(111pht('Object'),112$handles[$object->getPHID()]->renderLink());113114$total_cost = array_sum($timings);115$total_cost = pht('%sms', new PhutilNumber((int)(1000 * $total_cost)));116$object_list->addProperty(pht('Total Cost'), $total_cost);117118$object_box = id(new PHUIObjectBoxView())119->setHeaderText(pht('Fact Extraction Report'))120->addPropertyList($object_list);121122$content[] = $object_box;123124$icon_fact = id(new PHUIIconView())125->setIcon('fa-line-chart green')126->setTooltip(pht('Consistent Fact'));127128$icon_nodata = id(new PHUIIconView())129->setIcon('fa-question-circle-o violet')130->setTooltip(pht('No Stored Datapoints'));131132$icon_new = id(new PHUIIconView())133->setIcon('fa-plus red')134->setTooltip(pht('Not Stored'));135136$icon_surplus = id(new PHUIIconView())137->setIcon('fa-minus red')138->setTooltip(pht('Not Generated'));139140foreach ($engines as $key => $engine) {141$rows = array();142foreach ($generated_datapoints[$key] as $datapoint) {143$dimension_phid = $datapoint->getDimensionPHID();144if ($dimension_phid !== null) {145$dimension = $handles[$datapoint->getDimensionPHID()]->renderLink();146} else {147$dimension = null;148}149150$fact_key = $datapoint->getKey();151152$fact = idx($facts[$key], $fact_key, null);153if ($fact) {154$fact_label = $fact->getName();155} else {156$fact_label = $fact_key;157}158159$vector_key = $datapoint->newDatapointVector();160if (isset($stored_map[$key][$vector_key])) {161unset($stored_map[$key][$vector_key]);162$icon = $icon_fact;163} else {164$icon = $icon_new;165}166167$rows[] = array(168$icon,169$fact_label,170$dimension,171$datapoint->getValue(),172phabricator_datetime($datapoint->getEpoch(), $viewer),173);174}175176foreach ($stored_map[$key] as $vector_key => $datapoints) {177foreach ($datapoints as $datapoint) {178$dimension_phid = $datapoint['dimensionPHID'];179if ($dimension_phid !== null) {180$dimension = $handles[$dimension_phid]->renderLink();181} else {182$dimension = null;183}184185$fact_key = $datapoint['key'];186$fact = idx($facts[$key], $fact_key, null);187if ($fact) {188$fact_label = $fact->getName();189} else {190$fact_label = $fact_key;191}192193$rows[] = array(194$icon_surplus,195$fact_label,196$dimension,197$datapoint['value'],198phabricator_datetime($datapoint['epoch'], $viewer),199);200}201}202203foreach ($facts[$key] as $fact) {204$has_any = id(new PhabricatorFactDatapointQuery())205->withFacts(array($fact))206->setLimit(1)207->execute();208if ($has_any) {209continue;210}211212if (!$has_any) {213$rows[] = array(214$icon_nodata,215$fact->getName(),216null,217null,218null,219);220}221}222223$table = id(new AphrontTableView($rows))224->setHeaders(225array(226null,227pht('Fact'),228pht('Dimension'),229pht('Value'),230pht('Date'),231))232->setColumnClasses(233array(234'',235'',236'',237'n wide right',238'right',239));240241$extraction_cost = $timings[$key];242$extraction_cost = pht(243'%sms',244new PhutilNumber((int)(1000 * $extraction_cost)));245246$header = pht(247'%s (%s)',248get_class($engine),249$extraction_cost);250251$box = id(new PHUIObjectBoxView())252->setHeaderText($header)253->setTable($table);254255$content[] = $box;256257if ($engine instanceof PhabricatorTransactionFactEngine) {258$groups = $engine->newTransactionGroupsForObject($object);259$groups = array_values($groups);260261$xaction_phids = array();262foreach ($groups as $group_key => $xactions) {263foreach ($xactions as $xaction) {264$xaction_phids[] = $xaction->getAuthorPHID();265}266}267$xaction_handles = $viewer->loadHandles($xaction_phids);268269$rows = array();270foreach ($groups as $group_key => $xactions) {271foreach ($xactions as $xaction) {272$rows[] = array(273$group_key,274$xaction->getTransactionType(),275$xaction_handles[$xaction->getAuthorPHID()]->renderLink(),276phabricator_datetime($xaction->getDateCreated(), $viewer),277);278}279}280281$table = id(new AphrontTableView($rows))282->setHeaders(283array(284pht('Group'),285pht('Type'),286pht('Author'),287pht('Date'),288))289->setColumnClasses(290array(291null,292'pri',293'wide',294'right',295));296297$header = pht(298'%s (Transactions)',299get_class($engine));300301$xaction_box = id(new PHUIObjectBoxView())302->setHeaderText($header)303->setTable($table);304305$content[] = $xaction_box;306}307308}309310$crumbs = $this->buildApplicationCrumbs()311->addTextCrumb(pht('Chart'));312313$title = pht('Chart');314315return $this->newPage()316->setTitle($title)317->setCrumbs($crumbs)318->appendChild($content);319320}321322}323324325