Друпальчики

Туристическая соцсеть ТурБаза

Уже достаточно давно мы в NetSpark работаем над социальной сетью туристического толка ТурБаза. Сейчас можно, так сказать, поделиться промежуточным результатом.

Сделан сайт на Drupal 7, на заказ. Фич на сайте много, активно используется Solr, Message, OG, Gmap и много чего еще. Кастомного кода тоже немало. Краткий обзор функционала и ссылки на полезные статьи по теме можно найти в нашем портфолио. Если какие вопросы, можно писать в комментарии прямо тут.

CasperJS и Drupal

На днях разбирался в прогрессивной (кто-то даже говорит — хипстерской) библиотеке front-end-тестирования CasperJS. В результате родилась заметка о предмете. Заметка получилась немножко длинной, не обессудьте: как говорится, я написал длинное письмо, потому что не было времени написать короткое.

Если тезисно, в заметке рассматриваются следующие вопросы:

  • что такое CasperJS;
  • как установить библиотеку;
  • как выглядит примитивный скрипт;
  • важная особенность — casper.evaluate();
  • CasperJS foundation для Drupal;
  • пример тестового скрипта checkout.js: цепочка действий от «товар в корзине» до «заказ оформлен».

Комментарии, дополнения и дискуссии (особенно на тему «нужны ли вообще тесты») — приветствуются.

Прочитать заметку можно на NetSpark.Ru: Front-end тестирование с помощью CapserJS.

Баг пагинации во Views 2

В процессе доработки Cotranslate.Net столкнулся с любопытным багом пагинации во Views 2 (Drupal 6 т.е.), с которым раньше как-то не встречался.

Воспроизводится он так:

1. Делаем модуль, в нем создаем новую таблицу истории (лога) с разными записями о том, что происходило с материалом.
2. Дружим эту таблицу с Views. Поскольку данные таблицы актуальны только для материалов, делаем ее не базовой, а просто join-им с {node}.
3. Создаем представление на базе материалов, в котором выводим поля из таблицы истории, в представление добавляем пагинацию (хоть полную, хоть мини — не важно).
4. Пока выводятся записи для всех материалов, все нормально, пагер появляется и работает.
5. Теперь добавим в таблицу аргумент, либо просто фильтр по nid (чтобы вывести историю только для заданного материала).
6. Profit Пагер немедленно пропадает. Причем не только из вывода — даже в SQL-запросе представления нет никаких его следов. И без разницы как выводить: блоком, аттачем, страницей, программно — пагера все равно нет.

Видимо, Views 2 считает, что если базовое значение (материал) — одно, то и строить пагер незачем. Самый простой (и примененный мной) выход — интегрировать таблицу истории как базовую и построить вьюху относительно этой таблицы, с присоединением материала через relationship. Тогда работает.

Интересно, есть ли такой баг во Views 3? На уровне работы с полями и entityreference — не воспроизводится.

Drupal 8, привет

Пока работа, и проекты, суд да дело, времени ни на что не остается. Ни заметку на домовую страницу накатать, ни что-нибудь новенькое потыркать. А ведь хочется. Ну хотя бы Drupal 8 изнутри потыркать, а не только почитать про. И лучше бы заранее, а не через полгода после выхода, как в прошлый раз.
Сейчас вроде чуть-чуть посвободнее стало: несколько минут в день можно найти. Сделал над собой усилие — приступил:

О результатах сообщу.

Микросовет — абсолютные урлы

Как правило, фраза «Я сейчас вставлю в блок иконки с абсолютными путями, а на рабочем домене когда-нибудь потом вспомню и поменяю» истинна только на первую половину.
Следует об этом помнить.

User login block на продвинутых костылях

Как известно, всеми любимый блок логина в Друпале не появляется на страницах регистрации и восстановления пароля (user/register и user/password соотвественно). Объясняется это бессмысленное, на мой взгляд, ограничение обычным usability. В коде user.module, в котором оно реализовано, так и написано:

// For usability's sake, avoid showing two login forms on one page.
if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
  $block['subject'] = t('User login');
  $block['content'] = drupal_get_form('user_login_block');
}

(это функция user_block_view)
Написано, правда, про то что не надо показывать две формы логина на одной странице, но паровозом к этому цепляется и регистрация с восстановлением.

А что если бы мы хотели избавиться от ограничения? Придется добавить немного костылей.

Противникам патчей ядра дальше читать не нужно.

Продолжительность видео с помощью getid3

Как известно, для показа видеороликов, загруженных на сайт, неплохо подходит модуль Video. Хотя в статьях и мануалах на модуль, в основном, речь идет о настройке модуля так, чтобы загруженные файлы были автоматически перекодированы в нужный формат (ffmpeg-ом), обязательным условием это не является: загрузив на сайт видео в подходящем формате, его можно показывать без всякого перекодирования.

Но есть тут один нюанс. Дело в том, что в текущей версии модуля информация о видеоролике (такая как продолжительность, например) существует только в таблице БД, которая заполняется при перекодировании. То есть чтобы вывести длительность ролика, мы должны его перекодировать. Несправедливо как-то.

К счастью, эту проблему легко решить.

Читать целиком на NetSpark.ru

Особенность ajax_command_replace

Оказывается, у функции ajax_command_replace() есть интересная особенность, которая, скажем так, не совсем документирована. Суть в том, что JS, отвечающий за замену старого html — новым, от нового кода ждет того, что это будет один тег верхнего уровня, а не два, три или больше. Вложенных тегов может быть до фига, но верхнего уровня — только один. В противном случае новый код будет автоматически обернут в дополнительный div.

Особенность эта интересна прежде всего тем, что если о ней не знать, можно весь мозг сломать, [censored].

Ссылка more из Views в заголовке блока

Как известно, модуль Views позволяет выводить в генерируемых им блоках ссылку «еще». Вот так можно по-быстрому взять эту ссылку из содержимого блока и поместить в заголовок блока:

/**
 *
 * hook_block_view_alter() implementation
 *
 * @param type $data
 * @param type $block
 */

function mymodule_block_view_alter(&$data, $block) {
  if (($block->module == 'views') && strpos($data['content']['#markup'], '<div class="more-link">')) {
    $matches = array();
    preg_match('/<div class="more-link">[\s]*<a href="(.*)"/', $data['content']['#markup'], $matches);
    $data['subject'] = '<a href="' . $matches[1] . '">' . $data['subject'] . '</a>';
  }
} //mymodule_block_view_alter

Полезно, когда в ссылке содержатся аргументы, и просто так в заголовок их не прописать. Ну и когда блоков много и лень прописывать заголовок каждому.