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

Make Flags policy aware

Summary:
Ref T1809. Ref T603. Ref T3599. Makes flags policy aware.

This change reduces the utility of flag search/browse; the next change will switch it to ApplicationSearch to restore utility. Representing all that ordering in terms of cursor paging is also a giant pain.

Test Plan: Viewed Differential, Flags, etc. Grepped for all PhabricatorFlagQuery callsites.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T603, T1809, T3599

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

+83 -206
+6 -1
src/__phutil_library_map__.php
··· 3251 3251 'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow', 3252 3252 'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow', 3253 3253 'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow', 3254 - 'PhabricatorFlag' => 'PhabricatorFlagDAO', 3254 + 'PhabricatorFlag' => 3255 + array( 3256 + 0 => 'PhabricatorFlagDAO', 3257 + 1 => 'PhabricatorPolicyInterface', 3258 + ), 3255 3259 'PhabricatorFlagColor' => 'PhabricatorFlagConstants', 3256 3260 'PhabricatorFlagController' => 'PhabricatorController', 3257 3261 'PhabricatorFlagDAO' => 'PhabricatorLiskDAO', ··· 3259 3263 'PhabricatorFlagEditController' => 'PhabricatorFlagController', 3260 3264 'PhabricatorFlagListController' => 'PhabricatorFlagController', 3261 3265 'PhabricatorFlagListView' => 'AphrontView', 3266 + 'PhabricatorFlagQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3262 3267 'PhabricatorFlagsUIEventListener' => 'PhutilEventListener', 3263 3268 'PhabricatorFormExample' => 'PhabricatorUIExample', 3264 3269 'PhabricatorGarbageCollectorConfigOptions' => 'PhabricatorApplicationConfigOptions',
+7 -80
src/applications/flag/controller/PhabricatorFlagListController.php
··· 19 19 ->setHref($request->getRequestURI())); 20 20 $nav->setCrumbs($crumbs); 21 21 22 - $filter_form = new AphrontFormView(); 23 - $filter_form->setNoShading(true); 24 - $filter_form->setUser($user); 25 - $filter_form->appendChild( 26 - id(new AphrontFormToggleButtonsControl()) 27 - ->setName('o') 28 - ->setLabel(pht('Sort Order')) 29 - ->setBaseURI($request->getRequestURI(), 'o') 30 - ->setValue($flag_order) 31 - ->setButtons( 32 - array( 33 - 'n' => pht('Date'), 34 - 'c' => pht('Color'), 35 - 'o' => pht('Object Type'), 36 - ))); 37 - 38 - $filter = new AphrontListFilterView(); 39 - $filter->appendChild($filter_form); 40 - $nav->appendChild($filter); 41 - 42 22 $query = new PhabricatorFlagQuery(); 43 23 $query->withOwnerPHIDs(array($user->getPHID())); 44 24 $query->setViewer($user); 45 25 $query->needHandles(true); 46 26 47 - switch ($flag_order) { 48 - // 'r' 49 - // 'a' 50 - case 'n': 51 - $order = PhabricatorFlagQuery::ORDER_ID; 52 - break; 53 - case 'c': 54 - $order = PhabricatorFlagQuery::ORDER_COLOR; 55 - break; 56 - case 'o': 57 - $order = PhabricatorFlagQuery::ORDER_OBJECT; 58 - break; 59 - default: 60 - throw new Exception("Unknown order!"); 61 - } 62 - $query->withOrder($order); 63 - 64 27 $flags = $query->execute(); 65 28 66 29 $views = array(); 67 - if ($flag_order == 'n') { 68 - $view = new PhabricatorFlagListView(); 69 - $view->setFlags($flags); 70 - $view->setUser($user); 71 - $view->setFlush(true); 72 - $views[] = array( 73 - 'view' => $view, 74 - ); 75 - } else { 76 - switch ($flag_order) { 77 - case 'c': 78 - $flags_tmp = mgroup($flags, 'getColor'); 79 - $flags = array(); 80 - foreach ($flags_tmp as $color => $flag_group) { 81 - $title = pht('%s Flags', 82 - PhabricatorFlagColor::getColorName($color)); 83 - $flags[$title] = $flag_group; 84 - } 85 - break; 86 - case 'o': 87 - $flags_tmp = mgroup($flags, 'getType'); 88 - $flags = array(); 89 - foreach ($flags_tmp as $color => $flag_group) { 90 - // Appending an 's' to fake plurals 91 - $title = head($flag_group)->getHandle()->getTypeName() . 's'; 92 - $flags[$title] = $flag_group; 93 - } 94 - break; 95 - default: 96 - throw new Exception("Unknown order!"); 97 - } 98 - 99 - foreach ($flags as $group_title => $flag_group) { 100 - $view = new PhabricatorFlagListView(); 101 - $view->setFlags($flag_group); 102 - $view->setUser($user); 103 - $view->setFlush(true); 104 - $views[] = array( 105 - 'title' => pht('%s (%d)', $group_title, count($flag_group)), 106 - 'view' => $view, 107 - ); 108 - } 109 - } 30 + $view = new PhabricatorFlagListView(); 31 + $view->setFlags($flags); 32 + $view->setUser($user); 33 + $view->setFlush(true); 34 + $views[] = array( 35 + 'view' => $view, 36 + ); 110 37 111 38 foreach ($views as $view) { 112 39 $panel = new AphrontPanelView();
+44 -113
src/applications/flag/query/PhabricatorFlagQuery.php
··· 1 1 <?php 2 2 3 - final class PhabricatorFlagQuery { 3 + final class PhabricatorFlagQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 4 5 5 6 private $ownerPHIDs; 6 7 private $types; 7 8 private $objectPHIDs; 8 - private $color; 9 - 10 - private $limit; 11 - private $offset; 9 + private $colors; 12 10 13 11 private $needHandles; 14 12 private $needObjects; 15 - private $viewer; 16 - 17 - private $order = 'order-id'; 18 - const ORDER_ID = 'order-id'; 19 - const ORDER_COLOR = 'order-color'; 20 - const ORDER_OBJECT = 'order-object'; 21 - const ORDER_REASON = 'order-reason'; 22 - 23 - public function setViewer($viewer) { 24 - $this->viewer = $viewer; 25 - return $this; 26 - } 27 13 28 14 public function withOwnerPHIDs(array $owner_phids) { 29 15 $this->ownerPHIDs = $owner_phids; ··· 40 26 return $this; 41 27 } 42 28 43 - public function withColor($color) { 44 - $this->color = $color; 45 - return $this; 46 - } 47 - 48 - public function withOrder($order) { 49 - $this->order = $order; 29 + public function withColors(array $colors) { 30 + $this->colors = $colors; 50 31 return $this; 51 32 } 52 33 ··· 60 41 return $this; 61 42 } 62 43 63 - public function setLimit($limit) { 64 - $this->limit = $limit; 65 - return $this; 66 - } 67 - 68 - public function setOffset($offset) { 69 - $this->offset = $offset; 70 - return $this; 71 - } 72 - 73 44 public static function loadUserFlag(PhabricatorUser $user, $object_phid) { 74 45 // Specifying the type in the query allows us to use a key. 75 - return id(new PhabricatorFlag())->loadOneWhere( 76 - 'ownerPHID = %s AND type = %s AND objectPHID = %s', 77 - $user->getPHID(), 78 - phid_get_type($object_phid), 79 - $object_phid); 46 + return id(new PhabricatorFlagQuery()) 47 + ->setViewer($user) 48 + ->withOwnerPHIDs(array($user->getPHID())) 49 + ->withTypes(array(phid_get_type($object_phid))) 50 + ->withObjectPHIDs(array($object_phid)) 51 + ->executeOne(); 80 52 } 81 53 82 54 83 - public function execute() { 55 + public function loadPage() { 84 56 $table = new PhabricatorFlag(); 85 57 $conn_r = $table->establishConnection('r'); 86 58 87 - $where = $this->buildWhereClause($conn_r); 88 - $limit = $this->buildLimitClause($conn_r); 89 - $order = $this->buildOrderClause($conn_r); 90 - 91 59 $data = queryfx_all( 92 60 $conn_r, 93 61 'SELECT * FROM %T flag %Q %Q %Q', 94 62 $table->getTableName(), 95 - $where, 96 - $order, 97 - $limit); 63 + $this->buildWhereClause($conn_r), 64 + $this->buildOrderClause($conn_r), 65 + $this->buildLimitClause($conn_r)); 98 66 99 - $flags = $table->loadAllFromArray($data); 67 + return $table->loadAllFromArray($data); 68 + } 100 69 101 - if ($this->needHandles || $this->needObjects) { 102 - $phids = ipull($data, 'objectPHID'); 103 - $query = new PhabricatorObjectHandleData($phids); 104 - $query->setViewer($this->viewer); 70 + public function willFilterPage(array $flags) { 105 71 106 - if ($this->needHandles) { 107 - $handles = $query->loadHandles(); 108 - foreach ($flags as $flag) { 109 - $handle = idx($handles, $flag->getObjectPHID()); 110 - if ($handle) { 111 - $flag->attachHandle($handle); 112 - } 72 + if ($this->needObjects) { 73 + $objects = id(new PhabricatorObjectQuery()) 74 + ->setViewer($this->getViewer()) 75 + ->withPHIDs(mpull($flags, 'getObjectPHID')) 76 + ->execute(); 77 + $objects = mpull($objects, null, 'getPHID'); 78 + foreach ($flags as $key => $flag) { 79 + $object = idx($objects, $flag->getObjectPHID()); 80 + if ($object) { 81 + $flags[$key]->attachObject($object); 82 + } else { 83 + unset($flags[$key]); 113 84 } 114 85 } 86 + } 115 87 116 - if ($this->needObjects) { 117 - $objects = $query->loadObjects(); 118 - foreach ($flags as $flag) { 119 - $object = idx($objects, $flag->getObjectPHID()); 120 - if ($object) { 121 - $flag->attachObject($object); 122 - } 123 - } 88 + if ($this->needHandles) { 89 + $handles = id(new PhabricatorHandleQuery()) 90 + ->setViewer($this->getViewer()) 91 + ->withPHIDs(mpull($flags, 'getObjectPHID')) 92 + ->execute(); 93 + 94 + foreach ($flags as $flag) { 95 + $flag->attachHandle($handles[$flag->getObjectPHID()]); 124 96 } 125 97 } 126 98 ··· 128 100 } 129 101 130 102 private function buildWhereClause($conn_r) { 131 - 132 103 $where = array(); 133 104 134 105 if ($this->ownerPHIDs) { ··· 152 123 $this->objectPHIDs); 153 124 } 154 125 155 - if (strlen($this->color)) { 126 + if ($this->colors) { 156 127 $where[] = qsprintf( 157 128 $conn_r, 158 - 'flag.color = %d', 159 - $this->color); 160 - } 161 - 162 - if ($where) { 163 - return 'WHERE ('.implode(') AND (', $where).')'; 164 - } else { 165 - return ''; 129 + 'flag.color IN (%Ld)', 130 + $this->colors); 166 131 } 167 - } 168 132 169 - private function buildOrderClause($conn_r) { 170 - return qsprintf($conn_r, 171 - 'ORDER BY %Q', 172 - $this->getOrderColumn($conn_r)); 173 - } 133 + $where[] = $this->buildPagingClause($conn_r); 174 134 175 - private function getOrderColumn($conn_r) { 176 - switch ($this->order) { 177 - case self::ORDER_ID: 178 - return 'id DESC'; 179 - break; 180 - case self::ORDER_COLOR: 181 - return 'color ASC'; 182 - break; 183 - case self::ORDER_OBJECT: 184 - return 'type DESC'; 185 - break; 186 - case self::ORDER_REASON: 187 - return 'reasonPHID DESC'; 188 - break; 189 - default: 190 - throw new Exception("Unknown order {$this->order}!"); 191 - break; 192 - } 193 - } 194 - 195 - private function buildLimitClause($conn_r) { 196 - if ($this->limit && $this->offset) { 197 - return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, $this->limit); 198 - } else if ($this->limit) { 199 - return qsprintf($conn_r, 'LIMIT %d', $this->limit); 200 - } else if ($this->offset) { 201 - return qsprintf($conn_r, 'LIMIT %d, %d', $this->offset, PHP_INT_MAX); 202 - } else { 203 - return ''; 204 - } 135 + return $this->formatWhereClause($where); 205 136 } 206 137 207 138 }
+25 -11
src/applications/flag/storage/PhabricatorFlag.php
··· 1 1 <?php 2 2 3 - final class PhabricatorFlag extends PhabricatorFlagDAO { 3 + final class PhabricatorFlag extends PhabricatorFlagDAO 4 + implements PhabricatorPolicyInterface { 4 5 5 6 protected $ownerPHID; 6 7 protected $type; ··· 9 10 protected $color = PhabricatorFlagColor::COLOR_BLUE; 10 11 protected $note; 11 12 12 - private $handle = false; 13 - private $object = false; 13 + private $handle = self::ATTACHABLE; 14 + private $object = self::ATTACHABLE; 14 15 15 16 public function getObject() { 16 - if ($this->object === false) { 17 - throw new Exception('Call attachObject() before getObject()!'); 18 - } 19 - return $this->object; 17 + return $this->assertAttached($this->object); 20 18 } 21 19 22 20 public function attachObject($object) { ··· 25 23 } 26 24 27 25 public function getHandle() { 28 - if ($this->handle === false) { 29 - throw new Exception('Call attachHandle() before getHandle()!'); 30 - } 31 - return $this->handle; 26 + return $this->assertAttached($this->handle); 32 27 } 33 28 34 29 public function attachHandle(PhabricatorObjectHandle $handle) { 35 30 $this->handle = $handle; 36 31 return $this; 32 + } 33 + 34 + 35 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 36 + 37 + 38 + public function getCapabilities() { 39 + return array( 40 + PhabricatorPolicyCapability::CAN_VIEW, 41 + PhabricatorPolicyCapability::CAN_EDIT, 42 + ); 43 + } 44 + 45 + public function getPolicy($capability) { 46 + return PhabricatorPolicies::POLICY_NOONE; 47 + } 48 + 49 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 50 + return ($viewer->getPHID() == $this->getOwnerPHID()); 37 51 } 38 52 39 53 }
+1 -1
src/applications/macro/query/PhabricatorMacroQuery.php
··· 172 172 $flags = id(new PhabricatorFlagQuery()) 173 173 ->withOwnerPHIDs(array($this->getViewer()->getPHID())) 174 174 ->withTypes(array(PhabricatorMacroPHIDTypeMacro::TYPECONST)) 175 - ->withColor($this->flagColor) 175 + ->withColors(array($this->flagColor)) 176 176 ->setViewer($this->getViewer()) 177 177 ->execute(); 178 178