9class Dialog implements \JsonSerializable
51 if (isset($options[
'entities']) && is_array($options[
'entities']))
53 foreach ($options[
'entities'] as $entityOptions)
55 if (is_array($entityOptions))
66 if (isset($options[
'id']) && is_string($options[
'id']))
68 $this->
id = $options[
'id'];
71 if (isset($options[
'context']) && is_string($options[
'context']) && strlen($options[
'context']) > 0)
73 $this->context = $options[
'context'];
76 if (isset($options[
'clearUnavailableItems']) && is_bool($options[
'clearUnavailableItems']))
78 $this->clearUnavailableItems = $options[
'clearUnavailableItems'];
86 if (isset($options[
'preselectedItems']) && is_array($options[
'preselectedItems']))
92 public function getId(): ?string
109 return is_object($GLOBALS[
'USER']) ? $GLOBALS[
'USER']->getId() : 0;
123 foreach ($items as $item)
139 'id' => $item->
getId(),
150 foreach ($items as $item)
161 $this->headerOptions = $options;
180 $this->footerOptions = $options;
201 $recentItem->setLoaded(
true);
207 if ($globalRecentItem)
209 $globalRecentItem->setLoaded(
true);
214 if ($preselectedItem && !$preselectedItem->getItem())
216 $preselectedItem->setItem($item);
237 if (!empty($tab->
getId()))
239 $this->tabs[$tab->
getId()] = $tab;
253 return $this->tabs[$tabId] ??
null;
258 if (!empty($entity->
getId()))
260 $this->entities[$entity->
getId()] = $entity;
279 return $this->entities[$entityId] ??
null;
290 if ($entity->hasDynamicLoad())
309 $this->
getEntity($entityId)->getProvider()->fillDialog($this);
312 $this->loadRecentItems();
331 $entity->isSearchable() &&
335 if ($hasDynamicSearch)
349 $this->
getEntity($entityId)->getProvider()->doSearch($searchQuery, $this);
362 if ($entity->hasDynamicLoad())
369 if ($entity && $entity->hasDynamicLoad())
372 $entity->getProvider()->getChildren($parentItem, $this);
403 if (!$entity && $preselectedMode)
405 $this->
addItem(self::createHiddenItem($preselectedItem->getId(), $entityId));
407 else if (!$preselectedItem->isLoaded())
409 $unloadedIds[] = $preselectedItem->getId();
413 if ($entity && !empty($unloadedIds))
415 $availableItems = [];
418 ? $entity->getProvider()->getPreselectedItems($unloadedIds)
419 : $entity->getProvider()->getItems($unloadedIds)
422 foreach ($items as $item)
424 $availableItems[$item->getId()] = $item;
427 foreach ($unloadedIds as $unloadedId)
429 $item = $availableItems[$unloadedId] ??
null;
434 else if ($preselectedMode)
436 $this->
addItem(self::createHiddenItem($unloadedId, $entityId));
452 'entityId' => $entityId,
455 'deselectable' =>
false,
456 'searchable' =>
false,
460 'availableInRecentTab' =>
false
470 return self::getItemsInternal($ids, $options,
true);
475 return self::getItemsInternal($ids, $options,
true);
480 return self::getItemsInternal($ids, $options,
false);
483 private static function getItemsInternal(array $ids, array $options = [], $preselectedMode =
true):
ItemCollection
485 $isAssocArray = array_keys($options) !== range(0, count($options) - 1);
486 $dialogOptions = $isAssocArray ? $options : [
'entities' => $options];
488 $dialog =
new self($dialogOptions);
489 $dialog->setPreselectedItems($ids);
490 $dialog->loadPreselectedItems($preselectedMode);
491 $dialog->applyFilters();
493 return $dialog->getItemCollection();
503 foreach ($recentItems as $recentItemOptions)
505 if (!is_array($recentItemOptions))
510 $recentItem =
new Item($recentItemOptions);
511 $entity = $this->
getEntity($recentItem->getEntityId());
515 $entity->getProvider()->handleBeforeItemSave($recentItem);
516 if ($recentItem->isSaveable())
518 EntityUsageTable::merge([
519 'USER_ID' => $GLOBALS[
'USER']->
getId(),
521 'ENTITY_ID' => $recentItem->getEntityId(),
522 'ITEM_ID' => $recentItem->getId()
529 private function fillRecentItems(array
$entities)
538 $usages = $this->getGlobalUsages(
$entities, 50);
539 while ($usage = $usages->fetch())
544 'id' => $usage[
'ITEM_ID'],
545 'entityId' => $usage[
'ENTITY_ID'],
546 'lastUseDate' => $usage[
'MAX_LAST_USE_DATE']->getTimestamp()
554 $usages = $this->getContextUsages(
$entities);
555 foreach ($usages as $usage)
560 'id' => $usage->getItemId(),
561 'entityId' => $usage->getEntityId(),
562 'lastUseDate' => $usage->getLastUseDate()->getTimestamp()
570 private function fillGlobalRecentItems(array
$entities)
577 $usages = $this->getGlobalUsages(
$entities);
578 while ($usage = $usages->fetch())
583 'id' => $usage[
'ITEM_ID'],
584 'entityId' => $usage[
'ENTITY_ID'],
585 'lastUseDate' => $usage[
'MAX_LAST_USE_DATE']->
getTimestamp()
592 private function getContextUsages(array
$entities)
594 return EntityUsageTable::getList(
600 '@ENTITY_ID' => $entities
604 'LAST_USE_DATE' =>
'DESC'
607 )->fetchCollection();
610 private function getGlobalUsages(array
$entities,
int $limit = 200)
612 $query = EntityUsageTable::query();
613 $query->setSelect([
'ENTITY_ID',
'ITEM_ID',
'MAX_LAST_USE_DATE']);
614 $query->setGroup([
'ENTITY_ID',
'ITEM_ID']);
620 $query->whereNot(
'CONTEXT', $this->
getContext());
623 $query->registerRuntimeField(
new ExpressionField(
'MAX_LAST_USE_DATE',
'MAX(%s)',
'LAST_USE_DATE'));
624 $query->setOrder([
'MAX_LAST_USE_DATE' =>
'desc']);
625 $query->setLimit($limit);
627 return $query->exec();
630 private function loadRecentItems()
635 $unavailableIds = [];
639 if (!$recentItem->isAvailable())
641 $unavailableIds[] = $recentItem->getId();
643 else if (!$recentItem->isLoaded())
645 $unloadedIds[] = $recentItem->getId();
649 if (!empty($unloadedIds))
651 $availableItems = [];
652 $items = $entity->getProvider()->getItems($unloadedIds);
653 foreach ($items as $item)
655 if ($item instanceof Item)
657 $availableItems[$item->getId()] = $item;
661 foreach ($unloadedIds as $unloadedId)
663 $item = $availableItems[$unloadedId] ??
null;
664 if ($item && $item->isAvailableInRecentTab())
670 $unavailableIds[] = $unloadedId;
677 EntityUsageTable::deleteByFilter([
680 '=ENTITY_ID' => $entity->getId(),
681 '@ITEM_ID' => $unavailableIds
697 $filters = $entity->getFilters();
698 foreach ($filters as $filter)
700 $filter->apply($items, $this);
718 'id' => $this->
getId(),
720 'tabs' => array_values($this->
getTabs()),
static getMessage($code, $replace=null, $language=null)