@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
at recaptime-dev/main 210 lines 6.0 kB view raw
1<?php 2 3final class PonderQuestionSearchEngine 4 extends PhabricatorApplicationSearchEngine { 5 6 public function getResultTypeDescription() { 7 return pht('Ponder Questions'); 8 } 9 10 public function getApplicationClassName() { 11 return PhabricatorPonderApplication::class; 12 } 13 14 public function newQuery() { 15 return id(new PonderQuestionQuery()) 16 ->needProjectPHIDs(true); 17 } 18 19 protected function buildQueryFromParameters(array $map) { 20 $query = $this->newQuery(); 21 22 if ($map['authorPHIDs']) { 23 $query->withAuthorPHIDs($map['authorPHIDs']); 24 } 25 26 if ($map['answerers']) { 27 $query->withAnswererPHIDs($map['answerers']); 28 } 29 30 if ($map['statuses']) { 31 $query->withStatuses($map['statuses']); 32 } 33 34 return $query; 35 } 36 37 protected function buildCustomSearchFields() { 38 return array( 39 id(new PhabricatorUsersSearchField()) 40 ->setKey('authorPHIDs') 41 ->setAliases(array('authors')) 42 ->setLabel(pht('Authors')), 43 id(new PhabricatorUsersSearchField()) 44 ->setKey('answerers') 45 ->setAliases(array('answerers')) 46 ->setLabel(pht('Answered By')), 47 id(new PhabricatorSearchCheckboxesField()) 48 ->setLabel(pht('Status')) 49 ->setKey('statuses') 50 ->setOptions(PonderQuestionStatus::getQuestionStatusMap()), 51 ); 52 } 53 54 protected function getURI($path) { 55 return '/ponder/'.$path; 56 } 57 58 protected function getBuiltinQueryNames() { 59 $names = array( 60 'recent' => pht('Recent Questions'), 61 'open' => pht('Open Questions'), 62 'resolved' => pht('Resolved Questions'), 63 'all' => pht('All Questions'), 64 ); 65 66 if ($this->requireViewer()->isLoggedIn()) { 67 $names['authored'] = pht('Authored'); 68 $names['answered'] = pht('Answered'); 69 } 70 71 return $names; 72 } 73 74 public function buildSavedQueryFromBuiltin($query_key) { 75 $query = $this->newSavedQuery(); 76 $query->setQueryKey($query_key); 77 78 switch ($query_key) { 79 case 'all': 80 return $query; 81 case 'open': 82 return $query->setParameter( 83 'statuses', array(PonderQuestionStatus::STATUS_OPEN)); 84 case 'recent': 85 return $query->setParameter( 86 'statuses', array( 87 PonderQuestionStatus::STATUS_OPEN, 88 PonderQuestionStatus::STATUS_CLOSED_RESOLVED, 89 )); 90 case 'resolved': 91 return $query->setParameter( 92 'statuses', array(PonderQuestionStatus::STATUS_CLOSED_RESOLVED)); 93 case 'authored': 94 return $query->setParameter( 95 'authorPHIDs', 96 array($this->requireViewer()->getPHID())); 97 case 'answered': 98 return $query->setParameter( 99 'answerers', 100 array($this->requireViewer()->getPHID())); 101 } 102 103 return parent::buildSavedQueryFromBuiltin($query_key); 104 } 105 106 protected function getRequiredHandlePHIDsForResultList( 107 array $questions, 108 PhabricatorSavedQuery $query) { 109 return mpull($questions, 'getAuthorPHID'); 110 } 111 112 /** 113 * @param array<PonderQuestion> $questions 114 * @param PhabricatorSavedQuery $query 115 * @param array<PhabricatorObjectHandle> $handles 116 */ 117 protected function renderResultList( 118 array $questions, 119 PhabricatorSavedQuery $query, 120 array $handles) { 121 assert_instances_of($questions, PonderQuestion::class); 122 123 $viewer = $this->requireViewer(); 124 125 $proj_phids = array(); 126 foreach ($questions as $question) { 127 foreach ($question->getProjectPHIDs() as $project_phid) { 128 $proj_phids[] = $project_phid; 129 } 130 } 131 132 $proj_handles = id(new PhabricatorHandleQuery()) 133 ->setViewer($viewer) 134 ->withPHIDs($proj_phids) 135 ->execute(); 136 137 $view = id(new PHUIObjectItemListView()) 138 ->setUser($viewer); 139 140 foreach ($questions as $question) { 141 $color = PonderQuestionStatus::getQuestionStatusTagColor( 142 $question->getStatus()); 143 $icon = PonderQuestionStatus::getQuestionStatusIcon( 144 $question->getStatus()); 145 $full_status = PonderQuestionStatus::getQuestionStatusFullName( 146 $question->getStatus()); 147 $item = new PHUIObjectItemView(); 148 $item->setObjectName('Q'.$question->getID()); 149 $item->setHeader($question->getTitle()); 150 $item->setHref('/Q'.$question->getID()); 151 $item->setObject($question); 152 $item->setStatusIcon($icon.' '.$color, $full_status); 153 154 $project_handles = array_select_keys( 155 $proj_handles, 156 $question->getProjectPHIDs()); 157 158 $created_date = phabricator_date($question->getDateCreated(), $viewer); 159 $item->addIcon('none', $created_date); 160 $item->addByline( 161 pht( 162 'Asked by %s', 163 $handles[$question->getAuthorPHID()]->renderLink())); 164 165 // Render Closed Questions as striked in query results 166 $item->setDisabled($question->isStatusClosed()); 167 168 $item->addAttribute( 169 pht( 170 '%s Answer(s)', 171 new PhutilNumber($question->getAnswerCount()))); 172 173 if ($project_handles) { 174 $item->addAttribute( 175 id(new PHUIHandleTagListView()) 176 ->setLimit(4) 177 ->setSlim(true) 178 ->setHandles($project_handles)); 179 } 180 181 $view->addItem($item); 182 } 183 184 $result = new PhabricatorApplicationSearchResultView(); 185 $result->setObjectList($view); 186 $result->setNoDataString(pht('No questions found.')); 187 188 return $result; 189 } 190 191 protected function getNewUserBody() { 192 $create_button = id(new PHUIButtonView()) 193 ->setTag('a') 194 ->setText(pht('Ask a Question')) 195 ->setHref('/ponder/question/create/') 196 ->setColor(PHUIButtonView::GREEN); 197 198 $icon = $this->getApplication()->getIcon(); 199 $app_name = $this->getApplication()->getName(); 200 $view = id(new PHUIBigInfoView()) 201 ->setIcon($icon) 202 ->setTitle(pht('Welcome to %s', $app_name)) 203 ->setDescription( 204 pht('A simple questions and answers application for your teams.')) 205 ->addAction($create_button); 206 207 return $view; 208 } 209 210}