Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/query/order/PhabricatorQueryOrderVector.php
12242 views
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
*/
25
final 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
}
144
145