@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use ApplicationSearch in Herald

Summary: Ref T2769. Ref T2625. Herald is currently a giant mishmash of hard-codes and weird special cases. Move toward modernization and normality.

Test Plan: {F52716}

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2625, T2769

Differential Revision: https://secure.phabricator.com/D6652

+231 -269
+8 -4
src/__phutil_library_map__.php
··· 611 611 'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php', 612 612 'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php', 613 613 'HeraldFieldConfig' => 'applications/herald/config/HeraldFieldConfig.php', 614 - 'HeraldHomeController' => 'applications/herald/controller/HeraldHomeController.php', 615 614 'HeraldInvalidConditionException' => 'applications/herald/engine/engine/HeraldInvalidConditionException.php', 616 615 'HeraldInvalidFieldException' => 'applications/herald/engine/engine/HeraldInvalidFieldException.php', 617 616 'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php', ··· 625 624 'HeraldRuleEdit' => 'applications/herald/storage/HeraldRuleEdit.php', 626 625 'HeraldRuleEditHistoryController' => 'applications/herald/controller/HeraldRuleEditHistoryController.php', 627 626 'HeraldRuleEditHistoryView' => 'applications/herald/view/HeraldRuleEditHistoryView.php', 628 - 'HeraldRuleListView' => 'applications/herald/view/HeraldRuleListView.php', 627 + 'HeraldRuleListController' => 'applications/herald/controller/HeraldRuleListController.php', 629 628 'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php', 629 + 'HeraldRuleSearchEngine' => 'applications/herald/query/HeraldRuleSearchEngine.php', 630 630 'HeraldRuleTranscript' => 'applications/herald/storage/transcript/HeraldRuleTranscript.php', 631 631 'HeraldRuleTypeConfig' => 'applications/herald/config/HeraldRuleTypeConfig.php', 632 632 'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php', ··· 2618 2618 'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter', 2619 2619 'HeraldDryRunAdapter' => 'HeraldObjectAdapter', 2620 2620 'HeraldEditLogQuery' => 'PhabricatorOffsetPagedQuery', 2621 - 'HeraldHomeController' => 'HeraldController', 2622 2621 'HeraldInvalidConditionException' => 'Exception', 2623 2622 'HeraldInvalidFieldException' => 'Exception', 2624 2623 'HeraldNewController' => 'HeraldController', ··· 2633 2632 'HeraldRuleEdit' => 'HeraldDAO', 2634 2633 'HeraldRuleEditHistoryController' => 'HeraldController', 2635 2634 'HeraldRuleEditHistoryView' => 'AphrontView', 2636 - 'HeraldRuleListView' => 'AphrontView', 2635 + 'HeraldRuleListController' => 2636 + array( 2637 + 0 => 'HeraldController', 2638 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 2639 + ), 2637 2640 'HeraldRuleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 2641 + 'HeraldRuleSearchEngine' => 'PhabricatorApplicationSearchEngine', 2638 2642 'HeraldTestConsoleController' => 'HeraldController', 2639 2643 'HeraldTranscript' => 'HeraldDAO', 2640 2644 'HeraldTranscriptController' => 'HeraldController',
+1 -3
src/applications/herald/application/PhabricatorApplicationHerald.php
··· 33 33 public function getRoutes() { 34 34 return array( 35 35 '/herald/' => array( 36 - '' => 'HeraldHomeController', 37 - 'view/(?P<content_type>[^/]+)/(?:(?P<rule_type>[^/]+)/)?' 38 - => 'HeraldHomeController', 36 + '(?:query/(?P<queryKey>[^/]+)/)?' => 'HeraldRuleListController', 39 37 'new/(?:(?P<type>[^/]+)/(?:(?P<rule_type>[^/]+)/)?)?' 40 38 => 'HeraldNewController', 41 39 'rule/(?:(?P<id>[1-9]\d*)/)?' => 'HeraldRuleController',
+12 -20
src/applications/herald/controller/HeraldController.php
··· 17 17 } 18 18 19 19 public function buildApplicationMenu() { 20 - return $this->renderNav()->getMenu(); 20 + return $this->buildSideNavView(true)->getMenu(); 21 21 } 22 22 23 23 public function buildApplicationCrumbs() { ··· 32 32 return $crumbs; 33 33 } 34 34 35 - protected function renderNav() { 36 - $nav = id(new AphrontSideNavFilterView()) 37 - ->setBaseURI(new PhutilURI('/herald/')) 38 - ->addLabel(pht('My Rules')) 39 - ->addFilter('new', pht('Create Rule')); 40 - 41 - $rules_map = HeraldContentTypeConfig::getContentTypeMap(); 42 - foreach ($rules_map as $key => $value) { 43 - $nav->addFilter("view/{$key}/personal", $value); 44 - } 35 + public function buildSideNavView($for_app = false) { 36 + $user = $this->getRequest()->getUser(); 45 37 46 - $nav->addLabel(pht('Global Rules')); 38 + $nav = new AphrontSideNavFilterView(); 39 + $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 47 40 48 - foreach ($rules_map as $key => $value) { 49 - $nav->addFilter("view/{$key}/global", $value); 41 + if ($for_app) { 42 + $nav->addFilter('create', pht('Create Rule')); 50 43 } 51 44 45 + id(new HeraldRuleSearchEngine()) 46 + ->setViewer($user) 47 + ->addNavigationItems($nav->getMenu()); 48 + 52 49 $nav 53 50 ->addLabel(pht('Utilities')) 54 51 ->addFilter('test', pht('Test Console')) 55 52 ->addFilter('transcript', pht('Transcripts')) 56 53 ->addFilter('history', pht('Edit Log')); 57 54 58 - if ($this->getRequest()->getUser()->getIsAdmin()) { 59 - $nav->addLabel(pht('Admin')); 60 - foreach ($rules_map as $key => $value) { 61 - $nav->addFilter("view/{$key}/all", $value); 62 - } 63 - } 55 + $nav->selectFilter(null); 64 56 65 57 return $nav; 66 58 }
-156
src/applications/herald/controller/HeraldHomeController.php
··· 1 - <?php 2 - 3 - final class HeraldHomeController extends HeraldController { 4 - 5 - private $contentType; 6 - private $ruleType; 7 - 8 - public function willProcessRequest(array $data) { 9 - $this->contentType = idx($data, 'content_type'); 10 - $this->ruleType = idx($data, 'rule_type'); 11 - } 12 - 13 - public function processRequest() { 14 - $request = $this->getRequest(); 15 - $user = $request->getUser(); 16 - 17 - if ($request->isFormPost()) { 18 - $phids = $request->getArr('set_phid'); 19 - $phid = head($phids); 20 - 21 - $uri = $request->getRequestURI(); 22 - if ($phid) { 23 - $uri = $uri->alter('phid', nonempty($phid, null)); 24 - } 25 - 26 - return id(new AphrontRedirectResponse())->setURI($uri); 27 - } 28 - 29 - $query = id(new HeraldRuleQuery()) 30 - ->setViewer($user); 31 - 32 - $content_type_map = HeraldContentTypeConfig::getContentTypeMap(); 33 - if (empty($content_type_map[$this->contentType])) { 34 - $this->contentType = head_key($content_type_map); 35 - } 36 - $content_desc = $content_type_map[$this->contentType]; 37 - 38 - $query->withContentTypes(array($this->contentType)); 39 - 40 - $show_author = false; 41 - $show_rule_type = false; 42 - $has_author_filter = false; 43 - $author_filter_phid = null; 44 - 45 - switch ($this->ruleType) { 46 - case 'all': 47 - if (!$user->getIsAdmin()) { 48 - return new Aphront400Response(); 49 - } 50 - $show_rule_type = true; 51 - $show_author = true; 52 - $has_author_filter = true; 53 - $author_filter_phid = $request->getStr('phid'); 54 - if ($author_filter_phid) { 55 - $query->withAuthorPHIDs(array($author_filter_phid)); 56 - } 57 - $rule_desc = pht('All'); 58 - break; 59 - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: 60 - $query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_GLOBAL)); 61 - $rule_desc = pht('Global'); 62 - break; 63 - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: 64 - default: 65 - $this->ruleType = HeraldRuleTypeConfig::RULE_TYPE_PERSONAL; 66 - $query->withRuleTypes(array(HeraldRuleTypeConfig::RULE_TYPE_PERSONAL)); 67 - $query->withAuthorPHIDs(array($user->getPHID())); 68 - $rule_desc = pht('Personal'); 69 - break; 70 - } 71 - 72 - $pager = new AphrontPagerView(); 73 - $pager->setURI($request->getRequestURI(), 'offset'); 74 - $pager->setOffset($request->getStr('offset')); 75 - 76 - $rules = $query->executeWithOffsetPager($pager); 77 - 78 - $need_phids = mpull($rules, 'getAuthorPHID'); 79 - $handles = $this->loadViewerHandles($need_phids); 80 - 81 - $list_view = id(new HeraldRuleListView()) 82 - ->setRules($rules) 83 - ->setShowAuthor($show_author) 84 - ->setShowRuleType($show_rule_type) 85 - ->setHandles($handles) 86 - ->setUser($user); 87 - 88 - $panel = new AphrontPanelView(); 89 - $panel->appendChild($list_view); 90 - $panel->appendChild($pager); 91 - $panel->setNoBackground(); 92 - 93 - $panel->setHeader( 94 - pht("Herald: %s Rules for %s", $rule_desc, $content_desc)); 95 - 96 - $crumbs = $this 97 - ->buildApplicationCrumbs() 98 - ->addCrumb( 99 - id(new PhabricatorCrumbView()) 100 - ->setName(pht('Herald Rules')) 101 - ->setHref($this->getApplicationURI( 102 - 'view/'.$this->contentType.'/'.$this->ruleType))); 103 - 104 - $nav = $this->renderNav(); 105 - $nav->selectFilter('view/'.$this->contentType.'/'.$this->ruleType); 106 - 107 - if ($has_author_filter) { 108 - $nav->appendChild($this->renderAuthorFilter($author_filter_phid)); 109 - } 110 - 111 - $nav->appendChild($panel); 112 - $nav->setCrumbs($crumbs); 113 - 114 - return $this->buildApplicationPage( 115 - $nav, 116 - array( 117 - 'title' => pht('Herald'), 118 - 'dust' => true, 119 - 'device' => true, 120 - )); 121 - } 122 - 123 - private function renderAuthorFilter($phid) { 124 - $user = $this->getRequest()->getUser(); 125 - if ($phid) { 126 - $handle = PhabricatorObjectHandleData::loadOneHandle( 127 - $phid, 128 - $user); 129 - $tokens = array( 130 - $phid => $handle->getFullName(), 131 - ); 132 - } else { 133 - $tokens = array(); 134 - } 135 - 136 - $form = id(new AphrontFormView()) 137 - ->setUser($user) 138 - ->setNoShading(true) 139 - ->appendChild( 140 - id(new AphrontFormTokenizerControl()) 141 - ->setName('set_phid') 142 - ->setValue($tokens) 143 - ->setLimit(1) 144 - ->setLabel(pht('Filter Author')) 145 - ->setDataSource('/typeahead/common/accounts/')) 146 - ->appendChild( 147 - id(new AphrontFormSubmitControl()) 148 - ->setValue(pht('Apply Filter'))); 149 - 150 - $filter = new AphrontListFilterView(); 151 - $filter->appendChild($form); 152 - return $filter; 153 - } 154 - 155 - 156 - }
+1 -1
src/applications/herald/controller/HeraldRuleEditHistoryController.php
··· 42 42 ->setName(pht('Edit History')) 43 43 ->setHref($this->getApplicationURI('herald/history'))); 44 44 45 - $nav = $this->renderNav(); 45 + $nav = $this->buildSideNavView(); 46 46 $nav->selectFilter('history'); 47 47 $nav->appendChild($panel); 48 48 $nav->setCrumbs($crumbs);
+78
src/applications/herald/controller/HeraldRuleListController.php
··· 1 + <?php 2 + 3 + final class HeraldRuleListController extends HeraldController 4 + implements PhabricatorApplicationSearchResultsControllerInterface { 5 + 6 + private $queryKey; 7 + 8 + public function shouldAllowPublic() { 9 + return true; 10 + } 11 + 12 + public function willProcessRequest(array $data) { 13 + $this->queryKey = idx($data, 'queryKey'); 14 + } 15 + 16 + public function processRequest() { 17 + $request = $this->getRequest(); 18 + $controller = id(new PhabricatorApplicationSearchController($request)) 19 + ->setQueryKey($this->queryKey) 20 + ->setSearchEngine(new HeraldRuleSearchEngine()) 21 + ->setNavigation($this->buildSideNavView()); 22 + 23 + return $this->delegateToController($controller); 24 + } 25 + 26 + public function renderResultsList( 27 + array $rules, 28 + PhabricatorSavedQuery $query) { 29 + assert_instances_of($rules, 'HeraldRule'); 30 + 31 + $viewer = $this->getRequest()->getUser(); 32 + 33 + $phids = mpull($rules, 'getAuthorPHID'); 34 + $this->loadHandles($phids); 35 + 36 + $content_type_map = HeraldContentTypeConfig::getContentTypeMap(); 37 + 38 + $list = id(new PhabricatorObjectItemListView()) 39 + ->setUser($viewer); 40 + foreach ($rules as $rule) { 41 + $id = $rule->getID(); 42 + 43 + $item = id(new PhabricatorObjectItemView()) 44 + ->setObjectName(pht('Rule %s', $rule->getID())) 45 + ->setHeader($rule->getName()) 46 + ->setHref($this->getApplicationURI("rule/{$id}/")); 47 + 48 + if ($rule->isPersonalRule()) { 49 + $item->addByline( 50 + pht( 51 + 'Authored by %s', 52 + $this->getHandle($rule->getAuthorPHID())->renderLink())); 53 + } else { 54 + $item->addIcon('world', pht('Global Rule')); 55 + } 56 + 57 + $item->addAction( 58 + id(new PHUIListItemView()) 59 + ->setHref($this->getApplicationURI("history/{$id}/")) 60 + ->setIcon('transcript') 61 + ->setName(pht('Edit Log'))); 62 + 63 + $item->addAction( 64 + id(new PHUIListItemView()) 65 + ->setHref('/herald/delete/'.$rule->getID().'/') 66 + ->setIcon('delete') 67 + ->setWorkflow(true)); 68 + 69 + $content_type_name = idx($content_type_map, $rule->getContentType()); 70 + $item->addAttribute(pht('Affects: %s', $content_type_name)); 71 + 72 + $list->addItem($item); 73 + } 74 + 75 + return $list; 76 + } 77 + 78 + }
+1 -1
src/applications/herald/controller/HeraldTestConsoleController.php
··· 113 113 id(new AphrontFormSubmitControl()) 114 114 ->setValue(pht('Test Rules'))); 115 115 116 - $nav = $this->renderNav(); 116 + $nav = $this->buildSideNavView(); 117 117 $nav->selectFilter('test'); 118 118 $nav->appendChild( 119 119 array(
+1 -1
src/applications/herald/controller/HeraldTranscriptListController.php
··· 95 95 $panel->appendChild($pager); 96 96 $panel->setNoBackground(); 97 97 98 - $nav = $this->renderNav(); 98 + $nav = $this->buildSideNavView(); 99 99 $nav->selectFilter('transcript'); 100 100 $nav->appendChild($panel); 101 101
+129
src/applications/herald/query/HeraldRuleSearchEngine.php
··· 1 + <?php 2 + 3 + final class HeraldRuleSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function buildSavedQueryFromRequest(AphrontRequest $request) { 7 + $saved = new PhabricatorSavedQuery(); 8 + 9 + $saved->setParameter( 10 + 'authorPHIDs', 11 + array_values($request->getArr('authors'))); 12 + 13 + $saved->setParameter('contentType', $request->getStr('contentType')); 14 + $saved->setParameter('ruleType', $request->getStr('ruleType')); 15 + 16 + return $saved; 17 + } 18 + 19 + public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { 20 + $query = id(new HeraldRuleQuery()); 21 + 22 + $author_phids = $saved->getParameter('authorPHIDs'); 23 + if ($author_phids) { 24 + $query->withAuthorPHIDs($author_phids); 25 + } 26 + 27 + $content_type = $saved->getParameter('contentType'); 28 + $content_type = idx($this->getContentTypeValues(), $content_type); 29 + if ($content_type) { 30 + $query->withContentTypes(array($content_type)); 31 + } 32 + 33 + $rule_type = $saved->getParameter('ruleType'); 34 + $rule_type = idx($this->getRuleTypeValues(), $rule_type); 35 + if ($rule_type) { 36 + $query->withRuleTypes(array($rule_type)); 37 + } 38 + 39 + return $query; 40 + } 41 + 42 + public function buildSearchForm( 43 + AphrontFormView $form, 44 + PhabricatorSavedQuery $saved_query) { 45 + 46 + $phids = $saved_query->getParameter('authorPHIDs', array()); 47 + $handles = id(new PhabricatorObjectHandleData($phids)) 48 + ->setViewer($this->requireViewer()) 49 + ->loadHandles(); 50 + $author_tokens = mpull($handles, 'getFullName', 'getPHID'); 51 + 52 + $content_type = $saved_query->getParameter('contentType'); 53 + $rule_type = $saved_query->getParameter('ruleType'); 54 + 55 + $form 56 + ->appendChild( 57 + id(new AphrontFormTokenizerControl()) 58 + ->setDatasource('/typeahead/common/users/') 59 + ->setName('authors') 60 + ->setLabel(pht('Authors')) 61 + ->setValue($author_tokens)) 62 + ->appendChild( 63 + id(new AphrontFormSelectControl()) 64 + ->setName('contentType') 65 + ->setLabel(pht('Content Type')) 66 + ->setValue($content_type) 67 + ->setOptions($this->getContentTypeOptions())) 68 + ->appendChild( 69 + id(new AphrontFormSelectControl()) 70 + ->setName('ruleType') 71 + ->setLabel(pht('Rule Type')) 72 + ->setValue($rule_type) 73 + ->setOptions($this->getRuleTypeOptions())); 74 + } 75 + 76 + protected function getURI($path) { 77 + return '/herald/'.$path; 78 + } 79 + 80 + public function getBuiltinQueryNames() { 81 + $names = array(); 82 + 83 + if ($this->requireViewer()->isLoggedIn()) { 84 + $names['authored'] = pht('Authored'); 85 + } 86 + 87 + $names['all'] = pht('All'); 88 + 89 + return $names; 90 + } 91 + 92 + public function buildSavedQueryFromBuiltin($query_key) { 93 + 94 + $query = $this->newSavedQuery(); 95 + $query->setQueryKey($query_key); 96 + 97 + switch ($query_key) { 98 + case 'all': 99 + return $query; 100 + case 'authored': 101 + return $query->setParameter( 102 + 'authorPHIDs', 103 + array($this->requireViewer()->getPHID())); 104 + } 105 + 106 + return parent::buildSavedQueryFromBuiltin($query_key); 107 + } 108 + 109 + private function getContentTypeOptions() { 110 + return array( 111 + '' => pht('(All Content Types)'), 112 + ) + HeraldContentTypeConfig::getContentTypeMap(); 113 + } 114 + 115 + private function getContentTypeValues() { 116 + return HeraldContentTypeConfig::getContentTypeMap(); 117 + } 118 + 119 + private function getRuleTypeOptions() { 120 + return array( 121 + '' => pht('(All Rule Types)'), 122 + ) + HeraldRuleTypeConfig::getRuleTypeMap(); 123 + } 124 + 125 + private function getRuleTypeValues() { 126 + return HeraldRuleTypeConfig::getRuleTypeMap(); 127 + } 128 + 129 + }
-83
src/applications/herald/view/HeraldRuleListView.php
··· 1 - <?php 2 - 3 - final class HeraldRuleListView extends AphrontView { 4 - 5 - private $rules; 6 - private $handles; 7 - 8 - private $showAuthor; 9 - private $showRuleType; 10 - 11 - public function setRules(array $rules) { 12 - assert_instances_of($rules, 'HeraldRule'); 13 - $this->rules = $rules; 14 - return $this; 15 - } 16 - 17 - public function setHandles(array $handles) { 18 - assert_instances_of($handles, 'PhabricatorObjectHandle'); 19 - $this->handles = $handles; 20 - return $this; 21 - } 22 - 23 - public function setShowAuthor($show_author) { 24 - $this->showAuthor = $show_author; 25 - return $this; 26 - } 27 - 28 - public function setShowRuleType($show_rule_type) { 29 - $this->showRuleType = $show_rule_type; 30 - return $this; 31 - } 32 - 33 - public function render() { 34 - 35 - $type_map = HeraldRuleTypeConfig::getRuleTypeMap(); 36 - 37 - $list = new PhabricatorObjectItemListView(); 38 - $list->setFlush(true); 39 - $list->setCards(true); 40 - foreach ($this->rules as $rule) { 41 - 42 - if ($rule->getRuleType() == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) { 43 - $author = pht('Global Rule'); 44 - } else { 45 - $author = $this->handles[$rule->getAuthorPHID()]->renderLink(); 46 - $author = pht('Editor: %s', $author); 47 - } 48 - 49 - $edit_log = phutil_tag( 50 - 'a', 51 - array( 52 - 'href' => '/herald/history/'.$rule->getID().'/', 53 - ), 54 - pht('View Edit Log')); 55 - 56 - $delete = javelin_tag( 57 - 'a', 58 - array( 59 - 'href' => '/herald/delete/'.$rule->getID().'/', 60 - 'sigil' => 'workflow', 61 - ), 62 - pht('Delete')); 63 - 64 - $item = id(new PhabricatorObjectItemView()) 65 - ->setObjectName($type_map[$rule->getRuleType()]) 66 - ->setHeader($rule->getName()) 67 - ->setHref('/herald/rule/'.$rule->getID().'/') 68 - ->addAttribute($edit_log) 69 - ->addIcon('none', $author) 70 - ->addAction( 71 - id(new PHUIListItemView()) 72 - ->setHref('/herald/delete/'.$rule->getID().'/') 73 - ->setIcon('delete') 74 - ->setWorkflow(true)); 75 - 76 - $list->addItem($item); 77 - } 78 - 79 - $list->setNoDataString(pht("No matching rules.")); 80 - 81 - return $list; 82 - } 83 - }