Example #1
0
 public function match(nc_routing_request $request, nc_routing_result $result)
 {
     if (!nc_preg_match($this->get_keyword_regexp(), $result->get_remainder(), $matches)) {
         return false;
         // --- RETURN ---
     }
     $possible_keywords = $this->get_possible_keywords($matches[1]);
     $infoblocks_in_folder = array();
     $infoblock_id = $result->get_resource_parameter('infoblock_id');
     // sic, not get_infoblock_id()
     $folder_id = $result->get_resource_parameter('folder_id');
     $infoblock_manager = nc_core::get_object()->sub_class;
     if ($infoblock_id) {
         $infoblocks_in_folder = array($infoblock_manager->get_by_id($infoblock_id));
     } else {
         if ($folder_id) {
             $infoblocks_in_folder = $infoblock_manager->get_by_subdivision_id($folder_id);
         }
     }
     foreach ($possible_keywords as $object_keyword) {
         foreach ($infoblocks_in_folder as $infoblock_settings) {
             list($object_id, $real_object_keyword) = (array) ObjectExists($infoblock_settings['Class_ID'], $infoblock_settings['sysTbl'], $infoblock_settings['Sub_Class_ID'], $object_keyword, $result->get_resource_parameter('date'), true);
             if ($object_id) {
                 $result->set_resource_parameter('infoblock_id', $infoblock_settings['Sub_Class_ID']);
                 $result->set_resource_parameter('object_keyword', $real_object_keyword);
                 $result->set_resource_parameter('object_id', $object_id);
                 $result->truncate_remainder(strlen($object_keyword));
                 return true;
                 // --- RETURN ---
             }
         }
     }
     return false;
     // --- RETURN ---
 }
Example #2
0
/**
 * @param nc_url|string $url Объект nc_url или строка
 * @param string $method GET|POST
 * @param int|null $site_id    Если null — текущий сайт
 * @return array|false   Массив с информацией об объекте, на который ссылается путь,
 *    или FALSE.
 *    array(
 *         resource_type => folder|infoblock|object|script
 *         site_id => идентификатор сайта
 *         folder_id => идентификатор раздела
 *         infoblock_id => [идентификатор инфоблока]
 *         object_id => идентификатор объекта в инфоблоке
 *         action => действие над инфоблоком или объектом
 *         format => html|rss|xml
 *         variables => массив с дополнительными переменными (только для модуля маршрутизации)
 *         date => дата в пути
 *         script_path => путь к скрипту от папки DOCUMENT_ROOT/SUB_FOLDER (только для модуля маршрутизации для resource_type=script)
 *         redirect_to_url => при запросе всегда будет выполняться переадресация
 *    )
 */
function nc_resolve_url($url, $method = null, $site_id = null)
{
    $nc_core = nc_core::get_object();
    $routing_module_enabled = nc_module_check_by_keyword('routing');
    // --- Приведение параметра $url к nc_url ---
    if (!$url instanceof nc_url) {
        $url = new nc_url($url);
    } else {
        if (!$routing_module_enabled) {
            // Создадим клон $url, так как в процессе работы будут изменяться свойства этого объекта
            $url = clone $url;
        }
    }
    // --- Определение сайта ---
    if (!$site_id) {
        $site_settings = $nc_core->catalogue->get_by_host_name($url->get_parsed_url('host'));
        if (isset($site_settings['Catalogue_ID'])) {
            $site_id = $site_settings['Catalogue_ID'];
        } else {
            $site_id = $nc_core->catalogue->id();
        }
    }
    if (!$site_id) {
        return false;
    }
    // --- Использование модуля маршрутизации ---
    if ($routing_module_enabled) {
        $result = nc_routing::resolve(new nc_routing_request($site_id, $method, $url->get_parsed_url()));
        if ($result) {
            $result = $result->to_array();
            $result['site_id'] = $site_id;
            return $result;
        } else {
            return false;
        }
    }
    // --- «Классическая» маршрутизация ---
    $result = array('resource_type' => 'folder', 'site_id' => $site_id, 'folder_id' => null, 'infoblock_id' => null, 'object_id' => null, 'action' => null, 'format' => 'html', 'variables' => array(), 'date' => null, 'redirect_to_url' => null);
    // Инициализация переменных
    $component_id = 0;
    $default_action = null;
    $page_not_found = false;
    // Имя «файла»
    $req_file = strrchr($url->get_parsed_url('path'), '/');
    // Определяем раздел по пути
    $result['folder_id'] = $nc_core->subdivision->get_by_uri($url->get_parsed_url('path'), $site_id, 'Subdivision_ID', true, true);
    // Если раздел не найден, дальнейшая обработка адреса не имеет смысла,
    // так как мы в любом случае должны вернуть FALSE
    if (!$result['folder_id']) {
        return false;
    }
    $file_name = '';
    $file_extension = '';
    $uri_date = $url->get_uri_date();
    if ($req_file != '/') {
        $req_file = substr($req_file, 1);
        if (strpos($req_file, '.')) {
            $req_file_parts = explode(".", $req_file);
            $file_name = $req_file_parts[0];
            $file_extension = strtolower($req_file_parts[count($req_file_parts) - 1]);
        }
        if (in_array($file_extension, array('html', 'rss', 'xml'))) {
            // name without extension
            $url->set_parsed_url_item('path', substr($url->get_parsed_url('path'), 0, strlen($url->get_parsed_url('path')) - strlen($req_file)));
        } else {
            // append trailing slash
            $url->set_parsed_url_item('path', rtrim($url->get_parsed_url('path'), "/") . "/");
        }
        // Адрес имеет расширение (.html, .rss, .xml) — это адрес объекта или инфоблока
        if (in_array($file_extension, array('html', 'rss', 'xml'))) {
            $result['format'] = $file_extension;
            $infoblocks_in_folder = $nc_core->sub_class->get_by_subdivision_id($result['folder_id']);
            // keyword.html — совпадение по ключевому слову объекта
            if (nc_preg_match("/^([_a-zа-я0-9-]+)\$/i", $file_name, $regs)) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        if ($file_extension == 'rss' && !$infoblock_settings['AllowRSS']) {
                            continue;
                        }
                        if ($file_extension == 'xml' && !$infoblock_settings['AllowXML']) {
                            continue;
                        }
                        // Находим объект, подходящий под имеющиеся параметры
                        if ($object_id = ObjectExists($infoblock_settings['Class_ID'], $infoblock_settings['sysTbl'], $infoblock_settings['Sub_Class_ID'], $file_name, $uri_date)) {
                            $component_id = $infoblock_settings['Class_ID'];
                            $result['resource_type'] = 'object';
                            $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                            $result['object_id'] = $object_id;
                            $result['action'] = 'full';
                            break;
                        }
                    }
                }
            }
            // news.html — ключевое слово компонента, при условии, что нет такого объекта
            if (!$result['object_id'] && nc_preg_match("/^([a-zа-я0-9-]+)\$/i", $file_name, $regs)) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        if ($infoblock_settings['EnglishName'] == $regs[1]) {
                            if ($file_extension == 'rss' && !$infoblock_settings['AllowRSS']) {
                                continue;
                            }
                            if ($file_extension == 'xml' && !$infoblock_settings['AllowXML']) {
                                continue;
                            }
                            $result['resource_type'] = 'infoblock';
                            $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                            // action может быть задан в get'e или post'e
                            if (!$result['action']) {
                                $result['action'] = $infoblock_settings['DefaultAction'];
                            }
                            break;
                        }
                    }
                }
            }
            // add_news.html, search_news.html, subscribe_news.html — добавление, поиск, подписка в компоненте
            if (nc_preg_match("/^(add|search|subscribe)_((?i:[a-zа-я0-9-]+))\$/", $file_name, $regs)) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        if ($infoblock_settings['EnglishName'] != $regs[2]) {
                            continue;
                        }
                        $result['resource_type'] = 'infoblock';
                        $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                        $result['action'] = $regs[1];
                        break;
                    }
                }
            }
            // news_5.html — отображение объекта по компоненту и идентификатору
            if (nc_preg_match("/^([a-zа-я0-9-]+)_([0-9]+)\$/i", $file_name, $regs) && $file_name == $regs[1] . "_" . $regs[2]) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        // check component in sub keyword
                        if ($infoblock_settings['EnglishName'] != $regs[1]) {
                            continue;
                        }
                        if ($file_extension == 'rss' && !$infoblock_settings['AllowRSS']) {
                            continue;
                        }
                        if ($file_extension == 'xml' && !$infoblock_settings['AllowXML']) {
                            continue;
                        }
                        // find message with requested params
                        if ($object_id = ObjectExistsByID($infoblock_settings['Class_ID'], $infoblock_settings['sysTbl'], $regs[2], $uri_date)) {
                            $component_id = $infoblock_settings['Class_ID'];
                            $result['resource_type'] = 'object';
                            $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                            $result['object_id'] = $object_id;
                            $result['action'] = 'full';
                            break;
                        }
                    }
                }
            }
            // edit_object.html — изменение объекта по ДЕЙСТВИЮ и КЛЮЧЕВОМУ СЛОВУ, при условии, что нет объекта по компоненту и идентификатору
            if (!$result['object_id'] && nc_preg_match("/^(edit|delete|drop|checked|subscribe)_((?i:[_a-zа-я0-9-]+))\$/", $file_name, $regs)) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        // find message with need params
                        if ($object_id = ObjectExists($infoblock_settings['Class_ID'], $infoblock_settings['sysTbl'], $infoblock_settings['Sub_Class_ID'], $regs[2])) {
                            $component_id = $infoblock_settings['Class_ID'];
                            $result['resource_type'] = 'object';
                            $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                            $result['object_id'] = $object_id;
                            $result['action'] = $regs[1];
                            break;
                        }
                    }
                }
            }
            // edit_news_5.html — изменение объекта по действию, компоненту и идентификатору объекта
            if (nc_preg_match("/^(edit|delete|drop|checked|subscribe)_((?i:[_a-zа-я0-9-]+))_([0-9]+)\$/", $file_name, $regs)) {
                if (!empty($infoblocks_in_folder)) {
                    foreach ($infoblocks_in_folder as $infoblock_settings) {
                        // check component in sub keyword
                        if ($infoblock_settings['EnglishName'] != $regs[2]) {
                            continue;
                        }
                        // find message with need params
                        if ($object_id = ObjectExistsByID($infoblock_settings['Class_ID'], $infoblock_settings['sysTbl'], $regs[3])) {
                            $component_id = $infoblock_settings['Class_ID'];
                            $result['resource_type'] = 'object';
                            $result['infoblock_id'] = $_db_cc = $infoblock_settings['Sub_Class_ID'];
                            $result['object_id'] = $object_id;
                            $result['action'] = $regs[1];
                            break;
                        }
                    }
                }
            }
        } else {
            // У «файла» нет расширения, либо нестандартное расширение
            // Добавить "/" и сделать переадресацию
            $result['redirect_to_url'] = $url->source_url() . ($url->get_parsed_url('query') ? "?" . $url->get_parsed_url('query') : "") . ($url->get_parsed_url('fragment') ? "#" . $url->get_parsed_url('fragment') : "");
        }
    }
    // Для разделов установить ID первого инфоблока
    if ($result['resource_type'] == 'folder' && !$file_name && $result['folder_id']) {
        if (empty($infoblocks_in_folder)) {
            $infoblocks_in_folder = $nc_core->sub_class->get_by_subdivision_id($result['folder_id']);
        }
        foreach ((array) $infoblocks_in_folder as $infoblock_settings) {
            if ($infoblock_settings['Checked'] || $infoblock_settings['sysTbl'] == 3) {
                $component_id = $infoblock_settings['Class_ID'];
                if ($uri_date && !$nc_core->get_component($component_id)->get_date_field()) {
                    continue;
                }
                $result['infoblock_id'] = $infoblock_settings['Sub_Class_ID'];
                if (!$result['action']) {
                    $result['action'] = $infoblock_settings['DefaultAction'];
                }
                break;
            }
        }
    }
    // Если есть «имя файла», но не определён по крайней мере ID инфоблока, то это неправильный путь
    if ($file_name && !$result['infoblock_id']) {
        $page_not_found = true;
    }
    // Дата в пути
    if (!$page_not_found && $uri_date) {
        if (!$result['infoblock_id'] || $result['infoblock_id'] && !$nc_core->get_component($component_id)->get_date_field()) {
            // if there is a date in URI segments and no "event" field in the corresponding component, it is an incorrect path
            $page_not_found = true;
        } else {
            $result['date'] = $uri_date;
        }
    }
    return $page_not_found ? false : $result;
}