Path: blob/master/src/infrastructure/query/order/PhabricatorQueryOrderVector.php
12242 views
<?php12/**3* Structural class representing a column ordering for a query.4*5* Queries often order results on multiple columns. For example, projects might6* be ordered by "name, id". This class wraps a list of column orderings and7* makes them easier to manage.8*9* To construct an order vector, use @{method:newFromVector}:10*11* $vector = PhabricatorQueryOrderVector::newFromVector(array('name', 'id'));12*13* You can iterate over an order vector normally:14*15* foreach ($vector as $item) {16* // ...17* }18*19* The items are objects of class @{class:PhabricatorQueryOrderItem}.20*21* This class is primarily internal to the query infrastructure, and most22* application code should not need to interact with it directly.23*/24final class PhabricatorQueryOrderVector25extends Phobject26implements Iterator {2728private $items;29private $keys;30private $cursor;3132private function __construct() {33// <private>34}3536public static function newFromVector($vector) {37if ($vector instanceof PhabricatorQueryOrderVector) {38return (clone $vector);39}4041if (!is_array($vector)) {42throw new Exception(43pht(44'An order vector can only be constructed from a list of strings or '.45'another order vector.'));46}4748if (!$vector) {49throw new Exception(50pht(51'An order vector must not be empty.'));52}5354$items = array();55foreach ($vector as $key => $scalar) {56if (!is_string($scalar)) {57throw new Exception(58pht(59'Value with key "%s" in order vector is not a string (it has '.60'type "%s"). An order vector must contain only strings.',61$key,62gettype($scalar)));63}6465$item = PhabricatorQueryOrderItem::newFromScalar($scalar);6667// Orderings like "id, id, id" or "id, -id" are meaningless and invalid.68if (isset($items[$item->getOrderKey()])) {69throw new Exception(70pht(71'Order vector "%s" specifies order "%s" twice. Each component '.72'of an ordering must be unique.',73implode(', ', $vector),74$item->getOrderKey()));75}7677$items[$item->getOrderKey()] = $item;78}7980$obj = new PhabricatorQueryOrderVector();81$obj->items = $items;82$obj->keys = array_keys($items);83return $obj;84}8586public function appendVector($vector) {87$vector = self::newFromVector($vector);8889// When combining vectors (like "group by" and "order by" vectors), there90// may be redundant columns. We only want to append unique columns which91// aren't already present in the vector.92foreach ($vector->items as $key => $item) {93if (empty($this->items[$key])) {94$this->items[$key] = $item;95$this->keys[] = $key;96}97}9899return $this;100}101102public function getAsString() {103$scalars = array();104foreach ($this->items as $item) {105$scalars[] = $item->getAsScalar();106}107return implode(', ', $scalars);108}109110public function containsKey($key) {111return isset($this->items[$key]);112}113114115/* -( Iterator Interface )------------------------------------------------- */116117118public function rewind() {119$this->cursor = 0;120}121122123public function current() {124return $this->items[$this->key()];125}126127128public function key() {129return $this->keys[$this->cursor];130}131132133public function next() {134++$this->cursor;135}136137138public function valid() {139return isset($this->keys[$this->cursor]);140}141142}143144145