1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Arrilot\BitrixModels\Queries; |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
use Arrilot\BitrixModels\Models\HLModel; |
7
|
|
|
use Illuminate\Support\Collection; |
8
|
|
|
use LogicException; |
9
|
|
|
|
10
|
|
|
class HLQuery extends BaseQuery |
11
|
|
|
{ |
12
|
|
|
public $keyBy = 'ID'; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Query sort. |
16
|
|
|
* |
17
|
|
|
* @var array |
18
|
|
|
*/ |
19
|
|
|
public $select = false; |
20
|
|
|
public $sort = ['ID' => 'ASC']; |
21
|
|
|
public $limit; |
22
|
|
|
public $page; |
23
|
|
|
public $ttl = 0; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Query group by. |
27
|
|
|
* |
28
|
|
|
* @var array |
29
|
|
|
*/ |
30
|
|
|
public $groupBy = false; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Iblock id. |
34
|
|
|
* |
35
|
|
|
* @var int |
36
|
|
|
*/ |
37
|
|
|
protected $tableName; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Constructor. |
41
|
|
|
* |
42
|
|
|
* @param object $bxObject |
43
|
|
|
* @param string $modelName |
44
|
|
|
*/ |
45
|
|
|
public function __construct($bxObject, $modelName) |
46
|
|
|
{ |
47
|
|
|
parent::__construct($bxObject, $modelName); |
48
|
|
|
|
49
|
|
|
$this->tableName = $modelName::tableName(); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Setter for groupBy. |
54
|
|
|
* |
55
|
|
|
* @param $value |
56
|
|
|
* |
57
|
|
|
* @return $this |
58
|
|
|
*/ |
59
|
|
|
public function groupBy($value) |
60
|
|
|
{ |
61
|
|
|
$this->groupBy = $value; |
62
|
|
|
|
63
|
|
|
return $this; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
public function limit($value) |
67
|
|
|
{ |
68
|
|
|
$this->limit = $value; |
69
|
|
|
|
70
|
|
|
return $this; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
public function page($num) |
74
|
|
|
{ |
75
|
|
|
$this->page = $num; |
76
|
|
|
|
77
|
|
|
return $this; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
public function cache($ttl) |
81
|
|
|
{ |
82
|
|
|
$this->ttl = (int) $ttl; |
83
|
|
|
|
84
|
|
|
return $this; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Get list of items. |
89
|
|
|
* |
90
|
|
|
* @return Collection |
91
|
|
|
*/ |
92
|
|
|
public function getList() |
93
|
|
|
{ |
94
|
|
|
if ($this->queryShouldBeStopped) { |
95
|
|
|
return new Collection(); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
$items = []; |
99
|
|
|
|
100
|
|
|
|
101
|
|
|
$params = [ |
102
|
|
|
'filter' => $this->normalizeFilter(), |
103
|
|
|
'order' => $this->sort, |
104
|
|
|
'select' => $this->normalizeSelect(), |
105
|
|
|
//'cache' => ['ttl' => 3600], |
|
|
|
|
106
|
|
|
]; |
107
|
|
|
|
108
|
|
|
if ($this->groupBy) $params['group'] = $this->groupBy; |
|
|
|
|
109
|
|
|
if ($this->limit) $params['limit'] = $this->limit; |
110
|
|
|
if ($this->ttl) $params['cache'] = ['ttl' => $this->ttl]; |
111
|
|
|
if ($this->page && $this->limit) $params['offset'] = $this->page * $this->limit; |
112
|
|
|
|
113
|
|
|
$rsItems = $this->bxObject::getList($params); |
114
|
|
|
while ($arItem = $rsItems->fetch()) { |
115
|
|
|
$this->addItemToResultsUsingKeyBy($items, new $this->modelName($arItem['ID'], $arItem)); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
return new Collection($items); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
View Code Duplication |
protected function addItemToResultsUsingKeyBy(&$results, HLModel $object) |
|
|
|
|
122
|
|
|
{ |
123
|
|
|
$item = $object->fields; |
124
|
|
|
|
125
|
|
|
if (!isset($item[$this->keyBy])) { |
126
|
|
|
throw new LogicException("Field {$this->keyBy} is not found in object"); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
$keyByValue = $item[$this->keyBy]; |
130
|
|
|
|
131
|
|
|
if (!isset($results[$keyByValue])) { |
132
|
|
|
$results[$keyByValue] = $object; |
133
|
|
|
} else { |
134
|
|
|
$oldFields = $results[$keyByValue]->fields; |
135
|
|
|
foreach ($oldFields as $field => $oldValue) { |
136
|
|
|
// пропускаем служебные поля. |
137
|
|
|
if (in_array($field, ['_were_multiplied', 'PROPERTIES'])) { |
138
|
|
|
continue; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
$alreadyMultiplied = !empty($oldFields['_were_multiplied'][$field]); |
142
|
|
|
|
143
|
|
|
// мультиплицируем только несовпадающие значения полей |
144
|
|
|
$newValue = $item[$field]; |
145
|
|
|
if ($oldValue !== $newValue) { |
146
|
|
|
// если еще не мультиплицировали поле, то его надо превратить в массив. |
147
|
|
|
if (!$alreadyMultiplied) { |
148
|
|
|
$oldFields[$field] = [ |
149
|
|
|
$oldFields[$field] |
150
|
|
|
]; |
151
|
|
|
$oldFields['_were_multiplied'][$field] = true; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// добавляем новое значению поле если такого еще нет. |
155
|
|
|
if (empty($oldFields[$field]) || (is_array($oldFields[$field]) && !in_array($newValue, $oldFields[$field]))) { |
156
|
|
|
$oldFields[$field][] = $newValue; |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
$results[$keyByValue]->fields = $oldFields; |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Get count of elements that match $filter. |
167
|
|
|
* |
168
|
|
|
* @return int |
169
|
|
|
*/ |
170
|
|
|
public function count() |
171
|
|
|
{ |
172
|
|
|
if ($this->queryShouldBeStopped) { |
173
|
|
|
return 0; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
return (int) $this->bxObject->getCount($this->normalizeFilter()); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Normalize filter before sending it to getList. |
181
|
|
|
* This prevents some inconsistency. |
182
|
|
|
* |
183
|
|
|
* @return array |
184
|
|
|
*/ |
185
|
|
|
protected function normalizeFilter() |
186
|
|
|
{ |
187
|
|
|
return $this->filter; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Normalize select before sending it to getList. |
192
|
|
|
* This prevents some inconsistency. |
193
|
|
|
* |
194
|
|
|
* @return array |
195
|
|
|
*/ |
196
|
|
|
protected function normalizeSelect() |
197
|
|
|
{ |
198
|
|
|
return ( !$this->select || empty($this->select) ) ? ['*'] : $this->select; |
|
|
|
|
199
|
|
|
} |
200
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.