1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
DefaultElement.php
См. документацию.
1<?php
8
10
31
37{
38 const DEFAULT_LIMIT = 10;
39
40 protected function getDefaultPreFilters()
41 {
42 return array_merge([new Scope(Scope::REST)], parent::getDefaultPreFilters());
43 }
44
45 public static function getAllowedList()
46 {
47 return [];
48 }
49
50 public static function getElementEntityAllowedList()
51 {
52 return [
53 'ID',
54 'NAME',
55 'IBLOCK_SECTION_ID',
56 ];
57 }
58
59 public static function getPropertyEntityAllowedList()
60 {
61 return [
62 'ID',
63 'VALUE',
64 'DESCRIPTION'
65 ];
66 }
67
78 public function getAction($iblock, $elementId, array $select = ['*'])
79 {
80 $listResult = $this->listAction($iblock, $select, [['ID', $elementId]]);
81 $element = !empty($listResult->getItems()[0]) ? $listResult->getItems()[0] : [];
82
83 return ['element' => $element];
84 }
85
98 public function listAction($iblock, $select = ['*'], $filter = [], $order = [], PageNavigation $pageNavigation = null)
99 {
100 $elementEntity = IblockTable::compileEntity($iblock);
101 if (!$elementEntity)
102 {
103 return null;
104 }
105
106 $elementDataClass = $elementEntity->getDataClass();
107
108 if (!$elementEntity->getIblock()->fillRestOn())
109 {
110 throw new ArgumentException(sprintf('Restricted iblock ID:%s (%s)',
111 $elementEntity->getIblock()->getId(),
112 $elementEntity->getIblock()->getApiCode()
113 ));
114 }
115
116 $query = $elementDataClass::query();
117
118 // prepare id select
119 $query->addSelect(new ExpressionField('DISTINCT_ID', 'DISTINCT %s', 'ID'));
120
121 // prepare filter
122 if (!empty($filter))
123 {
124 $qFilter = static::prepareFilter($filter, $elementEntity);
125 $query->where($qFilter);
126 }
127
128 // prepare order
129 if (!empty($order))
130 {
131 $qOrder = static::prepareOrder($order, $elementEntity);
132 $query->setOrder($qOrder);
133 }
134
135 // prepare limit
136 $qLimit = $pageNavigation ? $pageNavigation->getLimit() : static::DEFAULT_LIMIT;
137 $qOffset = $pageNavigation ? $pageNavigation->getOffset() : 0;
138
139 // get elements
141 ->setLimit($qLimit)
142 ->setOffset($qOffset)
143 ->exec();
144
145 // count records
146 if ($result->getSelectedRowsCount() < $qLimit)
147 {
148 // optimization for first and last pages
149 $countTotal = $qOffset + $result->getSelectedRowsCount();
150 }
151 else
152 {
153 $countTotal = function () use ($query) {
154 return $query->queryCountTotal();
155 };
156 }
157
158 // get elements data
159 $elements = [];
160 $ids = [];
161
162 foreach ($result->fetchAll() as $row)
163 {
164 $ids[] = $row['DISTINCT_ID'];
165 }
166
167 if (!empty($ids))
168 {
169 $query = $elementDataClass::query();
170
171 $qSelect = static::prepareSelect($select, $elementEntity);
172 $query->setSelect($qSelect);
173
174 $query->whereIn('ID', $ids);
175
176 $resultElements = [];
177
178 foreach ($query->fetchCollection() as $elementObject)
179 {
181 $resultElements[$elementObject->getId()] = $elementObject->collectValues(Values::ALL, FieldTypeMask::ALL, true);
182 }
183
184 // original sort
185 foreach ($ids as $id)
186 {
187 $elements[] = $resultElements[$id];
188 }
189 }
190
191 return new Page('elements', $elements, $countTotal);
192 }
193
194 protected static function prepareSelect($fields, Entity $entity)
195 {
196 return static::checkFields($fields, $entity);
197 }
198
199
200 protected static function prepareFilter($filter, Entity $entity)
201 {
203 $definitions = static::getFilterDefinitions($filter);
204
205 static::checkFields($definitions, $entity);
206
207 return $filter;
208 }
209
210 protected static function prepareOrder($order, Entity $entity)
211 {
212 static::checkFields(array_keys($order), $entity);
213
214 return $order;
215 }
216
217 protected static function checkFields($fields, Entity $entity)
218 {
219 $propertyEntityAllowedList = static::getPropertyEntityAllowedList();
220 $elementEntityAllowedList = static::getElementEntityAllowedList();
221 $allowedList = array_merge($elementEntityAllowedList, static::getAllowedList());
222
223 // replace REF.* for allowed fields REF.ALLOWED1, REF.ALLOWED2, etc.
224 $chainReplacement = [];
225
226 // analyze
227 foreach ($fields as $definition)
228 {
229 // check allowed list
230 if (in_array($definition, $allowedList, true))
231 {
232 continue;
233 }
234
235 // smart check for relations and property fields
236 $chain = Chain::getChainByDefinition($entity, $definition);
237 $currentDefinition = '';
238
239 $elements = $chain->getAllElements();
240 $lastElement = $chain->getLastElement();
241
242 foreach ($elements as $element)
243 {
244 $isLastElement = ($element === $lastElement);
245
246 // skip init entity
247 if ($element->getValue() instanceof ElementEntity && !$isLastElement)
248 {
249 continue;
250 }
251
252 // append definition
253 $currentDefinition = Chain::appendDefinition($currentDefinition, $element->getDefinitionFragment());
254
255 // handle wildcard
256 if ($currentDefinition === '*' && $isLastElement)
257 {
258 $chainReplacement[$definition] = [];
259
260 foreach ($elementEntityAllowedList as $allowedFieldName)
261 {
262 if ($entity->hasField($allowedFieldName))
263 {
264 $chainReplacement[$definition][] = $allowedFieldName;
265 }
266 }
267
268 continue;
269 }
270
271 // check access
272 if (!($element->getValue() instanceof Field))
273 {
274 throw new ArgumentException(
275 sprintf('Restricted field `%s`', $currentDefinition)
276 );
277 }
278
279 $currentField = $element->getValue();
280 $currentEntity = $currentField->getEntity();
281
282 // case 1. iblock
283 if ($currentEntity instanceof ElementEntity)
284 {
285 // case 1.1. iblock scalar
286 if (in_array($currentField->getName(), $elementEntityAllowedList, true))
287 {
288 continue;
289 }
290
291 // case 1.2. iblock property
292 if (!empty(class_uses($currentField)[PropertyRelation::class]))
293 {
294 if ($isLastElement)
295 {
296 // replace * with allowed fields
297 $propEntity = $currentField->getRefEntity();
298 $chainReplacement[$definition] = [];
299
300 foreach ($propertyEntityAllowedList as $allowedFieldName)
301 {
302 if ($propEntity->hasField($allowedFieldName))
303 {
304 $chainReplacement[$definition][] = Chain::appendDefinition($currentDefinition, $allowedFieldName);
305 }
306 }
307 }
308
309 continue;
310 }
311 }
312
313 // case 2. property entity
314 if ($currentEntity instanceof ValueStorageEntity)
315 {
316 // case 2.1. property scalar
317 if (in_array($currentField->getName(), $propertyEntityAllowedList, true))
318 {
319 continue;
320 }
321
322 // case 2.1. ref to another iblock
323 if ($currentField instanceof Reference)
324 {
325 $refEntity = $currentField->getRefEntity();
326
327 // check if remote iblock is readable
328 if ($refEntity instanceof ElementEntity && $refEntity->getIblock()->fillRestOn())
329 {
330 if ($isLastElement)
331 {
332 // replace * with allowed fields
333 $chainReplacement[$definition] = [];
334
335 foreach ($elementEntityAllowedList as $allowedFieldName)
336 {
337 if ($refEntity->hasField($allowedFieldName))
338 {
339 $chainReplacement[$definition][] = Chain::appendDefinition($currentDefinition, $allowedFieldName);
340 }
341 }
342 }
343
344 continue;
345 }
346 }
347 }
348
349 // restricted by default
350 throw new ArgumentException(
351 sprintf('Restricted field `%s`', $currentDefinition)
352 );
353 }
354 }
355
356 // time to replace *
357 foreach ($chainReplacement as $definition => $replacement)
358 {
359 // unset original
360 $key = array_search($definition, $fields);
361 unset($fields[$key]);
362
363 // add replacement
364 $fields = array_merge($fields, $replacement);
365 }
366
367 return $fields;
368 }
369
370 protected static function getFilterDefinitions(ConditionTree $filter)
371 {
372 $definitions = [];
373
374 foreach ($filter->getConditions() as $condition)
375 {
376 if ($condition instanceof ConditionTree)
377 {
378 // add subfilter recursively
379 $definitions = array_merge($definitions, static::getFilterDefinitions($condition));
380 }
381 else
382 {
383 // add column
384 if ($condition->getColumn() !== null)
385 {
386 $definitions[] = $condition->getColumn();
387 }
388
389 // add value
390 $values = $condition->getValue();
391 if (!is_array($values))
392 {
393 $values = [$values];
394 }
395
396 foreach ($values as $subValue)
397 {
398 if ($subValue instanceof ColumnExpression)
399 {
400 $definitions[] = $subValue->getDefinition();
401 }
402 }
403 }
404 }
405
406 return $definitions;
407 }
408}
static getPropertyEntityAllowedList()
Определения DefaultElement.php:59
static getElementEntityAllowedList()
Определения DefaultElement.php:50
static prepareOrder($order, Entity $entity)
Определения DefaultElement.php:210
static getFilterDefinitions(ConditionTree $filter)
Определения DefaultElement.php:370
static prepareSelect($fields, Entity $entity)
Определения DefaultElement.php:194
static checkFields($fields, Entity $entity)
Определения DefaultElement.php:217
getAction($iblock, $elementId, array $select=[' *'])
Определения DefaultElement.php:78
static prepareFilter($filter, Entity $entity)
Определения DefaultElement.php:200
Определения iblock.php:18
static appendDefinition($currentDefinition, $newDefinitionPart)
Определения chain.php:383
static createFromArray($filter)
Определения conditiontree.php:753
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$entity
if(! $catalogEdit->isSuccess()) $iblock
Определения iblock_catalog_edit.php:38
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
trait PropertyRelation
Определения propertyrelation.php:18
Определения ufield.php:9
$order
Определения payment.php:8
if(empty($signedUserToken)) $key
Определения quickway.php:257
$fields
Определения yandex_run.php:501