3namespace Bitrix\UI\EntitySelector;
5use Bitrix\Main\Localization\Loc;
6use Bitrix\Main\ORM\Fields\ExpressionField;
7use Bitrix\Main\UI\EntitySelector\EntityUsageTable;
9class Dialog implements \JsonSerializable
61 foreach (
$options[
'entities'] as $entityOptions)
63 if (is_array($entityOptions))
76 $this->
id = $options[
'id'];
81 $this->context =
$options[
'context'];
84 if (isset(
$options[
'clearUnavailableItems']) && is_bool(
$options[
'clearUnavailableItems']))
86 $this->clearUnavailableItems =
$options[
'clearUnavailableItems'];
95 if (isset(
$options[
'preselectedItems']) && is_array(
$options[
'preselectedItems']))
100 if (isset(
$options[
'recentItemsLimit']) && is_int(
$options[
'recentItemsLimit']))
102 $this->recentItemsLimit = max(1, min(
$options[
'recentItemsLimit'], static::MAX_RECENT_ITEMS_LIMIT));
153 'id' => $item->
getId(),
222 $recentItem->setLoaded(
true);
228 if ($globalRecentItem)
230 $globalRecentItem->setLoaded(
true);
235 if ($preselectedItem && !$preselectedItem->getItem())
237 $preselectedItem->setItem($item);
258 if (!empty($tab->
getId()))
260 $this->tabs[$tab->
getId()] = $tab;
274 return $this->tabs[$tabId] ??
null;
300 return $this->entities[
$entityId] ??
null;
330 $this->
getEntity($entityId)->getProvider()->fillDialog($this);
333 $this->loadRecentItems();
356 if ($hasDynamicSearch)
370 $this->
getEntity($entityId)->getProvider()->doSearch($searchQuery, $this);
393 $entity->getProvider()->getChildren($parentItem, $this);
424 if (!
$entity && $preselectedMode)
426 $this->
addItem(self::createHiddenItem($preselectedItem->getId(),
$entityId));
428 else if (!$preselectedItem->isLoaded())
430 $unloadedIds[] = $preselectedItem->getId();
434 if (
$entity && !empty($unloadedIds))
436 $availableItems = [];
439 ?
$entity->getProvider()->getPreselectedItems($unloadedIds)
440 :
$entity->getProvider()->getItems($unloadedIds)
445 $availableItems[$item->getId()] = $item;
448 foreach ($unloadedIds as $unloadedId)
450 $item = $availableItems[$unloadedId] ??
null;
455 else if ($preselectedMode)
474 'title' => Loc::getMessage(
"UI_SELECTOR_HIDDEN_ITEM_TITLE"),
476 'deselectable' =>
false,
477 'searchable' =>
false,
481 'availableInRecentTab' =>
false,
491 return self::getItemsInternal($ids,
$options,
true);
496 return self::getItemsInternal($ids,
$options,
true);
501 return self::getItemsInternal($ids,
$options,
false);
509 $dialog =
new self($dialogOptions);
510 $dialog->setPreselectedItems($ids);
511 $dialog->loadPreselectedItems($preselectedMode);
512 $dialog->applyFilters();
514 return $dialog->getItemCollection();
524 $this->errors->add(
$error);
534 foreach ($recentItems as $recentItemOptions)
536 if (!is_array($recentItemOptions))
541 $recentItem =
new Item($recentItemOptions);
546 $entity->getProvider()->handleBeforeItemSave($recentItem);
547 if ($recentItem->isSaveable())
549 EntityUsageTable::merge([
552 'ENTITY_ID' => $recentItem->getEntityId(),
553 'ITEM_ID' => $recentItem->getId(),
569 $usages = $this->getGlobalUsages(
$entities, $this->recentItemsLimit);
570 while ($usage = $usages->fetch())
575 'id' => $usage[
'ITEM_ID'],
576 'entityId' => $usage[
'ENTITY_ID'],
577 'lastUseDate' => $usage[
'MAX_LAST_USE_DATE']->getTimestamp(),
585 $usages = $this->getContextUsages(
$entities, $this->recentItemsLimit);
586 foreach ($usages as $usage)
591 'id' => $usage->getItemId(),
592 'entityId' => $usage->getEntityId(),
593 'lastUseDate' => $usage->getLastUseDate()->getTimestamp(),
608 $usages = $this->getGlobalUsages(
$entities);
609 while ($usage = $usages->fetch())
614 'id' => $usage[
'ITEM_ID'],
615 'entityId' => $usage[
'ENTITY_ID'],
616 'lastUseDate' => $usage[
'MAX_LAST_USE_DATE']->
getTimestamp(),
623 private function getContextUsages(
array $entities,
int $limit = 50)
625 return EntityUsageTable::getList(
635 'LAST_USE_DATE' =>
'DESC',
638 )->fetchCollection();
641 private function getGlobalUsages(
array $entities,
int $limit = 200)
643 $query = EntityUsageTable::query();
644 $query->setSelect([
'ENTITY_ID',
'ITEM_ID',
'MAX_LAST_USE_DATE']);
645 $query->setGroup([
'ENTITY_ID',
'ITEM_ID']);
654 $query->registerRuntimeField(
new ExpressionField(
'MAX_LAST_USE_DATE',
'MAX(%s)',
'LAST_USE_DATE'));
655 $query->setOrder([
'MAX_LAST_USE_DATE' =>
'desc']);
661 private function loadRecentItems()
666 $unavailableIds = [];
670 if (!$recentItem->isAvailable())
672 $unavailableIds[] = $recentItem->getId();
674 else if (!$recentItem->isLoaded())
676 $unloadedIds[] = $recentItem->getId();
680 if (!empty($unloadedIds))
682 $availableItems = [];
686 if ($item instanceof Item)
688 $availableItems[$item->getId()] = $item;
692 foreach ($unloadedIds as $unloadedId)
694 $item = $availableItems[$unloadedId] ??
null;
695 if ($item && $item->isAvailableInRecentTab())
701 $unavailableIds[] = $unloadedId;
708 EntityUsageTable::deleteByFilter([
711 '=ENTITY_ID' =>
$entity->getId(),
712 '@ITEM_ID' => $unavailableIds,
728 $filters =
$entity->getFilters();
749 'id' => $this->
getId(),
751 'tabs' => array_values($this->
getTabs()),
787 unset($this->tabs[
$id]);
__construct(array $options)
getChildren(Item $parentItem)
loadPreselectedItems($preselectedMode=true)
const MAX_RECENT_ITEMS_LIMIT
setPreselectedItems(array $preselectedItems)
shouldClearUnavailableItems()
addError(EntityError $error)
setFooter(string $footer, array $options=[])
static getSelectedItems(array $ids, array $options=[])
getEntity(string $entityId)
static getItems(array $ids, array $options=[])
doSearch(SearchQuery $searchQuery)
setHeader(string $header, array $options=[])
static createHiddenItem($id, $entityId)
static getPreselectedItems(array $ids, array $options=[])
addEntity(Entity $entity)
saveRecentItems(array $recentItems)
addRecentItem(Item $item)
getPreselectedCollection()
addRecentItems(array $items)
handleItemAdd(Item $item)
static create(array $entityOptions)
setDialog(Dialog $dialog)
setContextSort(?int $sort)
setGlobalSort(?int $sort)
hasDynamicSearchEntity(string $entityId)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
</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."%"
$GLOBALS['_____370096793']