Наследования контроллеров - правка

 

Всем доброго времени суток. Идея системы RS-MINI и RS-SITE v2.x.x (на которой сейчас работает мой блог) очень схожи. По сути я переписываю RS-SITE пытаясь улучшить структуру и код движка. Сегодня в RS-SITE я наткнулся на небольшой баг, а именно неадекватное наследования контроллеров при определенных условиях. Про этот недочет я знал уже давно, но пришел к выводу, что этот баг можно обойти без исправлений в ядре, а путем переподключения контроллеров.

Сегодня же у меня дошли руки исправить этот баг, по сему я решил сделать то же самое и в RS-MINI.

В чем собственно заключается баг?

Суть проблемы очень сложно объяснить, но я все же попробую. Представьте, что к верхнему блоку контроллеров прикручено два контроллера:

  • admin.access.permission — контроллер который получает поля авторизированного пользователя
  • pub.search.form — контроллер поиска по сайту

Оба контроллера наследуются для внутренних страниц. Теперь предположим где-нибудь на внутренней страницы, мы изменили параметр контроллера pub.search.form. Ожидается что на странице будут отрабатываться контроллеры в следующем порядке:

  • сначала admin.access.permission
  • а потом pub.search.form с новыми параметрами

Но не тут то было! Текущий алгоритм унаследует контроллеры уже в новом порядке:

  • сначала контроллер pub.search.form с измененными параметрами (собственно очередь сбивается как раз из-за того что у контроллера новые параметры)
  • а уже потом контроллер admin.access.permission

Ранее я решал этот вопрос, переподключив контроллеры в нужном мне порядке. Сейчас обдумав и взвесив, я решил сделать так, что бы подключенный контроллер с новыми параметрами вставал на место уже существующего унаследованного контроллера, тем самым не сбивая порядок отработки.

Как это реализовать?

Все довольно просто, нам всего лишь нужно для каждого объекта page.class.php пересобрать свойство controllerList так сказать с нуля. Сначала мы в это свойство впихнем контроллеры которые переданные по наследству, а уже потом все остальные. Если среди этих самый остальных (контроллеры подключенные на странице), будет контроллер который есть в списке унаследованных, то мы просто заменим контроллер который есть в списке, на тот который подключен к странице на прямую.

В общем вот код метода unionController() класса page.class.php (который лежит в папке /rs-mini/core/)

    /*
     * метод перезаписывает существующий контроллер вместе с параметрами
     *
     * @access - public
     *
     * @param array inhControllerList - массив с унаследованными контроллерами
     */

    public function unionController($inhControllerList)
    {
         // блоки к которым цепляются контроллеры
        $blocks = array('top', 'center', 'bottom');

        // если у страницы вообще нет контроллеров, то просто сохраняем наследованные контроллеры на этой страницы
        if (!$this->controllerList) {
            
            // прежде чем сохранять, необходимо контроллерам отметить, что они наследники
            // листаем блоки
            foreach ($blocks as $block)
                // если среди наследуемых контроллеров есть данный блок
                if (isset($inhControllerList[$block]))
                    // листаем контроллеры этого блока
                    foreach ($inhControllerList[$block] as $inhKey => $inhController)
                        // отмечаем у копии объекта контроллера что он наследуемый
                        $inhControllerList[$block][$inhKey]->inheritFlag = TRUE;
            
            // записываем список контроллеров в свойство
            $this->controllerList = $inhControllerList;
            return;
        }
        
        // если у страницы есть контроллеры
        // листаем блоки
        foreach ($blocks as $block)
            // если среди наследуемых контроллеров есть данный блок
            if (isset($inhControllerList[$block])) {
                // массив с новым порядком контроллеров
                $newList = array();
                
                // листаем список наследуемых контроллеров
                foreach ($inhControllerList[$block] as $inhKey => $inhController)
                    // ищем есть ли на страницы такой же подключенный контроллеры
                    // если на странице есть листаемый блок контроллеров
                    if (isset($this->controllerList[$block])) {
                        
                        // флаг позволяющий определить был ли найден контроллер
                        $found = FALSE;
                        
                        // листаем контроллеры страницы
                        foreach ($this->controllerList[$block] as $controllerKey => $controller)
                            // если id контроллера страницы совпадает с id контроллера наследника
                            if ($controller->controllerID == $inhController->controllerID) {
                                
                                // отмечаем флаг, что контроллер найден
                                $found = TRUE;
                                
                                // отмечаем что данный контроллер унаследован
                                $this->controllerList[$block][$controllerKey]->inheritFlag = TRUE;
                                   
                                // запускаем метод который сольет параметры наследуемого контроллера и параметры
                                // контроллера подключенного на этой странице
                                $this->controllerList[$block][$controllerKey]->unionParams($inhController->getParams());
                                
                                // записываем контроллер в новый блок
                                $newList[] = $this->controllerList[$block][$controllerKey];
                            }
                            
                        // если контроллер не был найден
                        if ($found === FALSE) {
                            // говорим что он унаследован
                            $inhController->inheritFlag = TRUE;
                            // записываем контроллер в новый блок
                            $newList[] = $inhController;
                        }
                            
                    }
                    
                    // если на странице нет листаемого блока контроллеров
                    else {
                        // отмечаем унаследованный контроллер как унаследованный
                        $inhController->inheritFlag = TRUE;
                        
                        // записываем контроллер в новый блок
                        $newList[]                  = $inhController;
                    }
                    
                // теперь нужно в массив $newList записать контроллеры страницы, которых
                // в массиве $newList еще нет
                // если на странице есть данный блок контроллеров
                if (isset($this->controllerList[$block]))
                    // листаем контроллеры страницы
                    foreach ($this->controllerList[$block] as $controllerKey => $controller) {
                        
                        // флаг позволяющий определить был ли найден контроллер
                        $found = FALSE;
                        
                        // листаем контроллеры лежащие в массиве $newList
                        foreach ($newList as $new)
                            // если id контроллеров совпадают
                            if ($new->controllerID == $controller->controllerID)
                                // переключаем флаг
                                $found = TRUE;
                                
                        // если контроллер среди $newList не найден
                        if ($found === FALSE)
                            // то записываем его туда
                            $newList[] = $controller;
                    }
                    
                // полностью заменяем блок контроллеров страницы
                $this->controllerList[$block] = $newList;
            }
    }

Код хорошо задокументирован, думаю у Вас не будет проблем с пониманием этого гигантского метода Улыбаюсь

Заключение

Если у Вас е сть какие либо вопросы, то задавайте их в комментариях. Весь код движка на данном этапе разработки можно скачать в конце статьи.

Очень надесь что материал не особо сложный, и в нем можно хоть как-то разобраться

Всего Вам наилучшего, на сегодня у меня все!

Прикрепленные файлы

 

Возможно Вам будут интересны следующие заметки

Комментарии (0)

Ваше имя *
Сайт
Ваш E-mail *
Ваше сообщение *
 
Вы не подтвердили условия политики конфиденциальности.
К данной статье пока нет комментариев.