Перейти к публикации
Дизайн и модификация IPS Community IPBSkinsBETA
Поиск в
  • Дополнительно...
Искать результаты, содержащие...
Искать результаты в...

metos (Blog)

  • записей
    5
  • комментария
    2
  • просмотров
    27375

[IPB 3.1.4] Устранение бага фильтрации топиков при сортировке по start_date

metos

469 просмотров

В IPB 3.1.4 пользователю предоставляется удобный инструмент фильтрации и сортировки отображаемых топиков. Но в этом инструменте есть бага. Точнее бага не в GUI, а в коде, который обрабатывает параметры запроса и строит SQL-запрос.

 

Для начала опишу причину, из-за которой пришлось этот инструмент дорабатывать. На нашем форуме есть один большущий подфорум BigForum, в котором каждый день создаётся от 4 до 20 топиков. И очень часто возникает потребность просмотра топиков, которые созданы в течении последних суток и отсортированных в порядке создания первого поста в топиках.

Я предложил главному админу (идеологу проекта) создать фейковый подфорум с названием "Все темы за последние сутки", который бы просто редиректил на BigForum с заранее установленными параметрами фильтрации и сортировки в строке запроса. Начал изучать возможность реализации этой идеи. В настройках создания нового форума нашёл опцию, в которой указавается редирект. Изучил возможные параметры в запросе, полазив по php-исходникам.

 

Screen_Hunter_0002.png

 

Строка запроса, которая осуществляет описанную фильтрацию и сортировку для форума #13:

index.php?showforum=13&prune_day=1&st=0&sort_key=start_date&sort_by=Z-A

Описание параметров запроса:

showforum=13 - указывает на ID форума в БД (BigForum)

prune_day=1 - указывает на количество дней, за которые нужно выбрать топики (1 день)

sort_key=start_date - указывает на параметр, по которому будет осуществлена сортировка (по дате создания топика)

sort_by=Z-A - указывает на направление сортировки (от большего к меньшему)

 

Так вот в ходе эксперементов выяснил, что при таких параметрах выборка топиков из БД всегда осуществляется по полю topics.last_post , что и является БАГОМ РАЗРАБОТЧИКОВ IPB. Ну сами посудите: вы хотите делать выборку по полю topics.start_date , но сделать это не можете, т.к. параметр sort_key отвечает только за сортировку. Пришлось искать место в коде, которое отвечает за это.

 

Затем главный админ решил фильтровать не за последние сутки, а за последние 3 дня. Поэтому название нового подфорума стало таким: "Все темы за последние 3 дня".

Так же было решено сделать дополнительно ещё 3 подфорума с редиректами: "Темы за последние 30 дней", "Темы за предыдущий месяц" и "Темы за позапрошлый месяц". На самом деле от двух последних тем мы отказались (после тестирования среди модераторов), но я всё равно опишу как это сделать.

 

Инструкция по доработке фильтрации и сортировки топиков.

 

Открываем на редактирование файл admin/applications/forums/modules_public/forums/forums.php и ищем строку:

$Prune = $prune_value < 100 ? (time() - ($prune_value * 60 * 60 * 24)) : ( ( $prune_value == 200 AND $this->memberData['member_id'] ) ? $this->memberData['last_visit'] : 0 );

Заменяем эту строку на:

if ($prune_value < 0) {
 $Prune = $prune_value;
} else {  
 $Prune = $prune_value < 100 ? (time() - ($prune_value * 60 * 60 * 24)) : ( ( $prune_value == 200 AND $this->memberData['member_id'] ) ? $this->memberData['last_visit'] : 0 );
}

 

Через несколько строчек идёт заполнение массива $prune_by_day, который отвечает за локализацию параметров сортировки (см. скриншот выше).

Т.к. мы хотим добавить 3 новых сортировки, то нужно добавить 3 новых параметра в массив.

Заменяем массив $prune_by_day на такой:

  $prune_by_day = array(
  '-2'   => 'show_before_prev_month',
  '-1'   => 'show_prev_month',
  '1'    => 'show_today',
  '3'    => 'show_3_days',
  '5'    => 'show_5_days',
  '7'    => 'show_7_days',
  '10'   => 'show_10_days',
  '15'   => 'show_15_days',
  '20'   => 'show_20_days',
  '25'   => 'show_25_days',
  '30'   => 'show_30_days',
  '60'   => 'show_60_days',
  '90'   => 'show_90_days',
  '100'  => 'show_all',
  '200'  => 'show_last_visit'
 );

 

Чуть ниже находим строчку "if ( $Prune )". Следующий блок кода:

    if ( $Prune )
   {
     if ( $prune_value == 200 )
     {
       /* Just new content, don't show pinned, please */
       $_SQL_AGE_PRUNE = " AND (t.last_post > {$Prune})";
     }
     else
     {
       $_SQL_AGE_PRUNE = " AND (t.pinned=1 or t.last_post > {$Prune})";
     }
   }

заменяем на такой:

    if ( $Prune > 0 )
   {
     $flt_field = 'last_post';
     if ( $sort_key == 'start_date' ) $flt_field = 'start_date';

     if ( $prune_value == 200 )
     {
       /* Just new content, don't show pinned, please */
       $_SQL_AGE_PRUNE = " AND (t.$flt_field > {$Prune})";
     }
     else
     {
       $_SQL_AGE_PRUNE = " AND (t.pinned=1 OR t.$flt_field > {$Prune})";
     }
   } 
   else 
   {
     // отрицательные значения параметра prune_day имеет силу только при сортировке по полю start_date !!!
     if ( $sort_key == 'start_date' ) 
     {         
       if ( $Prune == -1 OR $Prune == -2 ) 
       {
         // прошлый и позапрошлый месяц
         $ct = time();
         $y = intval(date('Y', $ct));
         $m = intval(date('n', $ct));
         $m += 1 + $Prune;
         if ($m <= 0) { 
           $y--;
           $m += 12;
         }  
         $d2 = strtotime(sprintf("%04d-%02d-%02d", $y, $m, 1));
         $m--;
         if ($m <= 0) { 
           $y--;
           $m += 12;
         }  
         $d1 = strtotime(sprintf("%04d-%02d-%02d", $y, $m, 1));
         $_SQL_AGE_PRUNE = " AND (t.pinned=0 AND t.start_date >= $d1 AND t.start_date < $d2)";
       }
     } 
   }

Данный код как раз таки заставит при указании sort_key=start_date производить выборку из БД по полю topics.start_date. Также данный код отвечает за отображение форумов "Темы за предыдущий месяц" и "Темы за позапрошлый месяц".

 

Чуть ниже находим строчку:

else if ( ( $_SQL_EXTRA or $_SQL_AGE_PRUNE ) and ! $this->request['modfilter'] )

и заменяем её на:

else if (   $_SQL_EXTRA or $_SQL_AGE_PRUNE   OR    $this->request['modfilter'] )

Новая строка взята из 3.3.4 (видимо баг какойто исправили в отображении топиков для модераторов).

 

Сохраняем файл forums.php и копируем его на WEB-сервер.

 

Теперь нужно локализировать 3 новых параметра.

Открываем на редактирование файл /admin/applications/forums/xml/public_forums_language_pack.xml и после строчки <languagegroup> добавляем 3 блока:

    <lang>
     <word_app>forums</word_app>
     <word_pack>public_forums</word_pack>
     <word_key>show_before_prev_month</word_key>
     <word_default>From: before prev days</word_default>
     <word_custom>За: позапрошлый месяц</word_custom>
     <word_default_version>31006</word_default_version>
     <word_custom_version/>
     <word_js>0</word_js>
   </lang>
   <lang>
     <word_app>forums</word_app>
     <word_pack>public_forums</word_pack>
     <word_key>show_prev_month</word_key>
     <word_default>From: prev days</word_default>
     <word_custom>За: предыдущий месяц</word_custom>
     <word_default_version>31006</word_default_version>
     <word_custom_version/>
     <word_js>0</word_js>
   </lang>
   <lang>
     <word_app>forums</word_app>
     <word_pack>public_forums</word_pack>
     <word_key>show_3_days</word_key>
     <word_default>From: 3 days</word_default>
     <word_custom>За: 3 дня</word_custom>
     <word_default_version>31006</word_default_version>
     <word_custom_version/>
     <word_js>0</word_js>
   </lang>

Сохраняем файл public_forums_language_pack.xml и копируем его на WEB-сервер.

 

Заходим в админскую панель.

Импортируем файлик public_forums_language_pack.xml в кеш IPB ("Внешний вид" -> "Языки системы" -> "Загрузка XML-архива с языковыми настройками").

Создаём четыре новых форума, в каждом из которых заполняем поле "Redirect URL":

1) "Все темы за последние 3 дня" : index.php?showforum=13&prune_day=3&st=0&sort_key=start_date&sort_by=Z-A

2) "Все темы за последние 30 дней" : index.php?showforum=13&prune_day=30&st=0&sort_key=start_date&sort_by=Z-A

3) "Темы за предыдущий месяц" : index.php?showforum=13&prune_day=-1&st=0&sort_key=start_date&sort_by=Z-A

4) "Темы за позапрошлый месяц" : index.php?showforum=13&prune_day=-2&st=0&sort_key=start_date&sort_by=Z-A

 

Этим самым мы создали удобную навигацию по BigForum, а также пофиксили фильтрацию топиков при указании сортировки "По: дате открытия".

 

PS. Данная бага с выборкой присутствует и в IPB 3.3.4



1 комментарий


Рекомендованные комментарии

Ну это не совсем баг. "Показать за время" никак не подразумевает, что выборка будет идти по потому же полю что указано в сортировке. Тут два варианта: либо по последнему сообщению, либо по дате создания. Очевидно что разработчики решили сделать по последнему сообщению, и имхо это вполне разумно.

Ну если вам нужно чтобы именно при "Сортировать по" в селекте участвовало поле start_date, создайте отдельное условие

 

$prune_field = ( $sort_key == 'start_date') ? 'start_date' : 'last_post';

 

Зачем весь остальной код, так и не понял.

Поделиться комментарием


Ссылка на комментарий

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас
×
×
  • Создать...