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