Example #1
0
<?php

return array('fields' => function () {
    $pages = Page::all_by_id();
    $pages_list = [];
    if (isset($pages) && is_object($pages) && $pages->count()) {
        #$pages_list = $pages->lists('name', 'id');
        foreach ($pages as $page) {
            if ($page->type_id == 1) {
                $pages_list[$page->id] = $page->name;
            }
        }
    }
    /**
     * Предзагружаем нужные словари с данными, по системному имени словаря, для дальнейшего использования.
     * Делается это одним SQL-запросом, для снижения нагрузки на сервер БД.
     */
    $dics_slugs = array('types');
    $dics = Dic::whereIn('slug', $dics_slugs)->with('values')->get();
    $dics = Dic::modifyKeys($dics, 'slug');
    #Helper::tad($dics);
    $lists = Dic::makeLists($dics, 'values', 'name', 'id');
    #Helper::dd($lists);
    $lists_ids = Dic::makeLists($dics, null, 'id', 'slug');
    #Helper::dd($lists_ids);
    return array('project_type_id' => array('title' => 'Тип проекта', 'type' => 'select', 'values' => $lists['types'], 'default' => Input::get('filter.fields.project_type_id') ?: null), 'page_id' => array('title' => 'Страница проекта', 'type' => 'select', 'values' => $pages_list));
}, 'fields_i18n' => function () {
    return array('project_name' => array('title' => 'Название проекта', 'type' => 'text'), 'mainpage' => array('no_label' => true, 'title' => 'Показывать на главной', 'type' => 'checkbox', 'label_class' => 'normal_checkbox'), 'image' => array('title' => 'Фоновое изображение', 'type' => 'image'), 'short' => array('title' => 'Краткое описание (анонс)', 'type' => 'textarea'));
}, 'hooks' => array('after_store_update_destroy_order' => function ($dic = NULL, $dicval = NULL) {
    Cache::forget('dic_' . $dic->slug);
}), 'second_line_modifier' => function ($line, $dic, $dicval) {
    /**
     * Возвращаем пометку об активности текущего пункта меню
     *
     * @param $element
     * @return bool
     */
    private function get_active($element) {
        #return false;

        #Helper::tad($element);

        $is_active = false;

        /**
         * Собственное правило для определения активности пункта меню
         * Проверка текущего URL на соответствие шаблону регулярного выражения
         */
        if (isset($element) && is_array($element)) {

            if (
                (@$element['use_active_regexp'] && @$element['active_regexp'])
            ) {

                #Helper::ta($element);

                if (@$element['use_active_regexp'] && @$element['active_regexp']) {

                    /**
                     * Сделаем замену в регулярке, если у нас обычная страница
                     */
                    if (isset($element['type']) && $element['type'] == 'page') {
                        $page = isset($this->pages[$element['page_id']]) ? $this->pages[$element['page_id']] : NULL;
                        if ($page && is_object($page) && $page->slug) {
                            $element['active_regexp'] = strtr($element['active_regexp'], [
                                '%slug%' => $page->slug, '%url%' => $page->slug,
                            ]);
                        }
                        #var_dump($element['active_regexp']);
                    }

                    try {
                        $element['active_regexp'] = $this->replaces($element['active_regexp']);
                    } catch (Exception $e) {
                        echo 'Error: ', $e->getMessage(), "\n";
                        Helper::tad($element);
                        #die;
                    }

                    /**
                     * Замена конструкций вида %_page_sysname_>url%
                     */
                    preg_match_all('~\%([A-Za-z0-9\-\_]+)\>url\%~is', $element['active_regexp'], $matches);

                    if (isset($matches[1]) && count($matches[1])) {

                        #var_dump($matches);
                        #Helper::ta($this->pages_by_sysname);
                        $pages = new Collection();
                        $page_sysnames = [];
                        ## Все найденные конструкции
                        foreach ($matches[1] as $page_sysname) {
                            if (isset($this->pages_by_sysname[$page_sysname])) {
                                ## Ищем текущую страницу среди страниц текущего меню
                                $pages[$page_sysname] = $this->pages_by_sysname[$page_sysname];
                            } elseif (NULL !== Config::get('pages.preload_pages_limit') && NULL !== ($tmp = Page::by_sysname($page_sysname))) {
                                ## Ищем текущую страницу в кеше страниц
                                $pages[$page_sysname] = $tmp;
                            } else {
                                ## Если страница уж совсем нигде не нашлась - придется ее подгружать из БД. Делать это будем позже одним запросом.
                                $page_sysnames[] = $page_sysname;
                            }
                        }
                        ## Если есть список страниц для их подгрузки из БД - сделаем это!
                        if (count($page_sysnames)) {
                            $temp = Page::whereIn('sysname', $page_sysnames)->where('version_of', NULL)->get();
                            if (count($temp)) {
                                ## Если что-то нашлось - разложим по sysname
                                $pages_by_sysnames = new Collection();
                                foreach ($temp as $tmp) {
                                    if (!$tmp->sysname)
                                        continue;
                                    $pages_by_sysnames[$tmp->sysname] = $tmp;
                                }
                                if (count($pages_by_sysnames)) {
                                    ## Найдем недостающие страницы и добавим их в список
                                    foreach ($page_sysnames as $psn) {
                                        if (isset($pages_by_sysnames[$psn]))
                                            $pages[$psn] = $pages_by_sysnames[$psn];
                                    }
                                }
                            }
                            unset($temp, $tmp);
                        }
                        #Helper::tad($pages_by_sysnames);
                        #Helper::tad($pages);

                        $replaces = [];
                        ## Еще раз пройдемся по списку найденных паттернов и сгенерируем список для замены
                        foreach ($matches[1] as $page_sysname) {
                            if (isset($pages[$page_sysname]) && NULL !== ($page = $pages[$page_sysname])) {
                                $replaces['%' . $page->sysname . '>url%'] = $page->slug;
                            }
                        }
                        #dd($replaces);

                        ## Производим замену паттернов
                        $element['active_regexp'] = strtr($element['active_regexp'], $replaces);
                        ## Если остались ненайденные паттерны - удалим их
                        $element['active_regexp'] = preg_replace('~\%([A-Za-z0-9\-\_]+)\>url\%~is', '', $element['active_regexp']);
                    }

                    #Helper::dd(Request::path());
                    #Helper::dd($element['active_regexp']);
                    #Helper::dd(preg_match($element['active_regexp'], Request::path()));

                    $is_active = @(bool)preg_match($element['active_regexp'], Request::path());
                    #return $is_active;
                }

                if ($is_active)
                    return true;
            }
        }

        /**
         * Возвращаем пометку об активности ссылки, в зависимости от типа элемента меню
         */
        switch(@$element['type']) {

            case 'page':
                #Helper::ta($this->pages);
                #Helper::ta($this->pages[$element['page_id']]);
                $page = isset($this->pages[$element['page_id']]) ? $this->pages[$element['page_id']] : NULL;
                #Helper::ta($page);
                if (!$page)
                    return NULL;

                #$return = $this->isRoute('page', ['url' => $page->slug]);
                #$return = $this->isRoute('page', $page->slug);

                $is_active = $this->isRoute($page->start_page ? 'mainpage' : 'page', ['url' => $page->slug]);
                #Helper::tad($is_active);

                if ($is_active)
                    return $is_active;

                ## Если активна опция определения активности по дочерним страницам (из структуры страниц)
                if (@$element['use_active_hierarchy']) {

                    #Helper::ta($element);
                    #Helper::ta($page);

                    ## Получим структуру страниц из Storage
                    $current_hierarchy = Storage::where('module', 'pages')->where('name', 'hierarchy')->pluck('value');
                    $elements = json_decode($current_hierarchy, false);
                    #Helper::d($elements);
                    #Helper::d($elements[$page->id]);

                    ## Сформируем id_left_right
                    $id_left_right = [];
                    if (count($elements)) {

                        foreach($elements as $element_id => $element) {
                            #dd($element);
                            $id_left_right[$element_id] = array();
                            $id_left_right[$element_id]['left'] = $element->left;
                            $id_left_right[$element_id]['right'] = $element->right;
                        }
                    }
                    #Helper::tad($id_left_right);

                    ## Получим IDs страниц, для которых текущая страница (пункт меню) является родителем
                    $pages_ids = (new NestedSetModel())->get_children_ids_by_id_from_id_left_right($id_left_right, $page->id);
                    #Helper::ta('PAGES IDS:');
                    #Helper::ta($pages_ids);

                    ## Если у текущей страницы (пункта меню) в иерархии есть потомки
                    if (isset($pages_ids) && is_array($pages_ids) && count($pages_ids)) {

                        ## Получение страниц-потомков по их IDs
                        ## Как будем искать страницы - в кеше или в БД?
                        if (Config::get('pages.not_cached')) {

                            #Helper::tad('PAGES CACHE DISABLED! MenuConstructor:709');
                            ## Кеширование отключено (или не найдено ни одной страницы) - ищем в БД
                            $pages = (new Page())
                                ->where('publication', 1)
                                ->where('version_of', NULL)
                                ->whereIn('id', $pages_ids)
                                ->get()
                            ;

                        } else {

                            ## Если страницы есть в кеше
                            if (count(Page::all_by_id())) {

                                ## Ищем все нужные страницы в кеше по их IDs
                                foreach ($pages_ids as $page_id) {

                                    $pages[] = Page::by_id($page_id);
                                }
                            }
                        }

                        ## Если получены объекты страниц
                        if (isset($pages) && count($pages)) {

                            #Helper::dd($pages);

                            ## Перебираем их
                            foreach ($pages as $page) {

                                if (!is_object($page)) {
                                    #dd($page);
                                    continue;
                                }

                                ## Проверка на активность
                                $is_active = $this->isRoute($page->start_page ? 'mainpage' : 'page', ['url' => $page->slug]);
                                if ($is_active)
                                    return true;
                            }
                        }

                    }

                    $is_active = false;
                }

                return $is_active;

                break;

            case 'link':
                return (bool)preg_match('~' . $element['url'] . '$~s', Request::fullUrl());
                break;

            case 'route':
                $route_params = array();
                if ('' != ($element['route_params'] = trim($element['route_params']))) {
                    $temp = explode("\n", $element['route_params']);
                    if (@count($temp)) {
                        foreach ($temp as $tmp) {
                            $tmp = trim($tmp);
                            if (!$tmp) {
                                continue;
                            }
                            if (strpos($tmp, '=')) {
                                $tmp_params = explode('=', $tmp, 2);
                                $route_params[trim($tmp_params[0])] = trim($tmp_params[1]);
                            } else {
                                $route_params[] = $tmp;
                            }
                        }
                    }
                }
                return $this->isRoute($element['route_name'], $route_params);
                break;

            case 'function':
                #Helper::dd($element);
                $function = Config::get('menu.functions.' . $element['function_name']);
                if (isset($function) && is_callable($function)) {
                    $result = $function();
                    #return $result['url'];


                    /**
                     * Одиночная ссылка
                     */
                    #return (bool)preg_match('~' . $result['url'] . '$~s', Request::fullUrl());
                    if (isset($result['url']))
                        $result = array($result);

                    /**
                     * Перебираем весь массив ссылок
                     */
                    foreach ($result as $res)
                        if (isset($res['url']) && (bool)preg_match('~' . $res['url'] . '$~s', Request::fullUrl()) == true)
                            return true;

                }
                return false;
                break;

            default:
                return false;
                break;
        }
    }