@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.

DifferentialRevisionList

+506 -14
+3 -3
src/__celerity_resource_map__.php
··· 17 17 ), 18 18 'aphront-form-view-css' => 19 19 array( 20 - 'path' => '/res/75636a53/rsrc/css/aphront/form-view.css', 20 + 'path' => '/res/785ac1c6/rsrc/css/aphront/form-view.css', 21 21 'type' => 'css', 22 22 'requires' => 23 23 array( ··· 33 33 ), 34 34 'aphront-side-nav-view-css' => 35 35 array( 36 - 'path' => '/res/1a16f19a/rsrc/css/aphront/side-nav-view.css', 36 + 'path' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css', 37 37 'type' => 'css', 38 38 'requires' => 39 39 array( ··· 66 66 ), 67 67 'phabricator-standard-page-view' => 68 68 array( 69 - 'path' => '/res/0eef6905/rsrc/css/application/base/standard-page-view.css', 69 + 'path' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css', 70 70 'type' => 'css', 71 71 'requires' => 72 72 array(
+2
src/__phutil_library_map__.php
··· 89 89 'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit', 90 90 'DifferentialRevisionEditor' => 'applications/differential/editor/revision', 91 91 'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist', 92 + 'DifferentialRevisionListData' => 'applications/differential/data/revisionlist', 92 93 'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus', 93 94 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 94 95 'Javelin' => 'infratructure/javelin/api', ··· 169 170 'require_celerity_resource' => 'infratructure/celerity/api', 170 171 'vqsprintf' => 'storage/qsprintf', 171 172 'vqueryfx' => 'storage/queryfx', 173 + 'vqueryfx_all' => 'storage/queryfx', 172 174 'xsprintf_query' => 'storage/qsprintf', 173 175 ), 174 176 'requires_class' =>
+1
src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
··· 79 79 80 80 '/differential/' => array( 81 81 '$' => 'DifferentialRevisionListController', 82 + 'filter/(?<filter>\w+)/$' => 'DifferentialRevisionListController', 82 83 'diff/(?<id>\d+)/$' => 'DifferentialDiffViewController', 83 84 'changeset/(?<id>\d+)/$' => 'DifferentialChangesetViewController', 84 85 'revision/edit/(?:(?<id>\d+)/)?$'
+17 -4
src/aphront/response/base/AphrontResponse.php
··· 22 22 abstract class AphrontResponse { 23 23 24 24 private $request; 25 + private $cacheable = false; 25 26 26 27 public function setRequest($request) { 27 28 $this->request = $request; ··· 35 36 public function getHeaders() { 36 37 return array(); 37 38 } 39 + 40 + public function setCacheDurationInSeconds($duration) { 41 + $this->cacheable = $duration; 42 + return $this; 43 + } 38 44 39 45 public function getCacheHeaders() { 40 - return array( 41 - array('Cache-Control', 'private, no-cache, no-store, must-revalidate'), 42 - array('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT'), 43 - ); 46 + if ($this->cacheable) { 47 + $epoch = time() + $this->cacheable; 48 + return array( 49 + array('Expires', gmdate('D, d M Y H:i:s', $epoch) . ' GMT'), 50 + ); 51 + } else { 52 + return array( 53 + array('Cache-Control', 'private, no-cache, no-store, must-revalidate'), 54 + array('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT'), 55 + ); 56 + } 44 57 } 45 58 46 59 abstract public function buildResponseString();
+157 -7
src/applications/differential/controller/revisionlist/DifferentialRevisionListController.php
··· 18 18 19 19 class DifferentialRevisionListController extends DifferentialController { 20 20 21 + private $filter; 22 + 23 + public function willProcessRequest(array $data) { 24 + $this->filter = idx($data, 'filter'); 25 + } 26 + 21 27 public function processRequest() { 22 28 23 - $side_nav = new AphrontSideNavView(); 24 - $side_nav->addNavItem( 25 - phutil_render_tag( 26 - 'a', 27 - array( 28 - 'href' => '/differential/', 29 + $filters = array( 30 + 'active' => array( 31 + 'name' => 'Active Revisions', 32 + 'queries' => array( 33 + array( 34 + 'query' 35 + => DifferentialRevisionListData::QUERY_NEED_ACTION_FROM_SELF, 36 + 'header' => 'Action Required', 37 + 'nodata' => 'You have no revisions requiring action.', 38 + ), 39 + array( 40 + 'query' 41 + => DifferentialRevisionListData::QUERY_NEED_ACTION_FROM_OTHERS, 42 + 'header' => 'Waiting on Others', 43 + 'nodata' => 'You have no revisions waiting on others', 44 + ), 29 45 ), 30 - 'Active Revisions')); 46 + ), 47 + 'open' => array( 48 + 'name' => 'Open Revisions', 49 + 'queries' => array( 50 + array( 51 + 'query' => DifferentialRevisionListData::QUERY_OPEN_OWNED, 52 + 'header' => 'Open Revisions', 53 + ), 54 + ), 55 + ), 56 + 'reviews' => array( 57 + 'name' => 'Open Reviews', 58 + 'queries' => array( 59 + array( 60 + 'query' => DifferentialRevisionListData::QUERY_OPEN_REVIEWER, 61 + 'header' => 'Open Reviews', 62 + ), 63 + ), 64 + ), 65 + 'all' => array( 66 + 'name' => 'All Revisions', 67 + 'queries' => array( 68 + array( 69 + 'query' => DifferentialRevisionListData::QUERY_OWNED, 70 + 'header' => 'All Revisions', 71 + ), 72 + ), 73 + ), 74 + 'related' => array( 75 + 'name' => 'All Revisions and Reviews', 76 + 'queries' => array( 77 + array( 78 + 'query' => DifferentialRevisionListData::QUERY_OWNED_OR_REVIEWER, 79 + 'header' => 'All Revisions and Reviews', 80 + ), 81 + ), 82 + ), 83 + ); 31 84 85 + if (empty($filters[$this->filter])) { 86 + $this->filter = key($filters); 87 + } 88 + 89 + $request = $this->getRequest(); 90 + $user = $request->getUser(); 91 + 92 + $queries = array(); 93 + $filter = $filters[$this->filter]; 94 + foreach ($filter['queries'] as $query) { 95 + $query_object = new DifferentialRevisionListData( 96 + $query['query'], 97 + array($user->getPHID())); 98 + $queries[] = array( 99 + 'object' => $query_object, 100 + ) + $query; 101 + } 102 + 103 + $side_nav = new AphrontSideNavView(); 104 + foreach ($filters as $filter_name => $filter_desc) { 105 + $selected = ($filter_name == $this->filter); 106 + $side_nav->addNavItem( 107 + phutil_render_tag( 108 + 'a', 109 + array( 110 + 'href' => '/differential/filter/'.$filter_name.'/', 111 + 'class' => $selected ? 'aphront-side-nav-selected' : null, 112 + ), 113 + phutil_escape_html($filter_desc['name']))); 114 + } 115 + 116 + foreach ($queries as $query) { 117 + $table = $this->renderRevisionTable( 118 + $query['object']->loadRevisions(), 119 + $query['header'], 120 + idx($query, 'nodata')); 121 + $side_nav->appendChild($table); 122 + } 32 123 33 124 return $this->buildStandardPageResponse( 34 125 $side_nav, 35 126 array( 36 127 'title' => 'Differential Home', 37 128 )); 129 + } 130 + 131 + private function renderRevisionTable(array $revisions, $header, $nodata) { 132 + 133 + $rows = array(); 134 + foreach ($revisions as $revision) { 135 + $status = DifferentialRevisionStatus::getNameForRevisionStatus( 136 + $revision->getStatus()); 137 + 138 + $rows[] = array( 139 + 'D'.$revision->getID(), 140 + phutil_render_tag( 141 + 'a', 142 + array( 143 + 'href' => '/D'.$revision->getID(), 144 + ), 145 + phutil_escape_html($revision->getTitle())), 146 + phutil_escape_html($status), 147 + number_format($revision->getLineCount()), 148 + $revision->getOwnerPHID(), 149 + 'TODO', 150 + $revision->getDateModified(), 151 + $revision->getDateCreated(), 152 + ); 153 + } 154 + 155 + $table = new AphrontTableView($rows); 156 + $table->setHeaders( 157 + array( 158 + 'ID', 159 + 'Revision', 160 + 'Status', 161 + 'Lines', 162 + 'Author', 163 + 'Reviewers', 164 + 'Updated', 165 + 'Created', 166 + )); 167 + $table->setColumnClasses( 168 + array( 169 + null, 170 + 'wide', 171 + null, 172 + null, 173 + null, 174 + null, 175 + null, 176 + null, 177 + )); 178 + if ($nodata !== null) { 179 + $table->setNoDataString($nodata); 180 + } 181 + 182 + 183 + $panel = new AphrontPanelView(); 184 + $panel->setHeader($header); 185 + $panel->appendChild($table); 186 + 187 + return $panel; 38 188 } 39 189 40 190 }
+5
src/applications/differential/controller/revisionlist/__init__.php
··· 6 6 7 7 8 8 9 + phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus'); 9 10 phutil_require_module('phabricator', 'applications/differential/controller/base'); 11 + phutil_require_module('phabricator', 'applications/differential/data/revisionlist'); 12 + phutil_require_module('phabricator', 'view/control/table'); 13 + phutil_require_module('phabricator', 'view/layout/panel'); 10 14 phutil_require_module('phabricator', 'view/layout/sidenav'); 11 15 12 16 phutil_require_module('phutil', 'markup'); 17 + phutil_require_module('phutil', 'utils'); 13 18 14 19 15 20 phutil_require_source('DifferentialRevisionListController.php');
+296
src/applications/differential/data/revisionlist/DifferentialRevisionListData.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DifferentialRevisionListData { 20 + 21 + const QUERY_OPEN_OWNED = 'open'; 22 + const QUERY_OPEN_REVIEWER = 'reviewer'; 23 + const QUERY_OWNED = 'owned'; 24 + const QUERY_OWNED_OR_REVIEWER = 'related'; 25 + const QUERY_NEED_ACTION_FROM_OTHERS = 'need-other-action'; 26 + const QUERY_NEED_ACTION_FROM_SELF = 'need-self-action'; 27 + const QUERY_COMMITTABLE = 'committable'; 28 + const QUERY_REVISION_IDS = 'revision-ids'; 29 + const QUERY_PHIDS = 'phids'; 30 + const QUERY_CC = 'cc'; 31 + const QUERY_ALL_OPEN = 'all-open'; 32 + 33 + private $ids; 34 + private $filter; 35 + private $handles; 36 + private $revisions; 37 + private $order; 38 + 39 + public function __construct($filter, array $ids) { 40 + $this->filter = $filter; 41 + $this->ids = $ids; 42 + } 43 + 44 + public function getRevisions() { 45 + return $this->revisions; 46 + } 47 + 48 + public function setOrder($order) { 49 + $this->order = $order; 50 + return $this; 51 + } 52 + 53 + public function loadRevisions() { 54 + switch ($this->filter) { 55 + case self::QUERY_CC: 56 + $this->revisions = $this->loadAllOpenWithCCs($this->ids); 57 + break; 58 + case self::QUERY_ALL_OPEN: 59 + $this->revisions = $this->loadAllOpen(); 60 + break; 61 + case self::QUERY_OPEN_OWNED: 62 + $this->revisions = $this->loadAllWhere( 63 + 'revision.status in (%Ld) AND revision.ownerPHID in (%Ls)', 64 + $this->getOpenStatuses(), 65 + $this->ids); 66 + break; 67 + case self::QUERY_COMMITTABLE: 68 + $this->revisions = $this->loadAllWhere( 69 + 'revision.status in (%Ld) AND revision.ownerPHID in (%Ls)', 70 + array( 71 + DifferentialRevisionStatus::ACCEPTED, 72 + ), 73 + $this->ids); 74 + break; 75 + case self::QUERY_REVISION_IDS: 76 + $this->revisions = $this->loadAllWhere( 77 + 'id in (%Ld)', 78 + $this->ids); 79 + break; 80 + case self::QUERY_OPEN_REVIEWER: 81 + $this->revisions = $this->loadAllWhereJoinReview( 82 + 'revision.status in (%Ld) AND relationship.objectPHID in (%Ls)', 83 + $this->getOpenStatuses(), 84 + $this->ids); 85 + break; 86 + case self::QUERY_OWNED: 87 + $this->revisions = $this->loadAllWhere( 88 + 'revision.ownerPHID in (%Ls)', 89 + $this->ids); 90 + break; 91 + case self::QUERY_OWNED_OR_REVIEWER: 92 + $this->revisions = $this->loadAllWhereJoinReview( 93 + 'revision.ownerPHID in (%Ls) OR relationship.objectPHID in (%Ls)', 94 + $this->ids, 95 + $this->ids); 96 + break; 97 + case self::QUERY_NEED_ACTION_FROM_SELF: 98 + $rev = new DifferentialRevision(); 99 + $data = queryfx_all( 100 + $rev->establishConnection('r'), 101 + 'SELECT revision.* FROM %T revision 102 + WHERE revision.ownerPHID in (%Ls) 103 + AND revision.status in (%Ld) 104 + 105 + UNION ALL 106 + 107 + SELECT revision.* FROM %T revision JOIN %T relationship 108 + ON relationship.revisionID = revision.id 109 + AND relationship.relation = %s 110 + AND relationship.forbidden = 0 111 + WHERE relationship.objectPHID IN (%Ls) 112 + AND revision.status in (%Ld) 113 + 114 + %Q', 115 + $rev->getTableName(), 116 + $this->ids, 117 + array( 118 + DifferentialRevisionStatus::NEEDS_REVISION, 119 + DifferentialRevisionStatus::ACCEPTED, 120 + ), 121 + $rev->getTableName(), 122 + DifferentialRevision::RELATIONSHIP_TABLE, 123 + DifferentialRevision::RELATION_REVIEWER, 124 + $this->ids, 125 + array( 126 + DifferentialRevisionStatus::NEEDS_REVIEW, 127 + ), 128 + $this->getOrderClause()); 129 + 130 + $data = ipull($data, null, 'id'); 131 + $this->revisions = $rev->loadAllFromArray($data); 132 + break; 133 + case self::QUERY_NEED_ACTION_FROM_OTHERS: 134 + $rev = new DifferentialRevision(); 135 + $data = queryfx_all( 136 + $rev->establishConnection('r'), 137 + 'SELECT revision.* FROM %T revision 138 + WHERE revision.ownerPHID in (%Ls) 139 + AND revision.status IN (%Ld) 140 + 141 + UNION ALL 142 + 143 + SELECT revision.* FROM %T revision JOIN %T relationship 144 + ON relationship.revisionID = revision.id 145 + AND relationship.relation = %s 146 + AND relationship.forbidden = 0 147 + WHERE relationship.objectPHID IN (%Ls) 148 + AND revision.status in (%Ld) 149 + 150 + %Q', 151 + $rev->getTableName(), 152 + $this->ids, 153 + array( 154 + DifferentialRevisionStatus::NEEDS_REVIEW, 155 + ), 156 + $rev->getTableName(), 157 + DifferentialRevision::RELATIONSHIP_TABLE, 158 + DifferentialRevision::RELATION_REVIEWER, 159 + $this->ids, 160 + array( 161 + DifferentialRevisionStatus::NEEDS_REVISION, 162 + DifferentialRevisionStatus::ACCEPTED, 163 + ), 164 + $this->getOrderClause()); 165 + 166 + $data = ipull($data, null, 'id'); 167 + 168 + $this->revisions = $rev->loadAllFromArray($data); 169 + break; 170 + case self::QUERY_BY_PHID: 171 + $this->revisions = $this->loadAllWhere( 172 + 'revision.phid in (%Ls)', 173 + $this->ids); 174 + break; 175 + } 176 + 177 + return $this->revisions; 178 + } 179 + 180 + private function getOpenStatuses() { 181 + return array( 182 + DifferentialRevisionStatus::NEEDS_REVIEW, 183 + DifferentialRevisionStatus::NEEDS_REVISION, 184 + DifferentialRevisionStatus::ACCEPTED, 185 + ); 186 + } 187 + 188 + private function loadAllOpen() { 189 + return $this->loadAllWhere('status in (%Ld)', $this->getOpenStatuses()); 190 + } 191 + 192 + private function loadAllWhereJoinReview($pattern) { 193 + $reviewer = DifferentialRevision::RELATION_REVIEWER; 194 + 195 + $argv = func_get_args(); 196 + 197 + $rev = new DifferentialRevision(); 198 + 199 + $pattern = array_shift($argv); 200 + $pattern = 201 + 'SELECT revision.* 202 + FROM %T revision LEFT JOIN %T relationship 203 + ON revision.id = relationship.revisionID 204 + AND relationship.relation = %s 205 + AND relationship.forbidden = 0 206 + WHERE '.$pattern.' 207 + GROUP BY revision.id '.$this->getOrderClause(); 208 + 209 + array_unshift( 210 + $argv, 211 + $rev->getTableName(), 212 + DifferentialRevision::RELATIONSHIP_TABLE, 213 + DifferentialRevision::RELATION_REVIEWER); 214 + 215 + $data = vqueryfx_all( 216 + $rev->establishConnection('r'), 217 + $pattern, 218 + $argv); 219 + 220 + return $rev->loadAllFromArray($data); 221 + } 222 + 223 + private function loadAllWhere($pattern) { 224 + $rev = new DifferentialRevision(); 225 + 226 + $argv = func_get_args(); 227 + array_shift($argv); 228 + array_unshift($argv, $rev->getTableName()); 229 + 230 + $data = vqueryfx_all( 231 + $rev->establishConnection('r'), 232 + 'SELECT * FROM %T revision WHERE '.$pattern, 233 + $argv); 234 + 235 + return $rev->loadAllFromArray($data); 236 + } 237 + 238 + private function loadAllOpenWithCCs(array $ccphids) { 239 + $revision = new DifferentialRevision(); 240 + $data = queryfx_all( 241 + 'SELECT revision.* FROM %T revision 242 + JOIN %T relationship ON relationship.revisionID = revision.id 243 + AND relationship.relation = %s 244 + AND relationship.forbidden = 0 245 + AND relationship.objectPHID in (%Ls) 246 + WHERE revision.status in (%Ld) %Q', 247 + $revision->getTableName(), 248 + DifferentialRevision::RELATIONSHIP_TABLE, 249 + DifferentialRevision::RELATION_SUBSCRIBED, 250 + $ccphids, 251 + $this->getOpenStatuses(), 252 + $this->getOrderClause()); 253 + return $revision->loadAllFromArray($data); 254 + } 255 + 256 + private function getOrderClause() { 257 + $reverse = false; 258 + $order = $this->order; 259 + 260 + if (strlen($order) && $order[0] == '-') { 261 + $reverse = true; 262 + $order = substr($order, 1); 263 + } 264 + 265 + $asc = $reverse ? 'DESC' : 'ASC'; 266 + 267 + switch ($order) { 268 + case 'ID': 269 + $clause = 'id'; 270 + break; 271 + case 'Revision': 272 + $clause = 'name'; 273 + break; 274 + case 'Status': 275 + $clause = 'status'; 276 + break; 277 + case 'Lines': 278 + $clause = 'lineCount'; 279 + break; 280 + case 'Created': 281 + $clause = 'dateCreated'; 282 + $asc = $reverse ? 'ASC' : 'DESC'; 283 + break; 284 + case '': 285 + case 'Modified': 286 + $clause = 'dateModified'; 287 + $asc = $reverse ? 'ASC' : 'DESC'; 288 + break; 289 + default: 290 + throw new Exception("Invalid order '{$order}'."); 291 + } 292 + 293 + return "ORDER BY {$clause} {$asc}"; 294 + } 295 + 296 + }
+16
src/applications/differential/data/revisionlist/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus'); 10 + phutil_require_module('phabricator', 'applications/differential/storage/revision'); 11 + phutil_require_module('phabricator', 'storage/queryfx'); 12 + 13 + phutil_require_module('phutil', 'utils'); 14 + 15 + 16 + phutil_require_source('DifferentialRevisionListData.php');
+2
src/infratructure/celerity/controller/CelerityResourceController.php
··· 57 57 $response->setMimeType("text/javascript; charset=utf-8"); 58 58 break; 59 59 } 60 + 61 + $response->setCacheDurationInSeconds(60 * 60 * 24 * 30); 60 62 61 63 return $response; 62 64 }
+6
src/storage/queryfx/queryfx.php
··· 56 56 } 57 57 return null; 58 58 } 59 + 60 + function vqueryfx_all($conn, $sql, array $argv) { 61 + array_unshift($argv, $conn, $sql); 62 + $ret = call_user_func_array('queryfx', $argv); 63 + return $conn->selectAllResults($ret); 64 + }
+1
webroot/rsrc/css/aphront/side-nav-view.css
··· 4 4 5 5 table.aphront-side-nav-view { 6 6 width: 100%; 7 + font-size: 13px; 7 8 } 8 9 9 10 td.aphront-side-nav-content {