У меня такая же проблема была, только с комплексным каталогом.
Да, стандартными способами такое не получится. Битрикс не может разобрать раличия между
Код |
---|
"section" => "#SECTION_CODE#/",
"detail" => "#ELEMENT_CODE#/",
|
Я перерыл исходники чпу методов и нашёл такой класс:
Код |
---|
class CIBlockFindTools
|
Именно в нём реализуется метод
Код |
---|
public static function resolveComponentEngine(CComponentEngine $engine, $pageCandidates, &$arVariables) |
Этот метод как раз разбирает строку из реквеста и подбирает соответствующий ответ - секция или элемент.
При коде
Код |
---|
"section" => "#SECTION_CODE#/",
"detail" => "#ELEMENT_CODE#/", |
он мне всё время на код элемента возвращал ответ "section"
Покопавшись нашёл такой код:
Код |
---|
foreach ($pageCandidates as $pageID => $arVariablesTmp){
if (
$arVariablesTmp["SECTION_CODE_PATH"] != ""
&& (isset($arVariablesTmp["ELEMENT_ID"]) || isset($arVariablesTmp["ELEMENT_CODE"]))
)
{
if (CIBlockFindTools::checkElement($iblock_id, $arVariablesTmp, $strict_check))
{
$arVariables = $arVariablesTmp;
if (defined("BX_COMP_MANAGED_CACHE"))
$CACHE_MANAGER->EndTagCache();
$cache->EndDataCache(array($pageID, $arVariablesTmp));
return $pageID;
}
}
}
foreach ($pageCandidates as $pageID => $arVariablesTmp)
{
if (
$arVariablesTmp["SECTION_CODE_PATH"] != ""
&& (!isset($arVariablesTmp["ELEMENT_ID"]) && !isset($arVariablesTmp["ELEMENT_CODE"]))
)
{
if (CIBlockFindTools::checkSection($iblock_id, $arVariablesTmp))
{
$arVariables = $arVariablesTmp;
if (defined("BX_COMP_MANAGED_CACHE"))
$CACHE_MANAGER->EndTagCache();
$cache->EndDataCache(array($pageID, $arVariablesTmp));
return $pageID;
}
}
} |
Тут в каждом foreach определяется секция или элемент, а если не получается определить, возвращается всегда первый элемент массива, который у меня всегда section.
И проблема кроется в каждом foreach, а точнее в каждом if внутри foreach.
В каждом условии есть такой момент:
Код |
---|
if (
$arVariablesTmp["SECTION_CODE_PATH"] != ""
&& |
Но в нашем случае такой параметр в чпу не передаётся и он всегда будет не определен. Соответственно условие всегда не будет выполняться.
В итоге я переопределил новый класс, унаследовав исходный битриксовский
Код |
---|
class NEWIBlockFindTools extends CIBlockFindTools
|
И переопределил в нём это условие, заменив на
Код |
---|
if (
$arVariablesTmp["SECTION_CODE_PATH"] == ""
&& |
во всех foreach.
После подключил класс в init.php
И в самом комплексном компоненте
Код |
---|
if($arParams["SEF_MODE"] == "Y")
{
$arVariables = array();
$engine = new CComponentEngine($this);
if (\Bitrix\Main\Loader::includeModule('iblock'))
{
$engine->addGreedyPart("#SECTION_CODE_PATH#");
$engine->addGreedyPart("#SMART_FILTER_PATH#");
$engine->setResolveCallback(array("СIBlockFindTools", "resolveComponentEngine"));
}
$arUrlTemplates = CComponentEngine::makeComponentUrlTemplates($arDefaultUrlTemplates404, $arParams["SEF_URL_TEMPLATES"]);
$arVariableAliases = CComponentEngine::makeComponentVariableAliases($arDefaultVariableAliases404, $arParams["VARIABLE_ALIASES"]); |
заменил
Код |
---|
$engine->setResolveCallback(array("СIBlockFindTools", "resolveComponentEngine")); |
на
Код |
---|
$engine->setResolveCallback(array("NEWIBlockFindTools", "resolveComponentEngine")); |
Всё сразу заработало, кроме 404 ошибки на несуществующие секции.
Ну тут уже достаточно просто было сделать проверку в самой секции и возвращать 404.