[dev] Переопределение сортировки топиков

Статья предназначена для разработчиков плагинов и рассказывает о некоторых новых возможностях, появившихся в версии 1.1. Если быть более точным, то коммит с изменениями был залит в текущую ветку менее суток назад. Но так как это обновление решает важные застарелые проблемы, то решил написать об этом практически сразу же. Итак, известно, что прародителем Альто был движок Livestreet, и, соответственно, наш движок унаследовал, в числе прочего, множество методов для получения выборки топиков под конкретные случаи. Например:
public function GetTopicsGood($iPage, $iPerPage, $bAddAccessible = true) {
    // Список "хороших" топиков
}

public function GetTopicsDiscussed($iPage, $iPerPage, $sPeriod = null, $bAddAccessible = true) {
    // Список самых обсуждаемых топиков
}
Ну, и так далее.

Такие методы, как правило, работают по одному алгоритму: формируется фильтр, где задаются параметры отбора и порядок сортировки, а потом вызывается метод получения списка топиков через метод GetTopicsByFilter(...).

Серьезным недостатком такого подхода было то, что для всех этих узкоспециализированных методов фильтры задавались жестко в самом методе. И если разработчик хотел их изменить, ему приходилось полностью переписывать эти методы.

Как это работает сейчас.

Введено такое понятие, как «именованные фильтры». И теперь в этих узкоспециализированных методах фильтр задается через вызов метода GetNamedFilter(), куда передаются имя фильтра и дополнительные параметры. Т.е. было так:
public function GetTopicsNew($iPage, $iPerPage, $bAddAccessible = true) {
    $aFilter = array();
    // Здесь формируется фильтр ...
    return $this->GetTopicsByFilter($aFilter, $iPage, $iPerPage);
}
А теперь это так:
public function GetTopicsNew($iPage, $iPerPage, $bAddAccessible = true) {
    // Получаем именованный фильтр 'new' с доп.параметром 'accessible'
    $aFilter = $this->GetNamedFilter('new', array('accessible' => $bAddAccessible));
    return $this->GetTopicsByFilter($aFilter, $iPage, $iPerPage);
}
И теперь, если разработчик хочет изменить фильтр для метода GetTopicsNew(), он должен переопределить метод GetNamedFilter():
class PluginMine_ModuleTopic extends PluginMine_Inherits_ModuleTopic {

    public function GetNamedFilter($sFilterName, $aParams = array()) {
        // Получаем фильтр, заданный по умолчанию
        $aFilter = parent::GetNamedFilter($sFilterName, $aParams);
        if ($sFilterName == 'new') {
            $aFilter['order'] = '...'; // задаем свой порядок сортировки
        }
        return $aFilter;
    }
}
И стандартный метод GetTopicsNew() будет получать фильтр 'new', измененный плагином. Кроме того, можно задать настройки фильтра по умолчанию:
class PluginMine_ModuleTopic extends PluginMine_Inherits_ModuleTopic {

    public function Init() {
        parent::Init();
        $aFilter = array( /* новый фильтр по умолчанию */ );
        $this->SetTopicsFilter($aFilter); // задаем свой фильтр
    }
}
Разработчикам надо также иметь ввиду, что, если задаются какие-то свои специфические параметры фильтра, то, возможно, придется еще и переопределить метод buildFilter() в маппере модуля:
class PluginMine_ModuleTopic_MapperTopic extends PluginMine_Inherits_ModuleTopic_MapperTopic {

    protected function buildFilter($aFilter) {
        $sWhere = parent::buildFilter($aFilter);
        if (!empty($aFilter['...'])) {
            // здесь добавляем условия в $sWhere по своим параметрам
        }
        retuen $sWhere;
    }
}
Надеюсь, эти фичи облегчат жизнь сторонним разработчикам.

Похожие статьи


3 комментария

0
На первый взгляд то что доктор прописал, нужно будет практически попробывать как это работает.
0
Такой код только добавит лишней путаницы. Есть buildFilter в нём и назначай и переназначай.
0
Этой возможности никто не отменяет. Но если нужно изменить фильтр для конкретного случая — напр., для метода GetTopicsDiscussed(), то buildFilter() мудрено будет угадать, для чего строится фильтр.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.