У меня такая же проблема была, только с комплексным каталогом.
Да, стандартными способами такое не получится. Битрикс не может разобрать раличия между [CODE] "section" => "#SECTION_CODE#/",
"detail" => "#ELEMENT_CODE#/",
[/CODE]Я перерыл исходники чпу методов и нашёл такой класс:
[CODE]class CIBlockFindTools
[/CODE]
Именно в нём реализуется метод
[CODE]public static function resolveComponentEngine(CComponentEngine $engine, $pageCandidates, &$arVariables)[/CODE]
Этот метод как раз разбирает строку из реквеста и подбирает соответствующий ответ - секция или элемент.
При коде
[CODE] "section" => "#SECTION_CODE#/",
"detail" => "#ELEMENT_CODE#/",[/CODE]
он мне всё время на код элемента возвращал ответ "section"
Покопавшись нашёл такой код:[CODE]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;
}
}
}[/CODE]
Тут в каждом foreach определяется секция или элемент, а если не получается определить, возвращается всегда первый элемент массива, который у меня всегда section.
И проблема кроется в каждом foreach, а точнее в каждом if внутри foreach.
В каждом условии есть такой момент:
[CODE]if (
$arVariablesTmp["SECTION_CODE_PATH"] != ""
&& [/CODE]
Но в нашем случае такой параметр в чпу не передаётся и он всегда будет не определен. Соответственно условие всегда не будет выполняться.
В итоге я переопределил новый класс, унаследовав исходный битриксовский
[CODE]class NEWIBlockFindTools extends CIBlockFindTools
[/CODE]
И переопределил в нём это условие, заменив на
[CODE]if (
$arVariablesTmp["SECTION_CODE_PATH"] == ""
&&[/CODE]
во всех foreach.
После подключил класс в init.php
И в самом комплексном компоненте
[CODE]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"]);[/CODE]
заменил [CODE]$engine->setResolveCallback(array("СIBlockFindTools", "resolveComponentEngine"));[/CODE]на[CODE]$engine->setResolveCallback(array("NEWIBlockFindTools", "resolveComponentEngine"));[/CODE]
Всё сразу заработало, кроме 404 ошибки на несуществующие секции.
Ну тут уже достаточно просто было сделать проверку в самой секции и возвращать 404.