Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/components/bitrix/main.interface.buttons/ |
Upload File : |
<?php use Bitrix\Main\Localization\Loc; use Bitrix\Main\Text; use Bitrix\Main; use Bitrix\Main\Web\Uri; if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die(); Loc::loadMessages(__FILE__); class CMainInterfaceButtons extends CBitrixComponent implements Main\Engine\Contract\Controllerable, Main\Errorable { /** * First argument for CUserOptions::GetOption * this is Options Category * @var string */ protected $userOptionsCategory = "ui"; /** * @var int */ protected $maxCounterSize = 99; /** * User options settings key * @var string */ protected $userOptionsKey = "settings"; /** * Component items settings * @var array */ protected $settings = []; /** * User options expanded items * @var array */ private $expandedLists = []; private $randomSequences = []; private $pinnedItems = []; /** * More item class * @var string */ protected $defaultMoreItemClass = "main-buttons-item-more-default"; /** * @var Main\ErrorCollection */ protected $errorCollection; protected const EDIT_MODE_PERSONAL = 'PERSONAL'; protected const EDIT_MODE_COMMON = 'COMMON'; protected const EDIT_MODE_DISABLE = 'DISABLE'; public function onPrepareComponentParams($arParams) { $this->errorCollection = new Main\ErrorCollection(); if (empty($arParams["ID"])) { $this->errorCollection->setError(new Main\Error(Loc::getMessage("MIB_ID_NOT_SET"), "unknown")); } else { $arParams["ID"] = $this->prepareContainerId($arParams["ID"]); $arParams["EDIT_MODE"] = $this->prepareSaveMode( array_key_exists("EDIT_MODE", $arParams) ? $arParams["EDIT_MODE"] : null, $arParams["DISABLE_SETTINGS"] ?? false ); $arParams["DISABLE_SETTINGS"] = $this->prepareDisableSettings($arParams["EDIT_MODE"]); $arParams["THEME"] = isset($arParams["THEME"]) && is_string($arParams["THEME"]) ? $arParams["THEME"] : "default" ; $arParams["THEME_ID"] = " --" . $arParams["THEME"]; $arParams["THEME_VARS"] = isset($arParams["THEME_VARS"]) && is_array($arParams["THEME_VARS"]) ? $arParams["THEME_VARS"] : [] ; } return $arParams; } protected function setStyles() { global $APPLICATION; if (isset($this->arParams["INCLUDE_CSS_FILE"]) && !empty($this->arParams["INCLUDE_CSS_FILE"])) { $APPLICATION->SetAdditionalCSS($this->arParams["INCLUDE_CSS_FILE"]); } } /** * Prepares params * @return object $this */ protected function prepareParams() { $this->arParams["CLASS_ITEM_ACTIVE"] = $this->prepareItemClass($this->arParams["CLASS_ITEM_ACTIVE"] ?? ''); $this->arParams["CLASS_ITEM"] = $this->prepareItemClass($this->arParams["CLASS_ITEM"] ?? ''); $this->arParams["CLASS_ITEM_LINK"] = $this->prepareItemClass($this->arParams["CLASS_ITEM_LINK"] ?? ''); $this->arParams["CLASS_ITEM_ICON"] = $this->prepareItemClass($this->arParams["CLASS_ITEM_ICON"] ?? ''); $this->arParams["CLASS_ITEM_TEXT"] = $this->prepareItemClass($this->arParams["CLASS_ITEM_TEXT"] ?? ''); $this->arParams["CLASS_ITEM_COUNTER"] = $this->prepareItemClass($this->arParams["CLASS_ITEM_COUNTER"] ?? ''); $this->arParams["ITEMS"] = $this->prepareItems($this->arParams["ITEMS"]); $this->arParams["MORE_BUTTON"] = $this->prepareMoreItem($this->arParams["MORE_BUTTON"] ?? []); $this->arParams["MAX_ITEM_LENGTH"] = $this->prepareMaxItemLength($this->arParams['MAX_ITEM_LENGTH'] ?? 0); return $this; } protected function prepareDisableSettings(string $mode): bool { return $mode === self::EDIT_MODE_DISABLE; } protected function prepareMaxItemLength($length): int { $length = (int)$length; if ($length > 6) { return $length; } if ($this->arParams['THEME'] === 'flat') { return 30; } else if ($this->arParams['THEME'] === 'small' || $this->arParams['THEME'] === 'tiny') { return 20; } return 40; } protected function prepareSaveMode($mode = null, $disableSettings = false): string { $result = self::EDIT_MODE_PERSONAL; if (is_string($mode)) { $mode = mb_strtoupper($mode); if (in_array($mode, [self::EDIT_MODE_COMMON, self::EDIT_MODE_DISABLE])) { $result = $mode; } } else if (is_bool($mode)) { $result = $mode === false ? self::EDIT_MODE_DISABLE : self::EDIT_MODE_PERSONAL; } else if ($disableSettings === true) { $result = self::EDIT_MODE_DISABLE; } return $result; } /** * Gets user options as is * @return array|bool */ protected function getUserOptions() { return CUserOptions::GetOption($this->userOptionsCategory, $this->arParams["ID"]); } /** * Prepares container id * @param string $id * @return string Container id */ protected function prepareContainerId($id) { $id = $this->safeString($id); $id = preg_replace("/[^a-z0-9_-]/i", "", $id); $id = mb_strtolower($id); return $id; } protected function getRandomItemId($seed): string { if (!isset($this->randomSequences[$seed])) { $this->randomSequences[$seed] = new \Bitrix\Main\Type\RandomSequence($seed); } return $this->randomSequences[$seed]->randString(12); } /** * Prepares user options * @param array $userOptions * @param $userOptionsKey * @return array User options */ protected function prepareUserOptions($userOptions, $userOptionsKey) { $userOptionsSettings = array(); if (is_array($userOptions) && isset($userOptions[$userOptionsKey]) && !empty($userOptions[$userOptionsKey])) { $userOptionsSettings = json_decode($userOptions[$userOptionsKey], true); } return $userOptionsSettings; } /** * Prepares settings */ protected function prepareSettings() { $userOptionsRaw = $this->getUserOptions(); $settings = $this->prepareUserOptions($userOptionsRaw, $this->userOptionsKey); $this->settings = $settings; $this->expandedLists = $this->prepareUserOptions($userOptionsRaw, 'expanded_lists'); } /** * Gets item settings by item id * @param string $id * @return array */ protected function getItemSettingsByItemId($id) { $result = array(); if (!empty($id) && is_array($this->settings) && !empty($this->settings[$id])) { $result = $this->settings[$id]; } return $result; } /** * Prepares item text value * @param string $text Text string * @return string */ protected function prepareItemText($text) { if (!is_string($text) && !is_numeric($text)) { return ''; } return trim((string)$text); } /** * Prepares item html * @param string $html * @return string */ protected function prepareItemHtml($html) { return Text\Converter::getHtmlConverter()->decode($html); } /** * Prepares item url * @param string $url * @return string */ protected function prepareItemUrl($url) { return preg_match('#^(?:/|https?://)#', $url) ? (string)$url: ''; } /** * Prepares item class * @param string $class * @return string */ protected function prepareItemClass($class) { return $this->safeString($class); } /** * Prepares item id * @param string $id * @return string */ protected function prepareItemId($id) { $result = ""; if (!empty($id)) { $result = $this->safeString($id); $result = str_replace('-', '_', $result); $result = preg_replace("/[^a-z0-9_\/]/i", "", $result); $result = mb_strtolower($result); } return $result; } /** * Prepares item counter value * @param integer $counter * @return integer|boolean */ protected function prepareItemCounter($counter) { $result = false; if (is_float($counter) || is_int($counter)) { $result = $counter; } return $result; } /** * Prepares item is locked value * @param boolean $isLocked * @return boolean json_encode'd */ protected function prepareItemIsLocked($item) { return isset($item['IS_LOCKED']) && $item['IS_LOCKED'] === true; } protected function prepareItemIsPinned($item) { $result = false; $settings = $this->getItemSettingsByItemId($item['ID']); if (is_array($settings) && isset($settings["isPinned"]) && is_bool($settings["isPinned"])) { $result = $settings["isPinned"]; } return $result; } /** * Prepares item is disabled value * @param boolean $isDisabled * @param string $id * @return boolean json_encode'd */ protected function prepareItemIsDisabled($isDisabled, $id) { $result = false; $settings = $this->getItemSettingsByItemId($id); if (!empty($isDisabled) && is_bool($isDisabled)) { $result = $isDisabled; } if (is_array($settings) && isset($settings["isDisabled"]) && is_bool($settings["isDisabled"])) { $result = $settings["isDisabled"]; } $result = json_encode($result); return $result; } /** * Prepares item sublink array * @param array $sublink * @return array|boolean return false if sublink not set */ protected function prepareItemSublink($sublink) { $result = false; if (!empty($sublink) && is_array($sublink)) { if (!empty($sublink["URL"])) { $sublink["URL"] = $this->prepareItemUrl($sublink["URL"]); } else { $sublink["URL"] = ''; } if (!empty($sublink["CLASS"])) { $sublink["CLASS"] = $this->prepareItemClass($sublink["CLASS"]); } $result = $sublink; } return $result; } /** * Prepares item super title array * @param array $item * @return array|boolean return false if super title not set */ protected function prepareItemSuperTitle($item) { if (isset($item['SUPER_TITLE']) && is_array($item['SUPER_TITLE']) && isset($item['SUPER_TITLE']['TEXT'])) { return [ 'TEXT' => $this->safeString($item['SUPER_TITLE']['TEXT']), 'CLASS' => isset($item['SUPER_TITLE']['CLASS']) ? $this->safeString($item['SUPER_TITLE']['CLASS']) : '', 'COLOR' => isset($item['SUPER_TITLE']['COLOR']) ? $this->safeString($item['SUPER_TITLE']['COLOR']) : '', ]; } else if (isset($item['IS_NEW']) && $item['IS_NEW'] === true) { return [ 'TEXT' => Loc::getMessage('MIB_NEW_ITEM_LABEL'), 'CLASS' => '', 'COLOR' => '', ]; } return false; } /** * Prepares item sort index value * * @param string $id * @param integer $defaultSort * @return integer Sort index */ protected function prepareItemSort($id, $defaultSort) { $result = $defaultSort; $settings = $this->getItemSettingsByItemId($id); if (!empty($settings) && is_array($settings)) { if (is_int($settings["sort"])) { $result = $settings["sort"]; } } return $result; } /** * Prepares item is active value * @param array $item * @return boolean */ protected function prepareItemIsActive(&$item) { $result = false; if (!isset($item["IS_ACTIVE"])) { $requestUri = $this->request->getRequestUri(); if ($requestUri == $item["URL"]) { $result = true; } if (!$result && isset($item["ADDITIONAL_URL"]) && is_array($item["ADDITIONAL_URL"])) { $result = array_search($requestUri, $item["ADDITIONAL_URL"]); $result = !is_null($result); } } else { $result = $item['IS_ACTIVE'] === true || $item['IS_ACTIVE'] === 'true' || $item['IS_ACTIVE'] === 'Y'; } return $result; } protected function prepareItemIsPassive($item) { return isset($item['IS_PASSIVE']) && $item['IS_PASSIVE'] === true; } /** * Prepares item * * @param array $item * @param integer $defaultSort * @return array Prepared $item */ protected function prepareItem(array $item, int $defaultSort = 0, $rootItem = null) { $item["TEXT"] = $this->prepareItemText($item["TEXT"] ?? ''); $item["TITLE"] = $this->prepareItemText($item["TITLE"] ?? ''); $item["HTML"] = $this->prepareItemHtml($item["HTML"] ?? ''); $item["URL"] = $this->prepareItemUrl($item["URL"] ?? ''); $item["CLASS"] = $this->prepareItemClass($item["CLASS"] ?? ''); $item["CLASS_SUBMENU_ITEM"] = $this->prepareItemClass($item["CLASS_SUBMENU_ITEM"] ?? ''); $item["ON_CLICK"] = $item["ON_CLICK"] ?? ''; $itemId = $this->prepareItemId($item['ID'] ?? ''); if (empty($itemId)) { if (!empty($item['URL'])) { $itemId = crc32($item['URL']); } else if (!empty($item["ON_CLICK"])) { $itemId = crc32($item['ON_CLICK']); } else { $seed = 'mib_' . $this->arParams['ID'] . '_' . ($rootItem !== null ? $rootItem['ID'] : ''); $itemId = $this->getRandomItemId($seed); } $itemId = "mib_$itemId"; } if ($rootItem === null) { $globalId = join('_', [$this->arParams['ID'], $itemId]); } else { $globalId = $rootItem['ID'] . ':' . $itemId; } $item["DATA_ID"] = $itemId; $item["ID"] = $globalId; $item["MAX_COUNTER_SIZE"] = array_key_exists('MAX_COUNTER_SIZE', $item) ? $item["MAX_COUNTER_SIZE"] : $this->maxCounterSize ; if (isset($item["COUNTER"])) { $counter = $this->prepareItemCounter($item["COUNTER"]); if ($counter !== false && !empty($counter)) { $item["COUNTER"] = $counter; } else { unset($item["COUNTER"]); } } if (isset($item["COUNTER_ID"])) { $counterId = $this->prepareItemCounterId($item); if (!empty($counterId) && is_string($counterId)) { $item["COUNTER_ID"] = $counterId; } else { unset($item["COUNTER_ID"]); } } if ($rootItem !== null) { $item["IS_PINNED"] = $this->prepareItemIsPinned($item); if ($item["IS_PINNED"]) { $this->pinnedItems[] = &$item; } } $item["IS_LOCKED"] = $this->prepareItemIsLocked($item); $item["IS_DISABLED"] = $this->prepareItemIsDisabled($item["IS_DISABLED"] ?? false, $item["ID"]); $item["SUB_LINK"] = $this->prepareItemSublink($item["SUB_LINK"] ?? ''); $item["SUPER_TITLE"] = $this->prepareItemSuperTitle($item); $item["SORT"] = $this->prepareItemSort($item["ID"], $defaultSort); $item["IS_ACTIVE"] = $this->prepareItemIsActive($item); $item["IS_PASSIVE"] = $this->prepareItemIsPassive($item); $item["HAS_MENU"] = isset($item['ITEMS']) && is_array($item['ITEMS']) && !empty($item['ITEMS']); if ($item["HAS_MENU"]) { $item["URL"] = ''; $item["ON_CLICK"] = ''; $item["IS_ACTIVE"] = false; $this->prepareSubItems($item, $item['ITEMS']); } return $item; } protected function prepareSubItems(&$item, array &$subItems) { $hasVisibleSubItems = false; for ($i = 0, $count = count($subItems); $i < $count; $i++) { $subItems[$i] = $this->prepareItem($subItems[$i], $i, $item); $isPinned = isset($subItems[$i]['IS_PINNED']) && $subItems[$i]['IS_PINNED'] === true; $isDelimiter = isset($subItems[$i]['IS_DELIMITER']) && $subItems[$i]['IS_DELIMITER'] === true; if (isset($subItems[$i]['COUNTER']) && !$isPinned && !$isDelimiter) { if (!isset($item['COUNTER'])) { $item['COUNTER'] = 0; } $item['COUNTER'] += $subItems[$i]['COUNTER']; } if ($subItems[$i]['IS_ACTIVE'] && !$isPinned && !$isDelimiter) { $item['IS_ACTIVE'] = true; } if (isset($subItems[$i]['COUNTER']) || isset($subItems[$i]['COUNTER_ID'])) { $item['HAS_COUNTERS'] = true; if (!isset($item['COUNTER_ID'])) { $item['COUNTER_ID'] = $item['ID'] . '_counter'; } } if (!$isPinned && !$isDelimiter) { $hasVisibleSubItems = true; } } if (!$hasVisibleSubItems) { $item['IS_DISBANDED'] = true; } } protected function prepareItemCounterId($item) { $id = ''; if (isset($item["COUNTER_ID"]) && is_string($item["COUNTER_ID"]) && !empty($item["COUNTER_ID"])) { $id = $item["COUNTER_ID"]; } return $id; } protected function prepareMoreItem($item) { $html = $this->prepareItemHtml($item["HTML"] ?? ''); $class = $this->prepareItemClass($item["CLASS"] ?? ''); $item["TEXT"] = Loc::getMessage("MIB_DEFAULT_MORE_ITEM_TEXT"); $item["HTML"] = $html; $item["CLASS"] = !empty($class) ? $class : $this->defaultMoreItemClass; return $item; } protected function filterItems() { $items = array_filter($this->arParams["ITEMS"], function($item) { return is_array($item); }); $itemsCount = count($items); if (!$itemsCount) { ShowError(Loc::getMessage("MIB_ITEMS_NOT_FOUND")); return 0; } $this->arParams["ITEMS"] = $items; return $itemsCount; } protected function prepareItems($items = array()) { foreach ($items as $key => $item) { $items[$key] = $this->prepareItem($item, $key); } foreach ($this->pinnedItems as $item) { $items[] = unserialize(serialize($item), ['allowed_classes' => false]); } $items = $this->sortBySortIndex($items); foreach ($items as $key => $item) { $childItems = array_filter($items, function($currentItem) use ($item) { return isset($currentItem['PARENT_ITEM_ID']) && $currentItem['PARENT_ITEM_ID'] === $item['DATA_ID']; }); $items[$key]['HAS_CHILD'] = is_array($childItems) && !empty($childItems); if ($items[$key]['HAS_CHILD'] === true) { if (array_key_exists($item['DATA_ID'], $this->expandedLists) && $this->expandedLists[$item['DATA_ID']] == 'Y') { $items[$key]['EXPANDED'] = true; } else { $items[$key]['EXPANDED'] = false; } $items[$key]['CHILD_ITEMS'] = []; foreach ($childItems as $currentItem) { $items[$key]['CHILD_ITEMS'][] = $currentItem; } } } return $items; } /** * Sorts array bi sort index * @param array $array * @return array Sorted array */ protected function sortBySortIndex($array = array()) { usort($array, function($a, $b) { return $a["SORT"] - $b["SORT"]; }); return $array; } protected function safeString($string) { if (!is_string($string) && !is_numeric($string) && !($string instanceof Uri)) { return ''; } $string = trim((string)$string); $string = Text\Converter::getHtmlConverter()->encode($string); return (String)$string; } /** * Prepares arResult */ protected function prepareResult() { $this->arResult = $this->arParams; } public function executeComponent() { if ($this->errorCollection->isEmpty()) { if ($this->filterItems()) { $this->prepareSettings(); $this->prepareParams(); $this->prepareResult(); $this->setStyles(); $this->includeComponentTemplate(); } } } public function configureActions() { return []; } public function getErrors() { return $this->errorCollection->toArray(); } public function getErrorByCode($code) { return $this->errorCollection->getErrorByCode($code); } protected function listKeysSignedParameters() { return [ 'ID', 'EDIT_MODE', 'DISABLE_SETTINGS', 'THEME', ]; } public function saveAction(array $options) { if ($this->errorCollection->isEmpty() && ($this->arParams['EDIT_MODE'] !== self::EDIT_MODE_DISABLE) ) { $value = array_merge( CUserOptions::GetOption($this->userOptionsCategory, $this->arParams['ID'], []), $options ); CUserOptions::SetOption( $this->userOptionsCategory, $this->arParams['ID'], $value, $this->arParams['EDIT_MODE'] === self::EDIT_MODE_COMMON); } } }