• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/menu.php
  • Класс: CMenu
  • Вызов: CMenu::RecalcMenu
function RecalcMenu($bMultiSelect = false, $bCheckSelected = true)
{
	if($this->bMenuCalc !== false)
		return true;

	/**
	 * @global CMain $APPLICATION
	 * @global CCacheManager $CACHE_MANAGER
	 * @noinspection PhpUnusedLocalVariableInspection
	 */
	global $USER, $DB, $APPLICATION, $CACHE_MANAGER;

	$result = array();

	$cur_page = $APPLICATION->GetCurPage(true);
	$cur_page_no_index = $APPLICATION->GetCurPage(false);

	$APPLICATION->_menu_recalc_counter++;

	$this->bMenuCalc = true;

	if($this->template <> '' && file_exists($_SERVER["DOCUMENT_ROOT"].$this->template))
	{
		$this->MenuTemplate = $_SERVER["DOCUMENT_ROOT"].$this->template;
	}
	else
	{
		if(defined("SITE_TEMPLATE_PATH") && file_exists($_SERVER["DOCUMENT_ROOT"].SITE_TEMPLATE_PATH."/".$this->type.".menu_template.php"))
		{
			$this->template = SITE_TEMPLATE_PATH."/".$this->type.".menu_template.php";
			$this->MenuTemplate = $_SERVER["DOCUMENT_ROOT"].$this->template;
		}
		elseif(file_exists($_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/php_interface/".LANG."/".$this->type.".menu_template.php"))
		{
			$this->template = BX_PERSONAL_ROOT."/php_interface/".LANG."/".$this->type.".menu_template.php";
			$this->MenuTemplate = $_SERVER["DOCUMENT_ROOT"].$this->template;
		}
		else
		{
			$this->template = BX_PERSONAL_ROOT."/templates/.default/".$this->type.".menu_template.php";
			$this->MenuTemplate = $_SERVER["DOCUMENT_ROOT"].$this->template;
		}
	}

	if(!file_exists($this->MenuTemplate))
	{
		$this->LAST_ERROR = "Template ".$this->MenuTemplate." is not found.";
		return false;
	}

	$arMenuCache = [];
	$bCached = false;
	$bCacheIsAllowed = CACHED_menu!==false && !$USER->IsAuthorized() && $this->MenuExtDir == '';
	if($bCacheIsAllowed)
	{
		$cache_id = $_SERVER["DOCUMENT_ROOT"].",".$this->MenuDir.",,".$this->type;
		if($CACHE_MANAGER->Read(CACHED_menu, $cache_id, "menu"))
		{
			$arMenuCache = $CACHE_MANAGER->Get($cache_id);
			$bCached = true;
		}
	}

	$arUserRights = $USER->GetAccessCodes();
	$ITEM_INDEX = -1;

	$cur_selected = -1;
	$cur_selected_len = -1;
	$previousDepthLevel = -1;
	$arParents = array(); //Stack of menu items

	foreach($this->arMenu as $iMenuItem=>$MenuItem)
	{
		$TEXT = $MenuItem[0];

		if($bCached)
		{
			$LINK = $arMenuCache[$iMenuItem]["LINK"];
		}
		else
		{
			//if the link is relative let's transform it to absolute
			if(!preg_match("'^(([A-Za-z]+://)|mailto:|javascript:|#)'i", $MenuItem[1]))
			{
				$LINK = Rel2Abs($this->MenuDir, $MenuItem[1]);
			}
			else
			{
				$LINK = $MenuItem[1];
			}
			$arMenuCache[$iMenuItem]["LINK"] = $LINK;
		}

		$bSkipMenuItem = false;
		$ADDITIONAL_LINKS = $MenuItem[2] ?? [];
		$PARAMS = $MenuItem[3] ?? [];

		//Calculate menu items stack for iblock items only
		if($this->MenuExtDir <> '' && is_array($PARAMS) && isset($PARAMS["FROM_IBLOCK"]))
		{
			if($previousDepthLevel == -1)
				$previousDepthLevel = $PARAMS["DEPTH_LEVEL"];

			if($PARAMS["DEPTH_LEVEL"] > $previousDepthLevel)
			{
				//Deeper into sections tree
				if($iMenuItem > 0)
					$arParents[] = array("INDEX" => $iMenuItem-1, "DEPTH_LEVEL" => $PARAMS["DEPTH_LEVEL"]);
			}
			else
			{
				//Unwind parents stack
				while(
					!empty($arParents)
					&& $arParents[count($arParents)-1]["DEPTH_LEVEL"] > $PARAMS["DEPTH_LEVEL"]
				)
				{
					array_pop($arParents);
				}
			}
			$previousDepthLevel = $PARAMS["DEPTH_LEVEL"];
		}
		elseif($previousDepthLevel != -1)
		{
			//End of tree, so reset the stack
			$previousDepthLevel = -1;
			$arParents = array();
		}


		if(count($MenuItem)>4)
		{
			$CONDITION = $MenuItem[4];
			if($CONDITION <> '' && (!eval("return ".$CONDITION.";")))
				$bSkipMenuItem = true;
		}

		if(!$bSkipMenuItem)
			$ITEM_INDEX++;

		if(($pos = mb_strpos($LINK, "?"))!==false)
			$ITEM_TYPE = "U";
		elseif(mb_substr($LINK, -1) == "/")
			$ITEM_TYPE = "D";
		else
			$ITEM_TYPE = "P";

		$SELECTED = false;

		if($bCached)
		{
			$all_links = $arMenuCache[$iMenuItem]["LINKS"];
			if(!is_array($all_links))
				$all_links = array();
		}
		else
		{
			$all_links = array();
			if(is_array($ADDITIONAL_LINKS))
			{
				foreach($ADDITIONAL_LINKS as $link)
				{
					$tested_link = trim(Rel2Abs($this->MenuDir, $link));
					if($tested_link <> '')
						$all_links[] = $tested_link;
				}
			}
			$all_links[] = $LINK;
			$arMenuCache[$iMenuItem]["LINKS"] = $all_links;
		}

		if(preg_match("'^(([A-Za-z]+://)|mailto:|javascript:|#)'i", $MenuItem[1]))
		{
			$PERMISSION = "Z";
		}
		else
		{
			if(!$bSkipMenuItem && $bCheckSelected)
			{
				foreach($all_links as $tested_link)
				{
					if($tested_link == '')
						continue;

					$SELECTED = self::IsItemSelected($tested_link, $cur_page, $cur_page_no_index);
					if($SELECTED)
						break;
				}
			}

			if($bCached)
				$PERMISSION = $arMenuCache[$iMenuItem]["PERM"];
			else
				$arMenuCache[$iMenuItem]["PERM"] = $PERMISSION = $APPLICATION->GetFileAccessPermission(GetFileFromURL($LINK), $arUserRights);
		}

		if($SELECTED && !$bMultiSelect)
		{
			/** @noinspection PhpUndefinedVariableInspection */
			$new_len = mb_strlen($tested_link);
			if($new_len > $cur_selected_len)
			{
				if($cur_selected !== -1)
					$result[$cur_selected]['SELECTED'] = false;

				$cur_selected = count($result);
				$cur_selected_len = $new_len;
			}
			else
			{
				$SELECTED = false;
			}
		}

		//Adjust selection for iblock sections tree
		if(
			$SELECTED
			&& $this->MenuExtDir <> ''
			&& is_array($PARAMS)
			&& isset($PARAMS["FROM_IBLOCK"])
		)
		{
			foreach($arParents as $parentMenuItem)
			{
				$parentIndex = $parentMenuItem["INDEX"];
				if(
					is_array($result[$parentIndex]["PARAMS"])
					&& isset($result[$parentIndex]["PARAMS"]["FROM_IBLOCK"])
				)
					$result[$parentIndex]["SELECTED"] = true;
			}
		}

		if(!$bSkipMenuItem)
		{
			$r = array(
				"TEXT" => $TEXT,
				"LINK" => $LINK,
				"SELECTED" => $SELECTED,
				"PERMISSION" => $PERMISSION,
				"ADDITIONAL_LINKS" => $ADDITIONAL_LINKS,
				"ITEM_TYPE" => $ITEM_TYPE,
				"ITEM_INDEX" => $ITEM_INDEX,
				"PARAMS" => $PARAMS
			);

			$result[] = $r;
		}
	}

	$this->arMenu = $result;

	if($bCacheIsAllowed && !$bCached)
	{
		/** @noinspection PhpUndefinedVariableInspection */
		$CACHE_MANAGER->Set($cache_id, $arMenuCache);
	}

	return true;
}