@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 247 lines 5.7 kB view raw
1<?php 2 3/** 4 * @extends AlmanacQuery<AlmanacService> 5 */ 6final class AlmanacServiceQuery 7 extends AlmanacQuery { 8 9 private $ids; 10 private $phids; 11 private $names; 12 private $serviceTypes; 13 private $devicePHIDs; 14 private $namePrefix; 15 private $nameSuffix; 16 17 private $needBindings; 18 private $needActiveBindings; 19 20 public function withIDs(array $ids) { 21 $this->ids = $ids; 22 return $this; 23 } 24 25 public function withPHIDs(array $phids) { 26 $this->phids = $phids; 27 return $this; 28 } 29 30 public function withNames(array $names) { 31 $this->names = $names; 32 return $this; 33 } 34 35 public function withServiceTypes(array $types) { 36 $this->serviceTypes = $types; 37 return $this; 38 } 39 40 public function withDevicePHIDs(array $phids) { 41 $this->devicePHIDs = $phids; 42 return $this; 43 } 44 45 public function withNamePrefix($prefix) { 46 $this->namePrefix = $prefix; 47 return $this; 48 } 49 50 public function withNameSuffix($suffix) { 51 $this->nameSuffix = $suffix; 52 return $this; 53 } 54 55 public function withNameNgrams($ngrams) { 56 return $this->withNgramsConstraint( 57 new AlmanacServiceNameNgrams(), 58 $ngrams); 59 } 60 61 public function needBindings($need_bindings) { 62 $this->needBindings = $need_bindings; 63 return $this; 64 } 65 66 public function needActiveBindings($need_active) { 67 $this->needActiveBindings = $need_active; 68 return $this; 69 } 70 71 public function newResultObject() { 72 return new AlmanacService(); 73 } 74 75 protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { 76 $joins = parent::buildJoinClauseParts($conn); 77 78 if ($this->shouldJoinBindingTable()) { 79 $joins[] = qsprintf( 80 $conn, 81 'JOIN %T binding ON service.phid = binding.servicePHID', 82 id(new AlmanacBinding())->getTableName()); 83 } 84 85 return $joins; 86 } 87 88 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 89 $where = parent::buildWhereClauseParts($conn); 90 91 if ($this->ids !== null) { 92 $where[] = qsprintf( 93 $conn, 94 'service.id IN (%Ld)', 95 $this->ids); 96 } 97 98 if ($this->phids !== null) { 99 $where[] = qsprintf( 100 $conn, 101 'service.phid IN (%Ls)', 102 $this->phids); 103 } 104 105 if ($this->names !== null) { 106 $hashes = array(); 107 foreach ($this->names as $name) { 108 $hashes[] = PhabricatorHash::digestForIndex($name); 109 } 110 111 $where[] = qsprintf( 112 $conn, 113 'service.nameIndex IN (%Ls)', 114 $hashes); 115 } 116 117 if ($this->serviceTypes !== null) { 118 $where[] = qsprintf( 119 $conn, 120 'service.serviceType IN (%Ls)', 121 $this->serviceTypes); 122 } 123 124 if ($this->devicePHIDs !== null) { 125 $where[] = qsprintf( 126 $conn, 127 'binding.devicePHID IN (%Ls)', 128 $this->devicePHIDs); 129 } 130 131 if ($this->namePrefix !== null) { 132 $where[] = qsprintf( 133 $conn, 134 'service.name LIKE %>', 135 $this->namePrefix); 136 } 137 138 if ($this->nameSuffix !== null) { 139 $where[] = qsprintf( 140 $conn, 141 'service.name LIKE %<', 142 $this->nameSuffix); 143 } 144 145 return $where; 146 } 147 148 protected function willFilterPage(array $services) { 149 $service_map = AlmanacServiceType::getAllServiceTypes(); 150 151 foreach ($services as $key => $service) { 152 $implementation = idx($service_map, $service->getServiceType()); 153 154 if (!$implementation) { 155 $this->didRejectResult($service); 156 unset($services[$key]); 157 continue; 158 } 159 160 $implementation = clone $implementation; 161 $service->attachServiceImplementation($implementation); 162 } 163 164 return $services; 165 } 166 167 protected function didFilterPage(array $services) { 168 $need_all = $this->needBindings; 169 $need_active = $this->needActiveBindings; 170 171 $need_any = ($need_all || $need_active); 172 $only_active = ($need_active && !$need_all); 173 174 if ($need_any) { 175 $service_phids = mpull($services, 'getPHID'); 176 177 $bindings_query = id(new AlmanacBindingQuery()) 178 ->setViewer($this->getViewer()) 179 ->withServicePHIDs($service_phids) 180 ->needProperties($this->getNeedProperties()); 181 182 if ($only_active) { 183 $bindings_query->withIsActive(true); 184 } 185 186 $bindings = $bindings_query->execute(); 187 $bindings = mgroup($bindings, 'getServicePHID'); 188 189 foreach ($services as $service) { 190 $service_bindings = idx($bindings, $service->getPHID(), array()); 191 192 if ($only_active) { 193 $service->attachActiveBindings($service_bindings); 194 } else { 195 $service->attachBindings($service_bindings); 196 } 197 } 198 } 199 200 return parent::didFilterPage($services); 201 } 202 203 private function shouldJoinBindingTable() { 204 return ($this->devicePHIDs !== null); 205 } 206 207 protected function shouldGroupQueryResultRows() { 208 if ($this->shouldJoinBindingTable()) { 209 return true; 210 } 211 212 return parent::shouldGroupQueryResultRows(); 213 } 214 215 protected function getPrimaryTableAlias() { 216 return 'service'; 217 } 218 219 public function getOrderableColumns() { 220 return parent::getOrderableColumns() + array( 221 'name' => array( 222 'table' => $this->getPrimaryTableAlias(), 223 'column' => 'name', 224 'type' => 'string', 225 'unique' => true, 226 'reverse' => true, 227 ), 228 ); 229 } 230 231 protected function newPagingMapFromPartialObject($object) { 232 return array( 233 'id' => (int)$object->getID(), 234 'name' => $object->getName(), 235 ); 236 } 237 238 public function getBuiltinOrders() { 239 return array( 240 'name' => array( 241 'vector' => array('name'), 242 'name' => pht('Service Name'), 243 ), 244 ) + parent::getBuiltinOrders(); 245 } 246 247}