Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
indexer.php
1<?php
8
10
12{
13 protected $iblockId = 0;
14 protected $lastElementId = null;
15 protected static $catalog = null;
16 protected $skuIblockId = 0;
17 protected $skuPropertyId = 0;
18 protected $sectionParents = array();
19 protected $propertyFilter = null;
20 protected $priceFilter = null;
21
23 protected $dictionary = null;
25 protected $storage = null;
26
30 public function __construct($iblockId)
31 {
32 $this->iblockId = intval($iblockId);
33 }
34
41 public function init()
42 {
43 $this->dictionary = new Dictionary($this->iblockId);
44 $this->storage = new Storage($this->iblockId);
45 if (self::$catalog === null)
46 {
47 self::$catalog = \Bitrix\Main\Loader::includeModule("catalog");
48 }
49
50 if (self::$catalog)
51 {
52 $catalog = \CCatalogSKU::getInfoByProductIBlock($this->iblockId);
53 if (!empty($catalog) && is_array($catalog))
54 {
55 $this->skuIblockId = $catalog["IBLOCK_ID"];
56 $this->skuPropertyId = $catalog["SKU_PROPERTY_ID"];
57 }
58 }
59 }
60
69 {
70 $this->lastElementId = intval($lastElementId);
71 }
72
78 public function getLastElementId()
79 {
81 }
82
89 public function isExists()
90 {
91 return $this->storage->isExists() && $this->dictionary->isExists();
92 }
93
99 public function startIndex()
100 {
101 if ($this->storage->isExists())
102 $this->storage->drop();
103 if ($this->dictionary->isExists())
104 $this->dictionary->drop();
105
106 $this->dictionary->create();
107 $this->storage->create();
108
109 return true;
110 }
111
117 public function endIndex()
118 {
119 \Bitrix\Iblock\IblockTable::update($this->iblockId, array(
120 "PROPERTY_INDEX" => "Y",
121 ));
122 //TODO: replace \CIBlock::CleanCache to d7 method
123 \CIBlock::CleanCache($this->iblockId);
124 if ($this->skuIblockId)
125 {
126 \Bitrix\Iblock\IblockTable::update($this->skuIblockId, array(
127 "PROPERTY_INDEX" => "Y",
128 ));
129 //TODO: replace \CIBlock::CleanCache to d7 method
130 \CIBlock::CleanCache($this->skuIblockId);
131 }
132
133 return true;
134 }
135
142 public function continueIndex($interval = 0)
143 {
144 if ($interval > 0)
145 $endTime = microtime(true) + $interval;
146 else
147 $endTime = 0;
148
149 $indexedCount = 0;
150
151 if ($this->lastElementId === null)
152 $lastElementId = $this->storage->getLastStoredElementId();
153 else
155
156 $elementList = $this->getElementsCursor($lastElementId);
157 while ($element = $elementList->fetch())
158 {
159 $this->indexElement($element["ID"]);
160 $indexedCount++;
161 $this->lastElementId = $element["ID"];
162 if ($endTime > 0 && $endTime < microtime(true))
163 break;
164 }
165 return $indexedCount;
166 }
167
173 public function estimateElementCount()
174 {
175 $filter = array(
176 "IBLOCK_ID" => $this->iblockId,
177 "ACTIVE" => "Y",
178 "CHECK_PERMISSIONS" => "N",
179 );
180
181 return (int)\CIBlockElement::getList(array(), $filter, array());
182 }
183
191 public function indexElement($elementId)
192 {
193 $element = new Element($this->iblockId, $elementId);
194 $element->loadFromDatabase();
195
196 $elementSections = $element->getSections();
197 $elementIndexValues = $this->getSectionIndexEntries($element);
198
199 foreach ($element->getParentSections() as $sectionId)
200 {
201 foreach ($elementIndexValues as $facetId => $values)
202 {
203 foreach ($values as $value)
204 {
205 $this->storage->queueIndexEntry(
206 $sectionId,
207 $elementId,
208 $facetId,
209 $value["VALUE"],
210 $value["VALUE_NUM"],
211 in_array($sectionId, $elementSections)
212 );
213 }
214 }
215 }
216
217 foreach ($elementIndexValues as $facetId => $values)
218 {
219 foreach ($values as $value)
220 {
221 $this->storage->queueIndexEntry(
222 0,
223 $elementId,
224 $facetId,
225 $value["VALUE"],
226 $value["VALUE_NUM"],
227 empty($elementSections)
228 );
229 }
230 }
231
232 $this->storage->flushIndexEntries();
233 }
234
242 public function deleteElement($elementId)
243 {
244 $this->storage->deleteIndexElement($elementId);
245 }
246
255 protected function getElementsCursor(int $lastElementID = 0): \Bitrix\Main\ORM\Query\Result
256 {
257 $filter = [
258 '=IBLOCK_ID' => $this->iblockId,
259 '=ACTIVE' => 'Y',
260 '=WF_STATUS_ID' => 1,
261 '==WF_PARENT_ELEMENT_ID' => null,
262 ];
263
264 if ($lastElementID > 0)
265 {
266 $filter['>ID'] = $lastElementID;
267 }
268
269 return Iblock\ElementTable::getList([
270 'select' => ['ID'],
271 'filter' => $filter,
272 'order' => ['ID' => 'ASC'],
273 ]);
274 }
275
283 protected function getSectionIndexEntries(Element $element)
284 {
285 $result = array(
286 1 => array( //Section binding
287 array("VALUE" => 0, "VALUE_NUM" => 0.0)
288 )
289 );
290
291 foreach ($this->getFilterProperty(Storage::DICTIONARY) as $propertyId)
292 {
293 $facetId = $this->storage->propertyIdToFacetId($propertyId);
294 $result[$facetId] = array();
295 $propertyValues = $element->getPropertyValues($propertyId);
296 foreach ($propertyValues as $value)
297 {
298 $value = intval($value);
299 $result[$facetId][$value] = array(
300 "VALUE" => $value,
301 "VALUE_NUM" => 0.0,
302 );
303 }
304 }
305
306 foreach ($this->getFilterProperty(Storage::STRING) as $propertyId)
307 {
308 $facetId = $this->storage->propertyIdToFacetId($propertyId);
309 $result[$facetId] = array();
310 $propertyValues = $element->getPropertyValues($propertyId);
311 foreach ($propertyValues as $value)
312 {
313 $valueId = $this->dictionary->getStringId($value);
314 $result[$facetId][$valueId] = array(
315 "VALUE" => $valueId,
316 "VALUE_NUM" => 0.0,
317 );
318 }
319 }
320
321 foreach ($this->getFilterProperty(Storage::NUMERIC) as $propertyId)
322 {
323 $facetId = $this->storage->propertyIdToFacetId($propertyId);
324 $result[$facetId] = array();
325 $propertyValues = $element->getPropertyValues($propertyId);
326 foreach ($propertyValues as $value)
327 {
328 $value = doubleval($value);
329 $result[$facetId][md5($value)] = array(
330 "VALUE" => 0,
331 "VALUE_NUM" => $value,
332 );
333 }
334 }
335
336 foreach ($this->getFilterProperty(Storage::DATETIME) as $propertyId)
337 {
338 $facetId = $this->storage->propertyIdToFacetId($propertyId);
339 $result[$facetId] = array();
340 $propertyValues = $element->getPropertyValues($propertyId);
341 foreach ($propertyValues as $value)
342 {
343 //Save date only based on server time.
344 $timestamp = MakeTimeStamp($value, "YYYY-MM-DD HH:MI:SS");
345 $value = date('Y-m-d', $timestamp);
346 $timestamp = MakeTimeStamp($value, "YYYY-MM-DD");
347 $valueId = $this->dictionary->getStringId($value);
348 $result[$facetId][$valueId] = array(
349 "VALUE" => $valueId,
350 "VALUE_NUM" => $timestamp,
351 );
352 }
353 }
354
355 foreach ($this->getFilterPrices() as $priceId)
356 {
357 $facetId = $this->storage->priceIdToFacetId($priceId);
358 $result[$facetId] = array();
359 $elementPrices = $element->getPriceValues($priceId);
360 if ($elementPrices)
361 {
362 foreach ($elementPrices as $currency => $priceValues)
363 {
364 $currencyId = $this->dictionary->getStringId($currency);
365 foreach ($priceValues as $price)
366 {
367 $result[$facetId][$currencyId.":".$price] = array(
368 "VALUE" => $currencyId,
369 "VALUE_NUM" => $price,
370 );
371 }
372 }
373 }
374 }
375
376 return array_filter($result, "count");
377 }
378
389 protected function getFilterProperty($propertyType)
390 {
391 if (!isset($this->propertyFilter))
392 {
393 $this->propertyFilter = array(
394 Storage::DICTIONARY => array(),
395 Storage::STRING => array(),
396 Storage::NUMERIC => array(),
397 Storage::DATETIME => array(),
398 );
399 $propertyList = \Bitrix\Iblock\SectionPropertyTable::getList(array(
400 "select" => array("PROPERTY_ID", "PROPERTY.PROPERTY_TYPE", "PROPERTY.USER_TYPE"),
401 "filter" => array(
402 "=IBLOCK_ID" => array($this->iblockId, $this->skuIblockId),
403 "=SMART_FILTER" => "Y",
404 ),
405 ));
406 while ($link = $propertyList->fetch())
407 {
408 $storageType = $this->getPropertyStorageType(array(
409 "PROPERTY_TYPE" => $link["IBLOCK_SECTION_PROPERTY_PROPERTY_PROPERTY_TYPE"],
410 "USER_TYPE" => $link["IBLOCK_SECTION_PROPERTY_PROPERTY_USER_TYPE"],
411 ));
412 $this->propertyFilter[$storageType][] = $link["PROPERTY_ID"];
413 }
414 }
415 return $this->propertyFilter[$propertyType];
416 }
417
423 protected function getFilterPrices()
424 {
425 if (!isset($this->priceFilter))
426 {
427 $this->priceFilter = array();
428 if (self::$catalog)
429 {
430 //TODO: replace \CCatalogGroup::GetListArray after create cached d7 method
431 $priceList = \CCatalogGroup::GetListArray();
432 if (!empty($priceList))
433 $this->priceFilter = array_keys($priceList);
434 unset($priceList);
435 }
436 }
437 return $this->priceFilter;
438 }
439
450 public static function getPropertyStorageType($property)
451 {
452 if (isset($property['PROPERTY_TYPE']) && $property["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_NUMBER)
453 {
454 return Storage::NUMERIC;
455 }
456 elseif (isset($property['USER_TYPE']) && $property["USER_TYPE"] === \CIBlockPropertyDateTime::USER_TYPE)
457 {
458 return Storage::DATETIME;
459 }
460 elseif (isset($property['PROPERTY_TYPE']) && $property["PROPERTY_TYPE"] === Iblock\PropertyTable::TYPE_STRING)
461 {
462 return Storage::STRING;
463 }
464 else
465 {
466 return Storage::DICTIONARY;
467 }
468 }
469}
static getPropertyStorageType($property)
Definition indexer.php:450
getSectionIndexEntries(Element $element)
Definition indexer.php:283
getElementsCursor(int $lastElementID=0)
Definition indexer.php:255