@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 199 lines 5.3 kB view raw
1<?php 2 3final class PhabricatorProjectColumnOwnerOrder 4 extends PhabricatorProjectColumnOrder { 5 6 const ORDERKEY = 'owner'; 7 8 public function getDisplayName() { 9 return pht('Group by Owner'); 10 } 11 12 protected function newMenuIconIcon() { 13 return 'fa-users'; 14 } 15 16 public function getHasHeaders() { 17 return true; 18 } 19 20 public function getCanReorder() { 21 return true; 22 } 23 24 public function getMenuOrder() { 25 return 2000; 26 } 27 28 protected function newHeaderKeyForObject($object) { 29 return $this->newHeaderKeyForOwnerPHID($object->getOwnerPHID()); 30 } 31 32 private function newHeaderKeyForOwnerPHID($owner_phid) { 33 if ($owner_phid === null) { 34 $owner_phid = '<null>'; 35 } 36 37 return sprintf('owner(%s)', $owner_phid); 38 } 39 40 protected function newSortVectorsForObjects(array $objects) { 41 $owner_phids = mpull($objects, null, 'getOwnerPHID'); 42 $owner_phids = array_keys($owner_phids); 43 $owner_phids = array_filter($owner_phids); 44 45 if ($owner_phids) { 46 $owner_users = id(new PhabricatorPeopleQuery()) 47 ->setViewer($this->getViewer()) 48 ->withPHIDs($owner_phids) 49 ->execute(); 50 $owner_users = mpull($owner_users, null, 'getPHID'); 51 } else { 52 $owner_users = array(); 53 } 54 55 $vectors = array(); 56 foreach ($objects as $vector_key => $object) { 57 $owner_phid = $object->getOwnerPHID(); 58 if (!$owner_phid) { 59 $vector = $this->newSortVectorForUnowned(); 60 } else { 61 $owner = idx($owner_users, $owner_phid); 62 if ($owner) { 63 $vector = $this->newSortVectorForOwner($owner); 64 } else { 65 $vector = $this->newSortVectorForOwnerPHID($owner_phid); 66 } 67 } 68 69 $vectors[$vector_key] = $vector; 70 } 71 72 return $vectors; 73 } 74 75 private function newSortVectorForUnowned() { 76 // Always put unasssigned tasks at the top. 77 return array( 78 0, 79 ); 80 } 81 82 private function newSortVectorForOwner(PhabricatorUser $user) { 83 // Put assigned tasks with a valid owner after "Unassigned", but above 84 // assigned tasks with an invalid owner. Sort these tasks by the owner's 85 // username. 86 return array( 87 1, 88 $user->getUsername(), 89 ); 90 } 91 92 private function newSortVectorForOwnerPHID($owner_phid) { 93 // If we have tasks with a nonempty owner but can't load the associated 94 // "User" object, move them to the bottom. We can only sort these by the 95 // PHID. 96 return array( 97 2, 98 $owner_phid, 99 ); 100 } 101 102 protected function newHeadersForObjects(array $objects) { 103 $owner_phids = mpull($objects, null, 'getOwnerPHID'); 104 $owner_phids = array_keys($owner_phids); 105 $owner_phids = array_filter($owner_phids); 106 107 if ($owner_phids) { 108 $owner_users = id(new PhabricatorPeopleQuery()) 109 ->setViewer($this->getViewer()) 110 ->withPHIDs($owner_phids) 111 ->needProfileImage(true) 112 ->execute(); 113 $owner_users = mpull($owner_users, null, 'getPHID'); 114 } else { 115 $owner_users = array(); 116 } 117 118 array_unshift($owner_phids, null); 119 120 $headers = array(); 121 foreach ($owner_phids as $owner_phid) { 122 $header_key = $this->newHeaderKeyForOwnerPHID($owner_phid); 123 124 $owner_image = null; 125 $effect_content = null; 126 if ($owner_phid === null) { 127 $owner = null; 128 $sort_vector = $this->newSortVectorForUnowned(); 129 $owner_name = pht('Not Assigned'); 130 131 $effect_content = pht('Remove task assignee.'); 132 } else { 133 $owner = idx($owner_users, $owner_phid); 134 if ($owner) { 135 $sort_vector = $this->newSortVectorForOwner($owner); 136 $owner_name = $owner->getUsername(); 137 $owner_image = $owner->getProfileImageURI(); 138 139 $effect_content = pht( 140 'Assign task to %s.', 141 phutil_tag('strong', array(), $owner_name)); 142 } else { 143 $sort_vector = $this->newSortVectorForOwnerPHID($owner_phid); 144 $owner_name = pht('Unknown User ("%s")', $owner_phid); 145 } 146 } 147 148 $owner_icon = 'fa-user'; 149 $owner_color = 'bluegrey'; 150 151 $icon_view = new PHUIIconView(); 152 153 if ($owner_image) { 154 $icon_view->setImage($owner_image); 155 } else { 156 $icon_view->setIcon($owner_icon, $owner_color); 157 } 158 159 $header = $this->newHeader() 160 ->setHeaderKey($header_key) 161 ->setSortVector($sort_vector) 162 ->setName($owner_name) 163 ->setIcon($icon_view) 164 ->setEditProperties( 165 array( 166 'value' => $owner_phid, 167 )); 168 169 if ($effect_content !== null) { 170 $header->addDropEffect( 171 $this->newEffect() 172 ->setIcon($owner_icon) 173 ->setColor($owner_color) 174 ->addCondition('owner', '!=', $owner_phid) 175 ->setContent($effect_content)); 176 } 177 178 $headers[] = $header; 179 } 180 181 return $headers; 182 } 183 184 protected function newColumnTransactions($object, array $header) { 185 $new_owner = idx($header, 'value'); 186 187 if ($object->getOwnerPHID() === $new_owner) { 188 return null; 189 } 190 191 $xactions = array(); 192 $xactions[] = $this->newTransaction($object) 193 ->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE) 194 ->setNewValue($new_owner); 195 196 return $xactions; 197 } 198 199}