[IPB 3.1.4] Устранение бага фильтрации топиков при сортировке по start_date - Дизайн и модификация Invision Power Board

Перейти к содержимому

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

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

-IMG-

Строка запроса, которая осуществляет описанную фильтрацию и сортировку для форума #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
0
Это нравится metos

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

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

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


Зачем весь остальной код, так и не понял.
0
Страница 1 из 1

Обратные ссылки на эту запись [ URL для обратной ссылки ]

Нет обратных ссылок на эту запись

Случайное изображение

г. Саламанка

0 посетителей

0 гостей
0 пользователей
0 скрытых

Теги

    Категории

    Последние посетители

    • Турин  »
      04 Ноя 2017 - 04:21
    • Estomel  »
      01 Ноя 2017 - 18:00
    • vitfix  »
      26 Авг 2017 - 21:11
    • Strategius  »
      22 Фев 2017 - 12:51
    • siv1987  »
      20 Авг 2016 - 15:09
    • ovi8  »
      12 Авг 2016 - 23:54
    • danzo  »
      21 Окт 2015 - 11:37
    • nervud  »
      27 Июл 2015 - 18:07
    • Mac  »
      05 Май 2015 - 17:02
    • FOMEN  »
      02 Мар 2015 - 12:51
    • tolik777  »
      15 Фев 2015 - 14:44
    • NoName  »
      11 Янв 2015 - 14:47
    • verbatim1  »
      07 Дек 2014 - 16:10
    • Zero108  »
      10 Сен 2014 - 11:06
    • 6letpwnz  »
      16 Авг 2014 - 23:00

    MyBlogLog

    Twitter


    Контактная информация

    Вопросы по работе сайта

    +7 (917) 501-4765
    C 10 до 20 в рабочие дни (время московское)

    Техническая поддержка

    Контактные данные специалистов

    Дизайн форумов

    IPB 3.x ¦ IPB 2.x

    Бесплатные шаблоны

    IPB 3.2 – 3.4 ¦ IPB 3.1 ¦ IPB 3.0 ¦ IPB 2.2 – 2.3 ¦ IPB 2.1 ¦ Клипарт
    Лицензия на использование ¦ Ваша поддержка ¦ О проекте
    Copyright © 2005-2017 IPBSkins.ru Team
    При копировании материалов с сайта
    прямая ссылка на источник обязательна