Path: blob/master/src/applications/differential/controller/DifferentialController.php
12256 views
<?php12abstract class DifferentialController extends PhabricatorController {34private $packageChangesetMap;5private $pathPackageMap;6private $authorityPackages;78public function buildSideNavView($for_app = false) {9$viewer = $this->getRequest()->getUser();1011$nav = new AphrontSideNavFilterView();12$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));1314id(new DifferentialRevisionSearchEngine())15->setViewer($viewer)16->addNavigationItems($nav->getMenu());1718$nav->selectFilter(null);1920return $nav;21}2223public function buildApplicationMenu() {24return $this->buildSideNavView(true)->getMenu();25}2627protected function buildPackageMaps(array $changesets) {28assert_instances_of($changesets, 'DifferentialChangeset');2930$this->packageChangesetMap = array();31$this->pathPackageMap = array();32$this->authorityPackages = array();3334if (!$changesets) {35return;36}3738$viewer = $this->getViewer();3940$have_owners = PhabricatorApplication::isClassInstalledForViewer(41'PhabricatorOwnersApplication',42$viewer);43if (!$have_owners) {44return;45}4647$changeset = head($changesets);48$diff = $changeset->getDiff();49$repository_phid = $diff->getRepositoryPHID();50if (!$repository_phid) {51return;52}5354if ($viewer->getPHID()) {55$packages = id(new PhabricatorOwnersPackageQuery())56->setViewer($viewer)57->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE))58->withAuthorityPHIDs(array($viewer->getPHID()))59->execute();60$this->authorityPackages = $packages;61}6263$paths = mpull($changesets, 'getOwnersFilename');6465$control_query = id(new PhabricatorOwnersPackageQuery())66->setViewer($viewer)67->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE))68->withControl($repository_phid, $paths);69$control_query->execute();7071foreach ($changesets as $changeset) {72$changeset_path = $changeset->getOwnersFilename();7374$packages = $control_query->getControllingPackagesForPath(75$repository_phid,76$changeset_path);7778// If this particular changeset is generated code and the package does79// not match generated code, remove it from the list.80if ($changeset->isGeneratedChangeset()) {81foreach ($packages as $key => $package) {82if ($package->getMustMatchUngeneratedPaths()) {83unset($packages[$key]);84}85}86}8788$this->pathPackageMap[$changeset_path] = $packages;89foreach ($packages as $package) {90$this->packageChangesetMap[$package->getPHID()][] = $changeset;91}92}93}9495protected function getAuthorityPackages() {96if ($this->authorityPackages === null) {97throw new PhutilInvalidStateException('buildPackageMaps');98}99return $this->authorityPackages;100}101102protected function getChangesetPackages(DifferentialChangeset $changeset) {103if ($this->pathPackageMap === null) {104throw new PhutilInvalidStateException('buildPackageMaps');105}106107$path = $changeset->getOwnersFilename();108return idx($this->pathPackageMap, $path, array());109}110111protected function getPackageChangesets($package_phid) {112if ($this->packageChangesetMap === null) {113throw new PhutilInvalidStateException('buildPackageMaps');114}115116return idx($this->packageChangesetMap, $package_phid, array());117}118119protected function buildTableOfContents(120array $changesets,121array $visible_changesets,122array $coverage) {123$viewer = $this->getViewer();124125$toc_view = id(new PHUIDiffTableOfContentsListView())126->setViewer($viewer)127->setBare(true)128->setAuthorityPackages($this->getAuthorityPackages());129130foreach ($changesets as $changeset_id => $changeset) {131$is_visible = isset($visible_changesets[$changeset_id]);132$anchor = $changeset->getAnchorName();133134$filename = $changeset->getFilename();135$coverage_id = 'differential-mcoverage-'.md5($filename);136137$item = id(new PHUIDiffTableOfContentsItemView())138->setChangeset($changeset)139->setIsVisible($is_visible)140->setAnchor($anchor)141->setCoverage(idx($coverage, $filename))142->setCoverageID($coverage_id);143144$packages = $this->getChangesetPackages($changeset);145$item->setPackages($packages);146147$toc_view->addItem($item);148}149150return $toc_view;151}152153protected function loadDiffProperties(array $diffs) {154$diffs = mpull($diffs, null, 'getID');155156$properties = id(new DifferentialDiffProperty())->loadAllWhere(157'diffID IN (%Ld)',158array_keys($diffs));159$properties = mgroup($properties, 'getDiffID');160161foreach ($diffs as $id => $diff) {162$values = idx($properties, $id, array());163$values = mpull($values, 'getData', 'getName');164$diff->attachDiffProperties($values);165}166}167168169protected function loadHarbormasterData(array $diffs) {170$viewer = $this->getViewer();171172$diffs = mpull($diffs, null, 'getPHID');173174$buildables = id(new HarbormasterBuildableQuery())175->setViewer($viewer)176->withBuildablePHIDs(array_keys($diffs))177->withManualBuildables(false)178->needBuilds(true)179->needTargets(true)180->execute();181182$buildables = mpull($buildables, null, 'getBuildablePHID');183foreach ($diffs as $phid => $diff) {184$diff->attachBuildable(idx($buildables, $phid));185}186187$target_map = array();188foreach ($diffs as $phid => $diff) {189$target_map[$phid] = $diff->getBuildTargetPHIDs();190}191$all_target_phids = array_mergev($target_map);192193if ($all_target_phids) {194$unit_messages = id(new HarbormasterBuildUnitMessageQuery())195->setViewer($viewer)196->withBuildTargetPHIDs($all_target_phids)197->execute();198$unit_messages = mgroup($unit_messages, 'getBuildTargetPHID');199} else {200$unit_messages = array();201}202203foreach ($diffs as $phid => $diff) {204$target_phids = idx($target_map, $phid, array());205$messages = array_select_keys($unit_messages, $target_phids);206$messages = array_mergev($messages);207$diff->attachUnitMessages($messages);208}209210// For diffs with no messages, look for legacy unit messages stored on the211// diff itself.212foreach ($diffs as $phid => $diff) {213if ($diff->getUnitMessages()) {214continue;215}216217if (!$diff->hasDiffProperty('arc:unit')) {218continue;219}220221$legacy_messages = $diff->getProperty('arc:unit');222if (!$legacy_messages) {223continue;224}225226// Show the top 100 legacy lint messages. Previously, we showed some227// by default and let the user toggle the rest. With modern messages,228// we can send the user to the Harbormaster detail page. Just show229// "a lot" of messages in legacy cases to try to strike a balance230// between implementation simplicity and compatibility.231$legacy_messages = array_slice($legacy_messages, 0, 100);232233$messages = array();234foreach ($legacy_messages as $message) {235$messages[] = HarbormasterBuildUnitMessage::newFromDictionary(236new HarbormasterBuildTarget(),237$this->getModernUnitMessageDictionary($message));238}239240$diff->attachUnitMessages($messages);241}242}243244private function getModernUnitMessageDictionary(array $map) {245// Strip out `null` values to satisfy stricter typechecks.246foreach ($map as $key => $value) {247if ($value === null) {248unset($map[$key]);249}250}251252// Cast duration to a float since it used to be a string in some253// cases.254if (isset($map['duration'])) {255$map['duration'] = (double)$map['duration'];256}257258return $map;259}260261protected function getDiffTabLabels(array $diffs) {262// Make sure we're only going to render unique diffs.263$diffs = mpull($diffs, null, 'getID');264$labels = array(pht('Left'), pht('Right'));265266$results = array();267268foreach ($diffs as $diff) {269if (count($diffs) == 2) {270$label = array_shift($labels);271$label = pht('%s (Diff %d)', $label, $diff->getID());272} else {273$label = pht('Diff %d', $diff->getID());274}275276$results[] = array(277$label,278$diff,279);280}281282return $results;283}284285286}287288289