1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
Generator.php
См. документацию.
1<?php
2
3namespace Bitrix\Seo\Sitemap;
4
5use Bitrix\Main\Localization\Loc;
6use Bitrix\Main\SiteTable;
7use Bitrix\Main\Loader;
8use Bitrix\Main\IO;
9use Bitrix\Main\Type\DateTime;
10use Bitrix\Seo\Sitemap\Internals\SitemapTable;
11use Bitrix\Seo\Sitemap\Internals\RuntimeTable;
12use Bitrix\Seo\Sitemap\Type\Step;
13use Bitrix\Seo\RobotsFile;
14
15Loc::loadMessages(__DIR__ . '/../../admin/seo_sitemap.php');
16
21{
25 protected const STEP_DURATION = 13;
26
31 protected int $sitemapId;
32
37 protected array $sitemapData = [];
38
43 protected int $step;
44
49 protected int $stepStartTime;
50
55 protected array $state;
56
61 protected string $statusMessage = '';
62
67 protected ?File\Base $sitemapFile = null;
68
73 protected ?array $currentRuntimeIBlock = null;
74
79 protected ?array $currentIBlock = null;
80
81 public function __construct(int $sitemapId)
82 {
83 if ($sitemapId <= 0)
84 {
85 // todo: err
86 }
87 $this->sitemapId = $sitemapId;
88
89 $this->sitemapData = (SitemapTable::getById($this->sitemapId))->fetch();
90 if (empty($this->sitemapData))
91 {
92 // todo: error
93 }
94 $this->sitemapData['SETTINGS'] = unserialize($this->sitemapData['SETTINGS'], ['allowed_classes' => false]);
95 $this->sitemapData['SITE'] = (SiteTable::getByPrimary($this->sitemapData['SITE_ID']))->fetch();
96
97 $this->init(Step::getFirstStep(), []);
98 }
99
106 public function init(int $step, array $state): self
107 {
108 // todo: check state by whitelist
109 $this->step = $step;
110 $this->state = $state;
111
112 $this->statusMessage = Loc::getMessage('SEO_SITEMAP_RUN_INIT');
113
114 return $this;
115 }
116
121 public function getStep(): int
122 {
123 return $this->step;
124 }
125
130 public function getState(): array
131 {
132 return $this->state;
133 }
134
139 public function getStatusMessage(): string
140 {
142 }
143
147 public function run(): bool
148 {
149 $result = false;
150 $this->startStep();
151
152 if ($this->step === Step::STEPS[Step::STEP_INIT])
153 {
154 $result = $this->runInit();
155 }
156
157 elseif ($this->step < Step::STEPS[Step::STEP_FILES])
158 {
159 $result = $this->runFiles();
160 }
161
162 elseif ($this->step < Step::STEPS[Step::STEP_IBLOCK_INDEX])
163 {
164 $result = $this->runIblockIndex();
165 }
166
167 elseif ($this->step < Step::STEPS[Step::STEP_IBLOCK])
168 {
169 $result = $this->runIblock();
170 }
171
172 elseif ($this->step < Step::STEPS[Step::STEP_FORUM_INDEX])
173 {
174 $result = $this->runForumIndex();
175 }
176
177 elseif ($this->step < Step::STEPS[Step::STEP_FORUM])
178 {
179 $result = $this->runForum();
180 }
181
182 elseif ($this->step < Step::STEPS[Step::STEP_INDEX])
183 {
184 if ($this->runIndex())
185 {
186 $result = $this->finish();
187 }
188 }
189
190 return $result;
191 }
192
197 protected function runInit(): bool
198 {
199 RuntimeTable::clearByPid($this->sitemapId);
200
201 $isRootChecked =
202 isset($this->sitemapData['SETTINGS']['DIR']['/'])
203 && $this->sitemapData['SETTINGS']['DIR']['/'] == 'Y';
204
205 $runtimeData = [
206 'PID' => $this->sitemapId,
207 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_DIR,
208 'ITEM_PATH' => '/',
209 'PROCESSED' => RuntimeTable::UNPROCESSED,
210 'ACTIVE' => $isRootChecked ? RuntimeTable::ACTIVE : RuntimeTable::INACTIVE,
211 ];
212
213 try
214 {
215 $resAdd = RuntimeTable::add($runtimeData);
216 }
217 catch (\Exception $e)
218 {
219 return false;
220 }
221
222 if ($resAdd->isSuccess())
223 {
224 $this->step++;
225 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FILES', ['#PATH#' => '/']);
226 }
227
228 return $resAdd->isSuccess();
229 }
230
231 protected function runFiles(): bool
232 {
233 $this->sitemapFile =
234 new File\Runtime(
235 $this->sitemapId,
236 $this->sitemapData['SETTINGS']['FILENAME_FILES'],
237 $this->getSitemapSettings()
238 );
239
240 $isFinished = false;
241 $isCheckFinished = false;
242 $dbRes = null;
243
244 while (!$isFinished && !self::isStepTimeOver())
245 {
246 if (!$dbRes)
247 {
248 $dbRes = RuntimeTable::getList([
249 'order' => ['ITEM_PATH' => 'ASC'],
250 'filter' => [
251 'PID' => $this->sitemapId,
252 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_DIR,
253 'PROCESSED' => RuntimeTable::UNPROCESSED,
254 ],
255 'limit' => 1000,
256 ]);
257 }
258
259 if ($dirData = $dbRes->Fetch())
260 {
261 $this->processDirectory($dirData);
262 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FILES', ['#PATH#' => $dirData['ITEM_PATH']]);
263 $isCheckFinished = false;
264 }
265 elseif (!$isCheckFinished)
266 {
267 $dbRes = null;
268 $isCheckFinished = true;
269 }
270 else
271 {
272 $isFinished = true;
273 }
274 }
275
276 if (!$isFinished)
277 {
278 if ($this->step < Step::STEPS[Step::STEP_FILES] - 1)
279 {
280 $this->step++;
281 }
282 }
283 else
284 {
285 // todo: check state by whitelist
286 if (!is_array($this->state['XML_FILES']))
287 {
288 $this->state['XML_FILES'] = [];
289 }
290
291 $this->finishSitemapFile();
292
293 $this->step = Step::STEPS[Step::STEP_FILES];
294 $this->statusMessage = Loc::getMessage(
295 'SITEMAP_RUN_FILE_COMPLETE',
296 ['#FILE#' => $this->sitemapData['SETTINGS']['FILENAME_FILES']]
297 );
298 }
299
300 return true;
301 }
302
308 protected function processDirectory($dirData): void
309 {
310 $processedDirs = [];
311
312 if ($dirData['ACTIVE'] == RuntimeTable::ACTIVE)
313 {
314 $directories = \CSeoUtils::getDirStructure(
315 $this->sitemapData['SETTINGS']['logical'] == 'Y',
316 $this->sitemapData['SITE_ID'],
317 $dirData['ITEM_PATH']
318 );
319
320 foreach ($directories as $dir)
321 {
322 $dirKey = "/" . ltrim($dir['DATA']['ABS_PATH'], "/");
323
324 if ($dir['TYPE'] == 'F')
325 {
326 if (
327 !isset($this->sitemapData['SETTINGS']['FILE'][$dirKey])
328 || $this->sitemapData['SETTINGS']['FILE'][$dirKey] == 'Y'
329 )
330 {
331 if (preg_match($this->sitemapData['SETTINGS']['FILE_MASK_REGEXP'], $dir['FILE']))
332 {
333 $f = new IO\File($dir['DATA']['PATH'], $this->sitemapData['SITE_ID']);
334 $this->sitemapFile->addFileEntry($f);
335 }
336 }
337 }
338 else
339 {
340 if (!isset($this->sitemapData['SETTINGS']['DIR'][$dirKey])
341 || $this->sitemapData['SETTINGS']['DIR'][$dirKey] == 'Y')
342 {
343 $processedDirs[] = $dirKey;
344 }
345 }
346 }
347 }
348 else
349 {
350 $len = mb_strlen($dirData['ITEM_PATH']);
351 if (!empty($this->sitemapData['SETTINGS']['DIR']))
352 {
353 foreach ($this->sitemapData['SETTINGS']['DIR'] as $dirKey => $checked)
354 {
355 if ($checked == 'Y')
356 {
357 if (strncmp($dirData['ITEM_PATH'], $dirKey, $len) === 0)
358 {
359 $processedDirs[] = $dirKey;
360 }
361 }
362 }
363 }
364
365 if (!empty($this->sitemapData['SETTINGS']['FILE']))
366 {
367 foreach ($this->sitemapData['SETTINGS']['FILE'] as $dirKey => $checked)
368 {
369 if ($checked == 'Y')
370 {
371 if (strncmp($dirData['ITEM_PATH'], $dirKey, $len) === 0)
372 {
374 SiteTable::getDocumentRoot($this->sitemapData['SITE_ID']),
375 $dirKey
376 );
377
378 if (!is_dir($fileName))
379 {
380 $f = new IO\File($fileName, $this->sitemapData['SITE_ID']);
381 if (
382 $f->isExists()
383 && !$f->isSystem()
384 && preg_match($this->sitemapData['SETTINGS']['FILE_MASK_REGEXP'], $f->getName())
385 )
386 {
387 $this->sitemapFile->addFileEntry($f);
388 }
389 }
390 }
391 }
392 }
393 }
394 }
395
396 if (is_array($processedDirs) && !empty($processedDirs))
397 {
398 foreach ($processedDirs as $dirKey)
399 {
400 $runtimeData = [
401 'PID' => $this->sitemapId,
402 'ITEM_PATH' => $dirKey,
403 'PROCESSED' => RuntimeTable::UNPROCESSED,
404 'ACTIVE' => RuntimeTable::ACTIVE,
405 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_DIR,
406 ];
407 RuntimeTable::add($runtimeData);
408 }
409 }
410
411 RuntimeTable::update($dirData['ID'], [
412 'PROCESSED' => RuntimeTable::PROCESSED,
413 ]);
414 }
415
416 protected function runIblockIndex(): bool
417 {
418 $result = true;
419
420 $iblockToProcess = [];
421 if (Loader::includeModule('iblock'))
422 {
423 $iblockToProcess = $this->sitemapData['SETTINGS']['IBLOCK_ACTIVE'];
424 if (is_array($iblockToProcess) && !empty($iblockToProcess))
425 {
426 $arIBlocks = [];
427 $dbIBlock = \CIBlock::GetList([], ['ID' => array_keys($iblockToProcess)]);
428 while ($arIBlock = $dbIBlock->Fetch())
429 {
430 $arIBlocks[$arIBlock['ID']] = $arIBlock;
431 }
432
433 foreach ($iblockToProcess as $iblockId => $iblockActive)
434 {
435 if ($iblockActive !== 'Y' || !array_key_exists($iblockId, $arIBlocks))
436 {
437 unset($iblockToProcess[$iblockId]);
438 }
439 else
440 {
441 RuntimeTable::add([
442 'PID' => $this->sitemapId,
443 'PROCESSED' => RuntimeTable::UNPROCESSED,
444 'ITEM_ID' => $iblockId,
445 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_IBLOCK,
446 ]);
447 }
448 }
449 }
450 }
451
452 $this->state['LEFT_MARGIN'] = 0;
453 $this->state['IBLOCK_LASTMOD'] = 0;
454
455 $this->state['IBLOCK'] = [];
456 $this->state['IBLOCK_MAP'] = [];
457
458 if (is_array($iblockToProcess) && !empty($iblockToProcess))
459 {
460 $this->step = Step::STEPS[Step::STEP_IBLOCK_INDEX];
461 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_IBLOCK');
462 }
463 else
464 {
465 $this->step = Step::STEPS[Step::STEP_IBLOCK];
466 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_IBLOCK_EMPTY');
467 }
468
469 return $result;
470 }
471
472 protected function runIblock(): bool
473 {
474 $result = true;
475 $isFinished = false;
476
477 $this->currentRuntimeIBlock = null;
478 $this->currentIBlock = null;
479 $this->sitemapFile = null;
480
481 if (!Loader::includeModule('iblock'))
482 {
483 $isFinished = true;
484 }
485
486 if (isset($_SESSION["SEO_SITEMAP_" . $this->sitemapId]))
487 {
488 $this->state['IBLOCK_MAP'] = $_SESSION["SEO_SITEMAP_" . $this->sitemapId];
489 unset($_SESSION["SEO_SITEMAP_" . $this->sitemapId]);
490 }
491
492 while (!$isFinished)
493 {
494 if (self::isStepTimeOver())
495 {
496 $isFinished = false;
497
498 break;
499 }
500
501 if (!$this->currentRuntimeIBlock)
502 {
503 $dbRes = RuntimeTable::getList([
504 'order' => ['ID' => 'ASC'],
505 'filter' => [
506 'PID' => $this->sitemapId,
507 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_IBLOCK,
508 'PROCESSED' => RuntimeTable::UNPROCESSED,
509 ],
510 'limit' => 1,
511 ]);
512 $runtimeIblock = $dbRes->fetch();
513 $this->currentRuntimeIBlock = $runtimeIblock !== false ? $runtimeIblock : null;
514
515 if ($this->currentRuntimeIBlock)
516 {
517 $iblockId = (int)$this->currentRuntimeIBlock['ITEM_ID'];
518
519 $dbIBlock = \CIBlock::GetByID($iblockId);
520 $this->currentIBlock = $dbIBlock->Fetch();
521
522 if (!$this->currentIBlock)
523 {
524 $this->state['LEFT_MARGIN'] = 0;
525 $this->state['IBLOCK_LASTMOD'] = 0;
526 $this->state['LAST_ELEMENT_ID'] = 0;
527 unset($this->state['CURRENT_SECTION']);
528 unset($this->currentRuntimeIBlock);
529 }
530 else
531 {
532 $this->statusMessage = Loc::getMessage(
533 'SITEMAP_RUN_IBLOCK_NAME',
534 ['#IBLOCK_NAME#' => $this->currentIBlock['NAME']]
535 );
536
537 if ($this->currentIBlock['LIST_PAGE_URL'] == '')
538 {
539 $this->sitemapData['SETTINGS']['IBLOCK_LIST'][$iblockId] = 'N';
540 }
541 if ($this->currentIBlock['SECTION_PAGE_URL'] == '')
542 {
543 $this->sitemapData['SETTINGS']['IBLOCK_SECTION'][$iblockId] = 'N';
544 }
545 if ($this->currentIBlock['DETAIL_PAGE_URL'] == '')
546 {
547 $this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] = 'N';
548 }
549
550 $this->state['IBLOCK_LASTMOD'] =
551 max($this->state['IBLOCK_LASTMOD'], MakeTimeStamp($this->currentIBlock['TIMESTAMP_X']));
552
553 if (
554 $this->state['LEFT_MARGIN'] <= 0
555 && $this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] !== 'N'
556 )
557 {
558 $this->state['CURRENT_SECTION'] = 0;
559 }
560
561 $fileName = str_replace(
562 ['#IBLOCK_ID#', '#IBLOCK_CODE#', '#IBLOCK_XML_ID#'],
563 [$iblockId, $this->currentIBlock['CODE'], $this->currentIBlock['XML_ID']],
564 $this->sitemapData['SETTINGS']['FILENAME_IBLOCK']
565 );
566
567 $this->sitemapFile =
568 new File\Runtime(
569 $this->sitemapId,
570 $fileName,
571 $this->getSitemapSettings()
572 );
573 }
574 }
575 }
576
577 if (!$this->currentRuntimeIBlock || !$this->sitemapFile)
578 {
579 $isFinished = true;
580 }
581 elseif (is_array($this->currentIBlock))
582 {
583 $isFinishedSections = false;
584 if (!isset($this->state['CURRENT_SECTION']))
585 {
586 $isFinishedSections = self::processIblockSections();
587 }
588
589 if ($isFinishedSections && !isset($this->state['CURRENT_SECTION']))
590 {
591 $isFinishedElements = true;
592 }
593 else
594 {
595 $isFinishedElements = self::processIblockElements();
596 }
597
598 if ($isFinishedSections && $isFinishedElements)
599 {
600 $this->finishIblockProcess();
601 }
602 }
603 }
604
605 if ($this->step < Step::STEPS[Step::STEP_IBLOCK] - 1)
606 {
607 $this->step++;
608 $this->step = min($this->step, Step::STEPS[Step::STEP_IBLOCK] - 1);
609 }
610
611 if ($isFinished)
612 {
613 $this->step = Step::STEPS[Step::STEP_IBLOCK];
614 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_IBLOCK');
615 }
616
617 return $result;
618 }
619
625 protected function processIblockSections(): bool
626 {
627 $iblockId = (int)$this->currentRuntimeIBlock['ITEM_ID'];
628
629 $this->state['LAST_ELEMENT_ID'] = 0;
630 $dbIblockResult = \CIBlockSection::GetList(
631 ['LEFT_MARGIN' => 'ASC'],
632 [
633 'IBLOCK_ID' => $iblockId,
634 'GLOBAL_ACTIVE' => 'Y',
635 '>LEFT_BORDER' => intval($this->state['LEFT_MARGIN']),
636 ],
637 false,
638 ['ID', 'TIMESTAMP_X', 'SECTION_PAGE_URL', 'LEFT_MARGIN', 'IBLOCK_SECTION_ID'],
639 ['nTopCount' => 100]
640 );
641 $processedSections = 0;
642
643 while ($arSection = $dbIblockResult->fetch())
644 {
645 if ($this->isStepTimeOver())
646 {
647 break;
648 }
649
650 $sectionLastmod = MakeTimeStamp($arSection['TIMESTAMP_X']);
651 $this->state['LEFT_MARGIN'] = $arSection['LEFT_MARGIN'];
652 $this->state['IBLOCK_LASTMOD'] = max($this->state['IBLOCK_LASTMOD'], $sectionLastmod);
653
654 $isProcessSections = false;
655 $isProcessElements = false;
656
657 if (isset($this->sitemapData['SETTINGS']['IBLOCK_SECTION_SECTION'][$iblockId][$arSection['ID']]))
658 {
659 $isProcessSections =
660 $this->sitemapData['SETTINGS']['IBLOCK_SECTION_SECTION'][$iblockId][$arSection['ID']] == 'Y';
661 $isProcessElements =
662 $this->sitemapData['SETTINGS']['IBLOCK_SECTION_ELEMENT'][$iblockId][$arSection['ID']] == 'Y';
663 }
664 elseif ($arSection['IBLOCK_SECTION_ID'] > 0)
665 {
666 $dbRes = RuntimeTable::getList([
667 'filter' => [
668 'PID' => $this->sitemapId,
669 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_SECTION,
670 'ITEM_ID' => $arSection['IBLOCK_SECTION_ID'],
671 'PROCESSED' => RuntimeTable::PROCESSED,
672 ],
673 'select' => ['ACTIVE', 'ACTIVE_ELEMENT'],
674 'limit' => 1,
675 ]);
676
677 $parentSection = $dbRes->fetch();
678 if ($parentSection)
679 {
680 $isProcessSections = $parentSection['ACTIVE'] === RuntimeTable::ACTIVE;
681 $isProcessElements = $parentSection['ACTIVE_ELEMENT'] === RuntimeTable::ACTIVE;
682 }
683 }
684 else
685 {
686 $isProcessSections = $this->sitemapData['SETTINGS']['IBLOCK_SECTION'][$iblockId] == 'Y';
687 $isProcessElements = $this->sitemapData['SETTINGS']['IBLOCK_ELEMENT'][$iblockId] == 'Y';
688 }
689
690 $arRuntimeData = [
691 'PID' => $this->sitemapId,
692 'ITEM_ID' => $arSection['ID'],
693 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_SECTION,
694 'ACTIVE' => $isProcessSections ? RuntimeTable::ACTIVE : RuntimeTable::INACTIVE,
695 'ACTIVE_ELEMENT' => $isProcessElements ? RuntimeTable::ACTIVE : RuntimeTable::INACTIVE,
696 'PROCESSED' => RuntimeTable::PROCESSED,
697 ];
698
699 if ($isProcessSections)
700 {
701 $this->state['IBLOCK'][$iblockId]['S']++;
702 $arSection['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];
703
704 // remove or replace SERVER_NAME
705 $url =
707 $arSection['SECTION_PAGE_URL'],
708 $this->sitemapData['SITE_ID']
709 );
710 $url = \CIBlock::ReplaceDetailUrl($url, $arSection, false, "S");
711
712 $this->sitemapFile->addIBlockEntry($url, $sectionLastmod);
713 }
714
715 RuntimeTable::add($arRuntimeData);
716
717 if ($isProcessElements)
718 {
719 $this->state['CURRENT_SECTION'] = (int)$arSection['ID'];
720 $this->state['LAST_ELEMENT_ID'] = 0;
721
722 return false;
723 }
724
725 $processedSections++;
726 }
727
728 if ($processedSections === 0)
729 {
731
732 return true;
733 }
734
735 // not finished yet
736 return false;
737 }
738
739 protected function finishIblockSectionsProcess(): void
740 {
741 unset($this->state['CURRENT_SECTION']);
742 $this->state['LEFT_MARGIN'] = 0;
743 $this->state['LAST_ELEMENT_ID'] = 0;
744 }
745
750 protected function processIblockElements(): bool
751 {
752 if (!isset($this->state['CURRENT_SECTION']))
753 {
755
756 return true;
757 }
758
759 $iblockId = (int)$this->currentRuntimeIBlock['ITEM_ID'];
760 $dbIblockResult = \CIBlockElement::GetList(
761 ['ID' => 'ASC'],
762 [
763 'IBLOCK_ID' => $iblockId,
764 'ACTIVE' => 'Y',
765 'SECTION_ID' => $this->state['CURRENT_SECTION'],
766 '>ID' => $this->state['LAST_ELEMENT_ID'],
767 'SITE_ID' => $this->sitemapData['SITE_ID'],
768 "ACTIVE_DATE" => "Y",
769 ],
770 false,
771 ['nTopCount' => 100],
772 ['ID', 'TIMESTAMP_X', 'DETAIL_PAGE_URL']
773 );
774 $processedElements = 0;
775
776 while ($arElement = $dbIblockResult->fetch())
777 {
778 if ($this->isStepTimeOver())
779 {
780 break;
781 }
782
783 if (!is_array($this->state['IBLOCK_MAP'][$iblockId]))
784 {
785 $this->state['IBLOCK_MAP'][$iblockId] = [];
786 }
787 if (!array_key_exists($arElement['ID'], $this->state['IBLOCK_MAP'][$iblockId]))
788 {
789 $arElement['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];
790
791 $elementLastmod = MakeTimeStamp($arElement['TIMESTAMP_X']);
792 $this->state['IBLOCK_LASTMOD'] = max($this->state['IBLOCK_LASTMOD'], $elementLastmod);
793 $this->state['LAST_ELEMENT_ID'] = $arElement['ID'];
794
795 $this->state['IBLOCK'][$iblockId]['E']++;
796 $this->state['IBLOCK_MAP'][$iblockId][$arElement["ID"]] = 1;
797
798 // remove or replace SERVER_NAME
799 $url =
801 $arElement['DETAIL_PAGE_URL'],
802 $this->sitemapData['SITE_ID']
803 );
804 $url = \CIBlock::ReplaceDetailUrl($url, $arElement, false, "E");
805
806 $this->sitemapFile->addIBlockEntry($url, $elementLastmod);
807
808 $processedElements++;
809 }
810 }
811
812 if ($processedElements === 0)
813 {
815
816 return true;
817 }
818
819 // not finished yet
820 return false;
821 }
822
823 protected function finishIblockElementsProcess(): void
824 {
825 unset($this->state['CURRENT_SECTION']);
826 $this->state['LAST_ELEMENT_ID'] = 0;
827 }
828
829 protected function finishIblockProcess(): void
830 {
831 $iblockId = (int)$this->currentRuntimeIBlock['ID'];
832 if (!$iblockId)
833 {
834 return;
835 }
836
837 RuntimeTable::update($iblockId, [
838 'PROCESSED' => RuntimeTable::PROCESSED,
839 ]);
840
841 if (
842 $this->sitemapData['SETTINGS']['IBLOCK_LIST'][$iblockId] == 'Y'
843 && $this->currentIBlock['LIST_PAGE_URL'] <> ''
844 )
845 {
846 $this->state['IBLOCK'][$iblockId]['I']++;
847
848 $this->currentIBlock['IBLOCK_ID'] = $this->currentIBlock['ID'];
849 $this->currentIBlock['LANG_DIR'] = $this->sitemapData['SITE']['DIR'];
850
851 // remove or replace SERVER_NAME
852 $url =
854 $this->currentIBlock['LIST_PAGE_URL'],
855 $this->sitemapData['SITE_ID']
856 );
857 $url = \CIBlock::ReplaceDetailUrl($url, $this->currentIBlock, false, "");
858
859 $this->sitemapFile->addIBlockEntry($url, $this->state['IBLOCK_LASTMOD']);
860 }
861
863
864 $this->currentRuntimeIBlock = null;
865 $this->state['IBLOCK_LASTMOD'] = 0;
866 unset($this->state['CURRENT_SECTION']);
867 }
868
869 protected function runForumIndex(): bool
870 {
871 $result = true;
872
873 $forumToProcess = [];
874
875 if (Loader::includeModule('forum'))
876 {
877 if (!empty($this->sitemapData['SETTINGS']['FORUM_ACTIVE']))
878 {
879 foreach ($this->sitemapData['SETTINGS']['FORUM_ACTIVE'] as $forumId => $active)
880 {
881 if ($active == "Y")
882 {
883 $forumToProcess[$forumId] = "Y";
884 }
885 }
886 }
887 if (!empty($forumToProcess))
888 {
889 $arForums = [];
891 [],
892 [
893 '@ID' => array_keys($forumToProcess),
894 "ACTIVE" => "Y",
895 "SITE_ID" => $this->sitemapData['SITE_ID'],
896 "!TOPICS" => 0,
897 ]
898 );
899 while ($res = $db_res->Fetch())
900 {
901 $arForums[$res['ID']] = $res;
902 }
903 $forumToProcess = array_intersect_key($arForums, $forumToProcess);
904
905 foreach ($forumToProcess as $id => $forum)
906 {
907 RuntimeTable::add([
908 'PID' => $this->sitemapId,
909 'PROCESSED' => RuntimeTable::UNPROCESSED,
910 'ITEM_ID' => $id,
911 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_FORUM,
912 ]
913 );
914 }
915 }
916 }
917
918 $this->state['FORUM_CURRENT_TOPIC'] = 0;
919
920 if (is_array($forumToProcess) && !empty($forumToProcess))
921 {
922 $this->step = Step::STEPS[Step::STEP_FORUM_INDEX];
923 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FORUM');
924 }
925 else
926 {
927 $this->step = Step::STEPS[Step::STEP_FORUM];
928 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FORUM_EMPTY');
929 }
930
931 return $result;
932 }
933
934 protected function runForum(): bool
935 {
936 $result = true;
937
938 $isFinished = false;
939 $runtimeForum = false;
940 $currentForum = null;
941 $forumId = 0;
942 $this->sitemapFile = null;
943 $dbTopicResult = null;
944 $arTopic = null;
945
946 if (!Loader::includeModule('forum'))
947 {
948 $isFinished = true;
949 }
950
951 while (!$isFinished && !self::isStepTimeOver())
952 {
953 if (!$runtimeForum)
954 {
955 $dbRes = RuntimeTable::getList([
956 'order' => ['ID' => 'ASC'],
957 'filter' => [
958 'PID' => $this->sitemapId,
959 'ITEM_TYPE' => RuntimeTable::ITEM_TYPE_FORUM,
960 'PROCESSED' => RuntimeTable::UNPROCESSED,
961 ],
962 'limit' => 1,
963 ]);
964 $runtimeForum = $dbRes->fetch();
965
966 if ($runtimeForum)
967 {
968 $forumId = intval($runtimeForum['ITEM_ID']);
969
971 [],
972 [
973 'ID' => $forumId,
974 "ACTIVE" => "Y",
975 "SITE_ID" => $this->sitemapData['SITE_ID'],
976 "!TOPICS" => 0,
977 ]
978 );
979 $currentForum = $db_res->Fetch();
980 if ($currentForum)
981 {
982 $this->statusMessage = Loc::getMessage(
983 'SITEMAP_RUN_FORUM_NAME',
984 ['#FORUM_NAME#' => $currentForum['NAME']]
985 );
986
987 $fileName = str_replace('#FORUM_ID#', $forumId, $this->sitemapData['SETTINGS']['FILENAME_FORUM']);
988 $this->sitemapFile = new File\Runtime($this->sitemapId, $fileName, $this->getSitemapSettings());
989 }
990
991 RuntimeTable::update($runtimeForum['ID'], [
992 'PROCESSED' => RuntimeTable::PROCESSED,
993 ]);
994 }
995 }
996
997 if (!$runtimeForum || !$this->sitemapFile)
998 {
999 $isFinished = true;
1000 }
1001 elseif (is_array($currentForum))
1002 {
1003 $isActive =
1004 array_key_exists($forumId, $this->sitemapData['SETTINGS']['FORUM_TOPIC'])
1005 && $this->sitemapData['SETTINGS']['FORUM_TOPIC'][$forumId] == "Y"
1006 ;
1007 if ($isActive)
1008 {
1009 if ($dbTopicResult == null)
1010 {
1011 $dbTopicResult = \CForumTopic::GetList(
1012 ["LAST_POST_DATE" => "DESC"],
1013 array_merge(
1014 [
1015 "FORUM_ID" => $forumId,
1016 "APPROVED" => "Y",
1017 ],
1018 (
1019 $this->state['FORUM_CURRENT_TOPIC'] > 0
1020 ? [">ID" => $this->state["FORUM_CURRENT_TOPIC"]]
1021 : []
1022 )
1023 ),
1024 false,
1025 0,
1026 ['nTopCount' => 100]
1027 );
1028 }
1029 if (($arTopic = $dbTopicResult->fetch()) && $arTopic)
1030 {
1031 $this->state["FORUM_CURRENT_TOPIC"] = $arTopic["ID"];
1033 $currentForum["PATH2FORUM_MESSAGE"],
1034 [
1035 "FORUM_ID" => $currentForum["ID"],
1036 "TOPIC_ID" => $arTopic["ID"],
1037 "TITLE_SEO" => $arTopic["TITLE_SEO"],
1038 "MESSAGE_ID" => "s",
1039 "SOCNET_GROUP_ID" => $arTopic["SOCNET_GROUP_ID"],
1040 "OWNER_ID" => $arTopic["OWNER_ID"],
1041 "PARAM1" => $arTopic["PARAM1"],
1042 "PARAM2" => $arTopic["PARAM2"],
1043 ]
1044 );
1045 $this->sitemapFile->addIBlockEntry($url, MakeTimeStamp($arTopic['LAST_POST_DATE']));
1046 }
1047 }
1048 else
1049 {
1051 $currentForum["PATH2FORUM_MESSAGE"],
1052 [
1053 "FORUM_ID" => $currentForum["ID"],
1054 "TOPIC_ID" => $currentForum["TID"],
1055 "TITLE_SEO" => $currentForum["TITLE_SEO"],
1056 "MESSAGE_ID" => "s",
1057 "SOCNET_GROUP_ID" => $currentForum["SOCNET_GROUP_ID"],
1058 "OWNER_ID" => $currentForum["OWNER_ID"],
1059 "PARAM1" => $currentForum["PARAM1"],
1060 "PARAM2" => $currentForum["PARAM2"],
1061 ]
1062 );
1063 $this->sitemapFile->addIBlockEntry($url, MakeTimeStamp($currentForum['LAST_POST_DATE']));
1064 }
1065 if (empty($arTopic))
1066 {
1067 RuntimeTable::update($runtimeForum['ID'], [
1068 'PROCESSED' => RuntimeTable::PROCESSED,
1069 ]);
1070
1072
1073 $runtimeForum = false;
1074 $dbTopicResult = null;
1075 $this->state['FORUM_CURRENT_TOPIC'] = 0;
1076 }
1077 }
1078 }
1079 if ($this->step < Step::STEPS[Step::STEP_FORUM] - 1)
1080 {
1081 $this->step++;
1082 }
1083
1084 if ($isFinished)
1085 {
1086 $this->step = Step::STEPS[Step::STEP_FORUM];
1087 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FINALIZE');
1088 }
1089
1090 return $result;
1091 }
1092
1093 protected function finishSitemapFile(): void
1094 {
1095 if (!$this->sitemapFile)
1096 {
1097 return;
1098 }
1099
1100 if ($this->sitemapFile->isNotEmpty())
1101 {
1102 if ($this->sitemapFile->isCurrentPartNotEmpty())
1103 {
1104 $this->sitemapFile->finish();
1105 }
1106 else
1107 {
1108 $this->sitemapFile->delete();
1109 }
1110
1111 if (!is_array($this->state['XML_FILES']))
1112 {
1113 $this->state['XML_FILES'] = [];
1114 }
1115
1116 $xmlFiles = $this->sitemapFile->getNameList();
1117 $directory = $this->sitemapFile->getPathDirectory();
1118 foreach ($xmlFiles as &$xmlFile)
1119 {
1120 $xmlFile = $directory . $xmlFile;
1121 }
1122 $this->state['XML_FILES'] = array_unique(array_merge($this->state['XML_FILES'], $xmlFiles));
1123 }
1124 else
1125 {
1126 $this->sitemapFile->delete();
1127 }
1128 }
1129
1130 protected function runIndex(): bool
1131 {
1132 $result = true;
1133
1134 RuntimeTable::clearByPid($this->sitemapId);
1135
1136 $this->sitemapFile = new File\Index($this->sitemapData['SETTINGS']['FILENAME_INDEX'], $this->getSitemapSettings());
1137 $xmlFiles = [];
1138 if (is_array($this->state['XML_FILES']) && !empty($this->state['XML_FILES']))
1139 {
1140 foreach ($this->state['XML_FILES'] as $xmlFile)
1141 {
1142 $xmlFiles[] = new IO\File(
1144 $this->sitemapFile->getSiteRoot(),
1145 $xmlFile
1146 ), $this->sitemapData['SITE_ID']
1147 );
1148 }
1149 }
1150 $this->sitemapFile->createIndex($xmlFiles);
1151
1152 $existedSitemaps = [];
1153 if ($this->sitemapData['SETTINGS']['ROBOTS'] == 'Y')
1154 {
1155 $sitemapUrl = $this->sitemapFile->getUrl();
1156
1157 $robotsFile = new RobotsFile($this->sitemapData['SITE_ID']);
1158 $robotsFile->addRule([
1159 RobotsFile::SITEMAP_RULE, $sitemapUrl,
1160 ]);
1161
1162 $sitemapLinks = $robotsFile->getRules(RobotsFile::SITEMAP_RULE);
1163 if (count($sitemapLinks) > 1) // 1 - just added rule
1164 {
1165 foreach ($sitemapLinks as $rule)
1166 {
1167 if ($rule[1] != $sitemapUrl)
1168 {
1169 $existedSitemaps[] = $rule[1];
1170 }
1171 }
1172 }
1173 }
1174 // todo: need show message about robots.txt
1175 // if (isset($arExistedSitemaps) && count($arExistedSitemaps) > 0)
1176 // {
1177 // echo BeginNote(), Loc::getMessage('SEO_SITEMAP_RUN_ROBOTS_WARNING', array(
1178 // "#SITEMAPS#" => "<li>" . implode("</li><li>", $arExistedSitemaps) . "</li>",
1179 // "#LANGUAGE_ID#" => LANGUAGE_ID,
1180 // "#SITE_ID#" => $arSitemap['SITE_ID'],
1181 // ));
1182 // }
1183
1184 $this->step = Step::STEPS[Step::STEP_INDEX];
1185 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FINISH');
1186
1187 return $result;
1188 }
1189
1190 protected function finish(): bool
1191 {
1192 $this->statusMessage = Loc::getMessage('SITEMAP_RUN_FINISH');
1193 SitemapTable::update($this->sitemapId, ['DATE_RUN' => new DateTime()]);
1194
1195 return true;
1196 }
1197
1198
1203 protected function getSitemapSettings(): array
1204 {
1205 return [
1206 'SITE_ID' => $this->sitemapData['SITE_ID'],
1207 'PROTOCOL' => $this->sitemapData['SETTINGS']['PROTO'] == 1 ? 'https' : 'http',
1208 'DOMAIN' => $this->sitemapData['SETTINGS']['DOMAIN'],
1209 ];
1210 }
1211
1212 protected function startStep(): void
1213 {
1214 $this->stepStartTime = microtime(true);
1215 }
1216
1221 protected function isStepTimeOver(): bool
1222 {
1223 return microtime(true) > ($this->stepStartTime + self::STEP_DURATION * 0.95);
1224 }
1225}
$db_res
Определения options_user_settings.php:8
while($arIBType=$dbIBlockType->Fetch()) $dbIBlock
Определения options.php:178
while($arRes=$dbSites->GetNext()) $arForums
Определения options.php:34
static combine(... $args)
Определения path.php:254
const SITEMAP_RULE
Определения robotsfile.php:17
processIblockSections()
Определения Generator.php:625
processIblockElements()
Определения Generator.php:750
array $sitemapData
Определения Generator.php:37
int $sitemapId
Определения Generator.php:31
const STEP_DURATION
Определения Generator.php:25
processDirectory($dirData)
Определения Generator.php:308
finishIblockSectionsProcess()
Определения Generator.php:739
init(int $step, array $state)
Определения Generator.php:106
__construct(int $sitemapId)
Определения Generator.php:81
array $currentRuntimeIBlock
Определения Generator.php:73
array $currentIBlock
Определения Generator.php:79
array $state
Определения Generator.php:55
string $statusMessage
Определения Generator.php:61
finishIblockElementsProcess()
Определения Generator.php:823
finishIblockProcess()
Определения Generator.php:829
File Base $sitemapFile
Определения Generator.php:67
int $stepStartTime
Определения Generator.php:49
static clearByPid(int $pid)
Определения Runtime.php:81
static prepareUrlToReplace($url, $siteId=null)
Определения Iblock.php:77
static PreparePath2Message($strPath, $arVals=array())
Определения forum_new.php:1801
static GetListEx($arOrder=Array("SORT"=>"ASC"), $arFilter=Array(), $bCount=false, $iNum=0, $arAddParams=array())
Определения forum_new.php:936
static GetList($arOrder=Array("SORT"=>"ASC"), $arFilter=Array(), $bCount=false, $iNum=0, $arAddParams=array())
Определения topic.php:6
static getDirStructure($bLogical, $site, $path)
Определения seo_utils.php:91
$f
Определения component_props.php:52
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$iblockId
Определения iblock_catalog_edit.php:30
MakeTimeStamp($datetime, $format=false)
Определения tools.php:538
Определения Image.php:9
Определения directory.php:3
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$dir
Определения quickway.php:303
$fileName
Определения quickway.php:305
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$url
Определения iframe.php:7
$dbRes
Определения yandex_detail.php:168
$arIBlock['PROPERTY']
Определения yandex_detail.php:172