@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 upstream/main 143 lines 3.5 kB view raw
1<?php 2 3/** 4 * Structural class representing a column ordering for a query. 5 * 6 * Queries often order results on multiple columns. For example, projects might 7 * be ordered by "name, id". This class wraps a list of column orderings and 8 * makes them easier to manage. 9 * 10 * To construct an order vector, use @{method:newFromVector}: 11 * 12 * $vector = PhabricatorQueryOrderVector::newFromVector(array('name', 'id')); 13 * 14 * You can iterate over an order vector normally: 15 * 16 * foreach ($vector as $item) { 17 * // ... 18 * } 19 * 20 * The items are objects of class @{class:PhabricatorQueryOrderItem}. 21 * 22 * This class is primarily internal to the query infrastructure, and most 23 * application code should not need to interact with it directly. 24 */ 25final class PhabricatorQueryOrderVector 26 extends Phobject 27 implements Iterator { 28 29 private $items; 30 private $keys; 31 private $cursor; 32 33 private function __construct() { 34 // <private> 35 } 36 37 public static function newFromVector($vector) { 38 if ($vector instanceof PhabricatorQueryOrderVector) { 39 return (clone $vector); 40 } 41 42 if (!is_array($vector)) { 43 throw new Exception( 44 pht( 45 'An order vector can only be constructed from a list of strings or '. 46 'another order vector.')); 47 } 48 49 if (!$vector) { 50 throw new Exception( 51 pht( 52 'An order vector must not be empty.')); 53 } 54 55 $items = array(); 56 foreach ($vector as $key => $scalar) { 57 if (!is_string($scalar)) { 58 throw new Exception( 59 pht( 60 'Value with key "%s" in order vector is not a string (it has '. 61 'type "%s"). An order vector must contain only strings.', 62 $key, 63 gettype($scalar))); 64 } 65 66 $item = PhabricatorQueryOrderItem::newFromScalar($scalar); 67 68 // Orderings like "id, id, id" or "id, -id" are meaningless and invalid. 69 if (isset($items[$item->getOrderKey()])) { 70 throw new Exception( 71 pht( 72 'Order vector "%s" specifies order "%s" twice. Each component '. 73 'of an ordering must be unique.', 74 implode(', ', $vector), 75 $item->getOrderKey())); 76 } 77 78 $items[$item->getOrderKey()] = $item; 79 } 80 81 $obj = new PhabricatorQueryOrderVector(); 82 $obj->items = $items; 83 $obj->keys = array_keys($items); 84 return $obj; 85 } 86 87 public function appendVector($vector) { 88 $vector = self::newFromVector($vector); 89 90 // When combining vectors (like "group by" and "order by" vectors), there 91 // may be redundant columns. We only want to append unique columns which 92 // aren't already present in the vector. 93 foreach ($vector->items as $key => $item) { 94 if (empty($this->items[$key])) { 95 $this->items[$key] = $item; 96 $this->keys[] = $key; 97 } 98 } 99 100 return $this; 101 } 102 103 public function getAsString() { 104 $scalars = array(); 105 foreach ($this->items as $item) { 106 $scalars[] = $item->getAsScalar(); 107 } 108 return implode(', ', $scalars); 109 } 110 111 public function containsKey($key) { 112 return isset($this->items[$key]); 113 } 114 115 116/* -( Iterator Interface )------------------------------------------------- */ 117 118 119 public function rewind() { 120 $this->cursor = 0; 121 } 122 123 124 public function current() { 125 return $this->items[$this->key()]; 126 } 127 128 129 public function key() { 130 return $this->keys[$this->cursor]; 131 } 132 133 134 public function next() { 135 ++$this->cursor; 136 } 137 138 139 public function valid() { 140 return isset($this->keys[$this->cursor]); 141 } 142 143}