Поковыряемся в модуле Gravatar integration
Как многие знают, есть в интернетах сервис Gravatar, сопоставляющий пользовательские email-ы с аватарками. Благодаря данному сервису даже анонимы могут иметь собственный аватар, всего лишь указав email рядом с вновь написанным комментарием. Также многим известно, что Gravatar легко и непринужденно поддерживается известной блогомерзкой CMS Wordpress через соответствующий плагин. Есть такой модуль и для Друпала. И называется он Gravatar integration.
Настроить этот модуль для использования граватарок в комментариях — несложно. Этот процесс подробно описал xandeadx в статье «Интеграция Gravatar с помощью одноимённого модуля», так что останавливаться на нем не буду. Далее — о другом.
Модуль Gravatar я хотел поставить уже давно. Люблю я грешным делом все эти аватарки красивые. Но мешало мне то, что также я люблю блок последних комментариев (см. слева). В нем юзерпики загружаются через Views и уменьшаются через imagecache. А поставив Gravatar несколько месяцев назад, я обнаружил отсутствие какой-либо интеграции с Views. Это значит, в блоке будут одни аватарки, а в комментариях и на форуме — другие. Что, конечно, неприятно. Пришлось тогда от модуля отказаться.
А сегодня, исполненный решимости, поставил Gravatar еще раз — с целью добавить загрузку граватарок прямо в шаблоне темизации блока для всех пользователей, не установивших себе обычный юзерпик. Тем более, в последних новостях модулей проходил модуль Imagecache external, позволяющий использовать imagecache для обработки изображений из внешних источников — его тоже хотелось опробовать.
Для начала, полез в код модуля и обнаружил нужную функцию:
* Generate a gravatar URL.
*
* @param $mail
* A string with an e-mail address.
* @param $options
* An associative array of additional options, with the following keys:
* — 'default'
* A string with the default gravatar image parameter. Defaults to the
* result of _gravatar_get_default_image() with the current value of the
* gravatar_default variable.
* — 'size'
* An integer of the desired size of the image. Defaults to smallest size
* of the user_picture_dimensions variable.
* — 'rating'
* A string with a MPAA rating limit for the image. Can be 'G', 'PG', 'R',
* or 'X'. Defaults to 'G'.
* — 'cache'
* A boolean if TRUE, the resulting image will be cached. Defaults to FALSE.
* This feature is not yet implemented.
* @return
* An URL-encoded string with the gravatar image.
*/
function gravatar_get_gravatar($mail, $options = array()) {
static $is_https;
if (!isset($is_https)) {
$is_https = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
}
// Merge default options.
$options += array(
'default' => _gravatar_get_default_image(gravatar_var('default')),
'size' => _gravatar_get_size(),
'rating' => variable_get('gravatar_rating', 'G'),
'cache' => FALSE,
'force default' => FALSE,
);
$hash = md5(drupal_strtolower($mail));
$gravatar = $is_https ? variable_get('gravatar_url_ssl', GRAVATAR_URL_SSL) : variable_get('gravatar_url', GRAVATAR_URL);
$gravatar .= $hash . '.jpg';
$query = array(
'd' => $options['default'],
's' => $options['size'],
'r' => $options['rating'],
'f' => $options['force default'] ? 'y' : '',
);
$query = array_filter($query);
return url($gravatar, array('query' => $query));
}
gravatar_get_gravatar() принимает два аргумента:
- $mail — строку, содержащую email пользователя;
- $options — массив опций получения граватарки.
В опциях передаются:
- size — размер изображения (все граватарки — квадратные);
- default — изображение по умолчанию, которое будет показано при отсутствии граватарки (о чем далее);
- rating — рейтинг MPAA (на случай если вы хотите не показывать матерных и неприличных аватарок);
- force default — принудительный вывод изображения по умолчанию.
Также из кода понятно, что поскольку массивы опций соединяются через оператор суммы, все опции, переданные в аргументах, не будут заменены дефолтными.
По идее, нас устраивают дефолтные установки. Значит, надо (предварительно настроив imagecache external) получить граватарку и вывести ее примерно так:
Дело в том, что тогда Gravatar возвращает то, что указано в опции default, а точнее — либо одну из трех локально сохраненных дефолтных картинок, либо рандомную граватарку (монстрики, рожицы, абстракции, квадратики), либо логотип сервиса. И оказывается, у imagecache external не получается пропустить через себя дефолтные картинки. В результате все они заменяются логотипом. Из-за этого imagecache external здесь не подходит.
Решил вручную добавить размер в опции — пусть Gravatar сам уменьшает изображения:
Тем не менее, с этим вариантом тоже есть проблема: если в качестве дефолтного используется изображение, размещенное на сайте (например, черный силуэт, входящий в модуль) оно будет отображаться без уменьшения, так как грузится с сайта, а не с сервиса Gravatar. Но эту проблему легко решить заданием опции default, равной адресу заранее уменьшенной копии изображения. Меня же больше интересовали рандомные рожицы, а они отображались нормально.
Впрочем, ближайшее рассмотрение показало, что все рандомные граватарки — не такие уж и рандомные, а даже наоборот — одинаковые. Внимательное изучение приведенного выше кода функции gravatar_get_gravatar() показало, что для получения картинки используется md5-хэш аргумента $mail. Очевидно, если разные пользователи не ввели имейлы, аргумент $mail для них будет одинаково пустым. И хэш, соответственно, будет одинаковым тоже. Потому они получат одну и ту же рандомную граватарку.
В то же время при выводе комментариев эти пользователи получают разные граватарки. Почему? Потому что модуль Gravatar integration манипулирует аргументом $mail для генерации разных хэшей для разных анонимных пользователей. Вот часть кода функции _gravatar_get_account_user_picture() прямо перед вызовом gravatar_get_gravatar():
$options = array();
if (empty($mail)) {
$options['force default'] = TRUE;
// Use various fallbacks to provide a unique default gravatar.
if (!empty($account→hostname)) {
$mail = $account→hostname;
}
elseif (!empty($account→homepage)) {
$mail = $account→homepage;
}
else {
$mail = serialize($account);
}
}
return gravatar_get_gravatar($mail, $options);
$account.
Кажется, это достаточно умно и нужно просто имитировать поведение модуля, считав homepage и hostname комментатора из базы данных и добавив аналогичный код в наш шаблон. Однако проблема в том, что модуль Gravatar integration не читает ничего из БД, а работает с переменными шаблона и, следовательно, хэш зависит от правил их генерации. Так, например, если просматривающий страницу пользователь не имеет права на просмотр IP, hostname в переменных шаблона сгенерирован не будет. А если имеет — будет. То есть разные пользователи будут видеть для одного комментария разные граватарки. Кроме того, в определенных условиях (я так и не смог разобраться, в каких), шаблон считывает граватарку для одного пользователя дважды — сначала по email-у, а потом — по homepage.
Если бы все эти извращения были выделены автором в отдельную функцию генерации хэша (или хотя бы в прозрачное описание порядка действий), жить было бы гораздо проще. А так — у меня получилось сымитировать поведение модуля только частично. Вероятно, нужно поговорить с автором на предмет большей прозрачности генерации хэша для аватарок. Или на предмет интеграции с Views — что даже практичнее. Пока же буду пользоваться описанным решением.
Благо, помимо показа в некоторых случаях разных рандомных картинок в блоке и в соответствующем комменте, все остальное работает нормально.
Я написал длинное письмо, потому что у меня не было времени, чтобы написать короткое. (с)
Там не одна крошечная проблема рассмотрена, а три последовательных. Попробуй описать их в статье - увидишь, сколько текста это потребует. И потом, мне буковок ради хорошего дела не жалко :)
2graker: Просто у тебя аватарка как раз такая, как будто ты стоишь и думаешь "Писать или не писать автору..." :)))
О господи!
оужос!! теперь и у тебя эти монстры на аватарках =)
Бойся!!!
Какие сложности! Тоже люблю автарки, но ничего не поняла. Хорошо хоть Граватар интегрировать удалось, так что теперь у меня появились изображения в комментариях. Буду пока радоваться этому факту. :)
Роман, а если всего этого не делать, то как отображаются аватары у зарегистрированных пользователей? С фотографией?
Ну у вас же отображаются :)
Все это делать нужно только если есть необходимость отображать граватарки вручную.
Я имею в виду в боковой колонке. Сейчас только у меня фото, а у остальных - рисунок. А в комментариях у многих фото. Интересно, когда пользователи зарегистрируются, эта ситуация изменится?
Я имею в виду в боковой колонке. Сейчас только у меня фото, а у остальных - рисунок. А в комментариях у многих фото. Интересно, когда пользователи зарегистрируются, эта ситуация изменится?
Ситуация изменится либо если юзеры зададут фото у себя в профиле, зарегистрировавшись, либо - если будут указывать email и сделают себе граватарку.
У них есть граватарки! Но отображаются они только в комментариях, а в боковой колонке - нет. Я подумала, что, возможно, регистрация у меня на сайте изменит эту ситуацию.
«Боковая колонка» — это блок комментариев, как у меня? Тогда нужно проделать примерно то, что в заметке написано.
Ясно, спасибо. А я поадеялась без этого обойтись...
Там в новых версиях вроде есть какая-то интеграция во Views... Но я не вникал.
Ура, я докопалась до истины! Если пользователь, имеющий граватар, проходит регистрацию на сайте, то его граватар автоматически начинает отображаться как в комментариях, так и в боковой колонке (блоке последних комментариев). Без каких-либо изменений в коде.
Ну вот и отлично.
Здравствуйте!
Спасибо за подробное и понятное описание сервиса!
А у меня такой глюк на сайте приключился: Поменял я логин на Wordpress-блоге, но e-mail оставил прежним, - тот, который на gravatar.com указан. И, странное дело... Все комментарии до смены логина не отображают граватар, а новые - в норме. Хотя, все значения, вплоть до IP, названия сайта, имени, почты - одинаковые.
Подскажите, пожалуйста, как можно настроить, чтобы изображение под старым логином и новым - были одинаковыми?
Заранее благодарю за ответ!
Добрый день.
Понятия не имею, тут же про Друпал, в общем-то, я Вордпрессом не занимаюсь.












сколько много текста из-за казалось бы крошечной проблемы =) предлагаю тебе написать issue автору, благо английским владеешь ;)