[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class PhrictionDocumentQuery 4 extends PhabricatorCursorPagedPolicyAwareQuery { 5 6 private $ids; 7 private $phids; 8 private $slugs; 9 private $depths; 10 private $slugPrefix; 11 private $statuses; 12 13 private $needContent; 14 15 private $status = 'status-any'; 16 const STATUS_ANY = 'status-any'; 17 const STATUS_OPEN = 'status-open'; 18 const STATUS_NONSTUB = 'status-nonstub'; 19 20 private $order = 'order-created'; 21 const ORDER_CREATED = 'order-created'; 22 const ORDER_UPDATED = 'order-updated'; 23 const ORDER_HIERARCHY = 'order-hierarchy'; 24 25 public function withIDs(array $ids) { 26 $this->ids = $ids; 27 return $this; 28 } 29 30 public function withPHIDs(array $phids) { 31 $this->phids = $phids; 32 return $this; 33 } 34 35 public function withSlugs(array $slugs) { 36 $this->slugs = $slugs; 37 return $this; 38 } 39 40 public function withDepths(array $depths) { 41 $this->depths = $depths; 42 return $this; 43 } 44 45 public function withSlugPrefix($slug_prefix) { 46 $this->slugPrefix = $slug_prefix; 47 return $this; 48 } 49 50 public function withStatuses(array $statuses) { 51 $this->statuses = $statuses; 52 return $this; 53 } 54 55 public function withStatus($status) { 56 $this->status = $status; 57 return $this; 58 } 59 60 public function needContent($need_content) { 61 $this->needContent = $need_content; 62 return $this; 63 } 64 65 public function setOrder($order) { 66 $this->order = $order; 67 return $this; 68 } 69 70 protected function loadPage() { 71 $table = new PhrictionDocument(); 72 $conn_r = $table->establishConnection('r'); 73 74 if ($this->order == self::ORDER_HIERARCHY) { 75 $order_clause = $this->buildHierarchicalOrderClause($conn_r); 76 } else { 77 $order_clause = $this->buildOrderClause($conn_r); 78 } 79 80 $rows = queryfx_all( 81 $conn_r, 82 'SELECT d.* FROM %T d %Q %Q %Q %Q', 83 $table->getTableName(), 84 $this->buildJoinClause($conn_r), 85 $this->buildWhereClause($conn_r), 86 $order_clause, 87 $this->buildLimitClause($conn_r)); 88 89 $documents = $table->loadAllFromArray($rows); 90 91 if ($documents) { 92 $ancestor_slugs = array(); 93 foreach ($documents as $key => $document) { 94 $document_slug = $document->getSlug(); 95 foreach (PhabricatorSlug::getAncestry($document_slug) as $ancestor) { 96 $ancestor_slugs[$ancestor][] = $key; 97 } 98 } 99 100 if ($ancestor_slugs) { 101 $ancestors = queryfx_all( 102 $conn_r, 103 'SELECT * FROM %T WHERE slug IN (%Ls)', 104 $document->getTableName(), 105 array_keys($ancestor_slugs)); 106 $ancestors = $table->loadAllFromArray($ancestors); 107 $ancestors = mpull($ancestors, null, 'getSlug'); 108 109 foreach ($ancestor_slugs as $ancestor_slug => $document_keys) { 110 $ancestor = idx($ancestors, $ancestor_slug); 111 foreach ($document_keys as $document_key) { 112 $documents[$document_key]->attachAncestor( 113 $ancestor_slug, 114 $ancestor); 115 } 116 } 117 } 118 } 119 120 return $documents; 121 } 122 123 protected function willFilterPage(array $documents) { 124 // To view a Phriction document, you must also be able to view all of the 125 // ancestor documents. Filter out documents which have ancestors that are 126 // not visible. 127 128 $document_map = array(); 129 foreach ($documents as $document) { 130 $document_map[$document->getSlug()] = $document; 131 foreach ($document->getAncestors() as $key => $ancestor) { 132 if ($ancestor) { 133 $document_map[$key] = $ancestor; 134 } 135 } 136 } 137 138 $filtered_map = $this->applyPolicyFilter( 139 $document_map, 140 array(PhabricatorPolicyCapability::CAN_VIEW)); 141 142 // Filter all of the documents where a parent is not visible. 143 foreach ($documents as $document_key => $document) { 144 // If the document itself is not visible, filter it. 145 if (!isset($filtered_map[$document->getSlug()])) { 146 $this->didRejectResult($documents[$document_key]); 147 unset($documents[$document_key]); 148 continue; 149 } 150 151 // If an ancestor exists but is not visible, filter the document. 152 foreach ($document->getAncestors() as $ancestor_key => $ancestor) { 153 if (!$ancestor) { 154 continue; 155 } 156 157 if (!isset($filtered_map[$ancestor_key])) { 158 $this->didRejectResult($documents[$document_key]); 159 unset($documents[$document_key]); 160 break; 161 } 162 } 163 } 164 165 if (!$documents) { 166 return $documents; 167 } 168 169 if ($this->needContent) { 170 $contents = id(new PhrictionContent())->loadAllWhere( 171 'id IN (%Ld)', 172 mpull($documents, 'getContentID')); 173 174 foreach ($documents as $key => $document) { 175 $content_id = $document->getContentID(); 176 if (empty($contents[$content_id])) { 177 unset($documents[$key]); 178 continue; 179 } 180 $document->attachContent($contents[$content_id]); 181 } 182 } 183 184 return $documents; 185 } 186 187 private function buildJoinClause(AphrontDatabaseConnection $conn) { 188 $join = ''; 189 if ($this->order == self::ORDER_HIERARCHY) { 190 $content_dao = new PhrictionContent(); 191 $join = qsprintf( 192 $conn, 193 'JOIN %T c ON d.contentID = c.id', 194 $content_dao->getTableName()); 195 } 196 return $join; 197 } 198 protected function buildWhereClause(AphrontDatabaseConnection $conn) { 199 $where = array(); 200 201 if ($this->ids) { 202 $where[] = qsprintf( 203 $conn, 204 'd.id IN (%Ld)', 205 $this->ids); 206 } 207 208 if ($this->phids) { 209 $where[] = qsprintf( 210 $conn, 211 'd.phid IN (%Ls)', 212 $this->phids); 213 } 214 215 if ($this->slugs) { 216 $where[] = qsprintf( 217 $conn, 218 'd.slug IN (%Ls)', 219 $this->slugs); 220 } 221 222 if ($this->statuses) { 223 $where[] = qsprintf( 224 $conn, 225 'd.status IN (%Ld)', 226 $this->statuses); 227 } 228 229 if ($this->slugPrefix) { 230 $where[] = qsprintf( 231 $conn, 232 'd.slug LIKE %>', 233 $this->slugPrefix); 234 } 235 236 if ($this->depths) { 237 $where[] = qsprintf( 238 $conn, 239 'd.depth IN (%Ld)', 240 $this->depths); 241 } 242 243 switch ($this->status) { 244 case self::STATUS_OPEN: 245 $where[] = qsprintf( 246 $conn, 247 'd.status NOT IN (%Ld)', 248 array( 249 PhrictionDocumentStatus::STATUS_DELETED, 250 PhrictionDocumentStatus::STATUS_MOVED, 251 PhrictionDocumentStatus::STATUS_STUB, 252 )); 253 break; 254 case self::STATUS_NONSTUB: 255 $where[] = qsprintf( 256 $conn, 257 'd.status NOT IN (%Ld)', 258 array( 259 PhrictionDocumentStatus::STATUS_MOVED, 260 PhrictionDocumentStatus::STATUS_STUB, 261 )); 262 break; 263 case self::STATUS_ANY: 264 break; 265 default: 266 throw new Exception("Unknown status '{$this->status}'!"); 267 } 268 269 $where[] = $this->buildPagingClause($conn); 270 271 return $this->formatWhereClause($where); 272 } 273 274 private function buildHierarchicalOrderClause( 275 AphrontDatabaseConnection $conn_r) { 276 277 if ($this->getBeforeID()) { 278 return qsprintf( 279 $conn_r, 280 'ORDER BY d.depth, c.title, %Q %Q', 281 $this->getPagingColumn(), 282 $this->getReversePaging() ? 'DESC' : 'ASC'); 283 } else { 284 return qsprintf( 285 $conn_r, 286 'ORDER BY d.depth, c.title, %Q %Q', 287 $this->getPagingColumn(), 288 $this->getReversePaging() ? 'ASC' : 'DESC'); 289 } 290 } 291 292 protected function getPagingColumn() { 293 switch ($this->order) { 294 case self::ORDER_CREATED: 295 case self::ORDER_HIERARCHY: 296 return 'd.id'; 297 case self::ORDER_UPDATED: 298 return 'd.contentID'; 299 default: 300 throw new Exception("Unknown order '{$this->order}'!"); 301 } 302 } 303 304 protected function getPagingValue($result) { 305 switch ($this->order) { 306 case self::ORDER_CREATED: 307 case self::ORDER_HIERARCHY: 308 return $result->getID(); 309 case self::ORDER_UPDATED: 310 return $result->getContentID(); 311 default: 312 throw new Exception("Unknown order '{$this->order}'!"); 313 } 314 } 315 316 public function getQueryApplicationClass() { 317 return 'PhabricatorPhrictionApplication'; 318 } 319 320 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |