Услуги профессионального Битрикс-программиста

Меню с разделами и элементами инфоблока


свой компонент nikaverro:menu.sections component.php
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();
/** @var CBitrixComponent $this */
/** @var array $arParams */
/** @var array $arResult */
/** @var string $componentPath */
/** @var string $componentName */
/** @var string $componentTemplate */
/** @global CDatabase $DB */
/** @global CUser $USER */
/** @global CMain $APPLICATION */


if(!isset($arParams["CACHE_TIME"]))
   $arParams["CACHE_TIME"] = 36000000;

$arParams["ID"] = intval($arParams["ID"]);
$arParams["IBLOCK_ID"] = intval($arParams["IBLOCK_ID"]);

$arParams["DEPTH_LEVEL"] = intval($arParams["DEPTH_LEVEL"]);
if($arParams["DEPTH_LEVEL"]<=0)
   $arParams["DEPTH_LEVEL"]=1;

$arResult["SECTIONS"] = array();
$arResult["ELEMENT_LINKS"] = array();

if($this->StartResultCache())
{
   if(!CModule::IncludeModule("iblock"))
   {
      $this->AbortResultCache();
   }
   else
   {
      $arFilter = array(
         "IBLOCK_ID"=>$arParams["IBLOCK_ID"],
         "GLOBAL_ACTIVE"=>"Y",
         "IBLOCK_ACTIVE"=>"Y",
         "<="."DEPTH_LEVEL" => $arParams["DEPTH_LEVEL"],
      );
      $arOrder = array(
         "left_margin"=>"asc",
      );

      $rsSections = CIBlockSection::GetList($arOrder, $arFilter, false, array(
         "ID",
         "DEPTH_LEVEL",
         "NAME",
         "SECTION_PAGE_URL",
      ));
      if($arParams["IS_SEF"] !== "Y")
         $rsSections->SetUrlTemplates("", $arParams["SECTION_URL"]);
      else
         $rsSections->SetUrlTemplates("", $arParams["SEF_BASE_URL"].$arParams["SECTION_PAGE_URL"]);
      while($arSection = $rsSections->GetNext())
      {
         /*$arResult["SECTIONS"][] = array(
            "ID" => $arSection["ID"],
            "DEPTH_LEVEL" => $arSection["DEPTH_LEVEL"],
            "~NAME" => $Searction["~NAME"],
            "~SECTION_PAGE_URL" => "Category:".urlencode($arSection["NAME"])."/",
         );*/
         $arResult["SECTIONS"][] = $arSection;
         $arResult["ELEMENT_LINKS"][$arSection["ID"]] = array();
      }
      $this->EndResultCache();
   }
}

//In "SEF" mode we'll try to parse URL and get ELEMENT_ID from it
if($arParams["IS_SEF"] === "Y")
{
   $engine = new CComponentEngine($this);
   if (CModule::IncludeModule('iblock'))
   {
      $engine->addGreedyPart("#SECTION_CODE_PATH#");
      $engine->setResolveCallback(array("CIBlockFindTools", "resolveComponentEngine"));
   }
   $componentPage = $engine->guessComponentPath(
      $arParams["SEF_BASE_URL"],
      array(
         "section" => $arParams["SECTION_PAGE_URL"],
         "detail" => $arParams["DETAIL_PAGE_URL"],
      ),
      $arVariables
   );
   if($componentPage === "detail")
   {
      CComponentEngine::InitComponentVariables(
         $componentPage,
         array("SECTION_ID", "ELEMENT_ID"),
         array(
            "section" => array("SECTION_ID" => "SECTION_ID"),
            "detail" => array("SECTION_ID" => "SECTION_ID", "ELEMENT_ID" => "ELEMENT_ID"),
         ),
         $arVariables
      );
      $arParams["ID"] = intval($arVariables["ELEMENT_ID"]);
   }
}

if(CModule::IncludeModule("iblock")){
   $arSelect = array("ID", "IBLOCK_ID", "DETAIL_PAGE_URL", "IBLOCK_SECTION_ID","NAME");
   $arFilter = array(      
      "ACTIVE" => "Y",
      "IBLOCK_ID" => $arParams["IBLOCK_ID"],
   );
   $rsElements = CIBlockElement::GetList(array(), $arFilter, false, false, $arSelect);
   if(($arParams["IS_SEF"] === "Y") && ($arParams["DETAIL_PAGE_URL"] <> ''))
      $rsElements->SetUrlTemplates($arParams["SEF_BASE_URL"].$arParams["DETAIL_PAGE_URL"]);
   while($arElement = $rsElements->GetNext())
   {
      $arResult["ELEMENT_LINKS"][$arElement["IBLOCK_SECTION_ID"]][] = [
         "TEXT"=>htmlspecialcharsbx($arElement["~NAME"]),
         "LINK"=>$arElement["~DETAIL_PAGE_URL"],
      ];
   }
}

$aMenuLinksNew = array();
$menuIndex = 0;
$previousDepthLevel = 1;
foreach($arResult["SECTIONS"] as $arSection)
{
   if ($menuIndex > 0){
      if($arSection["DEPTH_LEVEL"] > $previousDepthLevel){
         $aMenuLinksNew[$menuIndex - $j-1][3]["IS_PARENT"] = true;         
      }      
   }
   $previousDepthLevel = $arSection["DEPTH_LEVEL"];

   //$arResult["ELEMENT_LINKS"][$arSection["ID"]][] = urldecode($arSection["~SECTION_PAGE_URL"]);
   
   $aMenuLinksNew[$menuIndex++] = array(
      htmlspecialcharsbx($arSection["~NAME"]),
      $arSection["~SECTION_PAGE_URL"],
      [],
      array(
         "FROM_IBLOCK" => true,
         "IS_PARENT" => empty($arResult["ELEMENT_LINKS"][$arSection["ID"]]) ? false : true,
         "DEPTH_LEVEL" => $arSection["DEPTH_LEVEL"],            
         "IS_ELEMENT" =>false      
      ),
   );
   $j = 0;
   foreach($arResult["ELEMENT_LINKS"][$arSection["ID"]] as $arElement){
      $j++;
      $aMenuLinksNew[$menuIndex++] = array(
         htmlspecialcharsbx($arElement["TEXT"]),
         $arElement["LINK"],
         [],
         array(
            "FROM_IBLOCK" => true,
            "IS_PARENT" => false,
            "DEPTH_LEVEL" => ($arSection["DEPTH_LEVEL"]+1),            
            "IS_ELEMENT" =>true      
         ),
      );
   }
}

return $aMenuLinksNew;
?>
menu_ext
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();

global $APPLICATION;
$aMenuLinksExt=$APPLICATION->IncludeComponent("nikaverro:menu.sections", "", array(
   "IBLOCK_TYPE" => "services",
   "IBLOCK_ID" => "193",
   "IS_SEF" => "Y",
   "SEF_BASE_URL" => "/knowledge_base/", //директория каталога
   "SECTION_PAGE_URL" => "#SECTION_CODE_PATH#/",
   "DETAIL_PAGE_URL" => "#SECTION_CODE_PATH#/#ID#",
   "DEPTH_LEVEL" => "5",
   "CACHE_TYPE" => "A",
   "CACHE_TIME" => "36000"
   ),
   false,
   array("HIDE_ICONS"=>"Y")   
);
$aMenuLinks = array_merge ($aMenuLinksExt, $aMenuLinks);
?>
вывод меню bitrix.menu template.php
<?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
$APPLICATION->AddHeadScript('/bitrix/templates/.default/js/jquery.min.js');?>

<?if (!empty($arResult)):?>

<div class="menu-sitemap-tree" id="knowledge-menu">
<ul>
<?
$previousLevel = 0;
foreach($arResult as $arItem):
?>
   <?if ($previousLevel && ($arItem["DEPTH_LEVEL"] < $previousLevel)):?>
      <?=str_repeat("</ul></li>", ($previousLevel - $arItem["DEPTH_LEVEL"]));?>
   <?endif?>

   <?if ($arItem["IS_PARENT"]):?>
         <li class="<?if(!$arItem["SELECTED"] && !$arItem["CHILD_SELECTED"]):?> menu-close<?endif?> ">
            <div class="folder" onClick="OpenMenuNode(this)"></div>
            <div class="item-text"><a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a></div>
            <ul class="parent">
   <?else:?>
      <?if ($arItem["PERMISSION"] > "D"):?>
            <li class="<?=$arItem["PARAMS"]["IS_ELEMENT"] ? "page-item" : "" ?>">               
               <div class="<?=$arItem["PARAMS"]["IS_ELEMENT"] ? "page" : "folder" ?>"></div>
               <div class="item-text"><a href="<?=$arItem["LINK"]?>"><?=$arItem["TEXT"]?></a></div>
            </li>            
      <?endif?>

   <?endif?>
   <?$previousLevel = $arItem["DEPTH_LEVEL"];?>   
<?endforeach?>

<?if ($previousLevel > 1)://close last item tags?>
   <?=str_repeat("</ul></li>", ($previousLevel-1) );?>
<?endif?>

</ul>
</div>
<?endif?>
<script>
   $(document).ready(function(){
      $('#knowledge-menu .page-item').each(function(ind,el){
         let page = el;         
         let ul = $(page).closest('.parent');         
         $(ul).append(page);
         $(ul).remove(page);         
      });
   });
       function OpenMenuNode(oThis){ //это битриксовский код
   if (oThis.parentNode.className == '')
      oThis.parentNode.className = 'menu-close';
   else
      oThis.parentNode.className = '';
   return false;
      }
</script>