Устранение ошибок в модуле Imce CCK Image

Главные вкладки

Аватар пользователя direqtor direqtor 7 августа 2008 в 11:02

Устранение ошибок в модуле Imce CCK Image (imceimage) посредством пользовательской темизации вывода поля.

Модуль Imce CCK Image

В этом модуле на момент написания заметки (лето 2008 года) присутствуют две небольших, но неприятных ошибки.

Первая заключается в том, что даже при отсутствии в поле imceimage изображения тег img все равно отображается в материале с пустым src. В браузерах Opera и Firefox подобные изображения не показываются, но вот счастливые обладатели Internet Explorer видят неприятные артефакты в виде незагруженных картинок – квадратик в красным крестиком. При формате вывода "Ссылка на файл изображения" в коде вообще виден только открывающий тег a без текста и завершающего . При пустом значении еще и с пустым href.
..
Обычно модуль content не выводит заголовок поля, если оно не содержит значения, но в данном случае с его точки зрения вывод есть и поэтому при отсутствии изображения и не спрятанном заголовке в материале выводится заголовок поля с пустым местом.

Вторая ошибка состоит в том, что каждое изображение (тег img) при отображении поля в материале снабжается атрибутом id с одинаковым для всех значением imceimage-имя_поля-. Ошибка не позволяет странице сайта пройти XHTML-валидацию (по стандартам на странице не должно быть одинаковых id), что тоже может служить предметом грусти для веб-мастеров.

Если кто-то уже успел наткнуться на эти неприятные особенности модуля imceimage, то этот пример является рецептом для избавления от нее без правки его кода.

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

Ищем ошибки в коде

Сначала разберемся с кодом самого модуля и найдем функцию темизирующую вывод поля в материал. Для этого откроем файл imceimage.module. Хук imceimage_field_formatter_info() предусматривает два формата вывода поля: default и link. Хук imceimage_theme(), описывающий функции вывода поля выглядит следующим образом (Drupal 6):

function imceimage_theme() {
  return array(
    'imceimage' => array(
       'arguments' => array('element' => NULL),
    ),
    'imceimage_formatter_default' => array(
       'arguments' => array('element' => NULL),
    ),
    'imceimage_formatter_link' => array(
       'arguments' => array('element' => NULL),
    ),
  );
}

Всем функциям передается один аргумент $element (по умолчанию NULL) и, поскольку ссылка на дополнительную функцию (элемент "function") здесь отсутствует, Drupal будет использовать для вывода поля функции, которые будут называються следующим образом:
theme_imceimage() - вывод в форму редактирования
theme_imceimage_formatter_default() - вывод поля в формате изображения.
theme_imceimage_formatter_link() - вывод поля в формате гиперссылки на файл изображения.
Нас интересуют последние две.

Функция theme_imceimage_formatter_link():

function theme_imceimage_formatter_link($element) {
  $item = $element['#item'];
  return '<a href="'. base_path() . $item['imceimage_path'] .'" class="imceimage-link">';
}

По-видимому, функция темизации вызывается даже в случае отсутствия значения в поле ($element=NULL), что и приводит к ошибке – выводится код, который не отображается.

<a href="" class="imceimage-link">

Функция theme_imceimage_formatter_default():

function theme_imceimage_formatter_default($element) {
  $item = $element['#item'];
  $field = $element['#field_name'];
  $delta = $element['#delta'];
  $id = "imceimage-". $field ."-". $delta;
  return theme_imceimage_image(
    $item['imceimage_path'], $item['imceimage_width'],
    $item['imceimage_height'], $item['imceimage_alt'],$id);
}
function theme_imceimage_image($s, $w='', $h='', $a='', $id='') {
  $s = 'src="'. $s .'" ';
  $a = 'alt="'. $a .'" ';
  $id = !empty($id)? 'id="'. $id .'" ':'';
  $w = !empty($w)? 'width="'. $w .'" ':'';
  $h = !empty($h)? 'height="'. $h .'" ':'';

  return '<img '. $s . $a . $w . $h . $id .'/>';
}

Сразу виден источник ошибки. Входной праметр функции $s (путь к файлу изображения) не проверяется на наличие значения и тег img выводится в любом случае.

С атрибутом id ситуация посложнее. Проверка показала, что значение $element['#delta'] при выводе поля в материал неопределено, поэтому каждый тег img снабжается одинаковым id.

Функция theme_imceimage_image() вызывается также и в функции imceimage_process() – в этом случае в $id передается действительно уникальный идентификатор, который используется IMCE для вставки изображения в требуемое место.

Пользовательская темизация

Мы выяснили имена двух функций, которые нам требуется темизировать. Откроем в папке используемой темы файл template.php или создадим его, если отсутствует.

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

/*
  Эта функция будет вызвана для формата "Ссылка на файл изображения" вместо
  theme_imceimage_formatter_link()
*/

function phptemplate_imceimage_formatter_link($element) {
  $item = $element['#item'];
/*
  Проверяем путь к файлу изображения на наличие значения
   При отсутствии возвращаем пустую строку
*/

  if(empty($item['imceimage_path'])) return '';
/*
  Формируем корректную гиперссылку
  Параметр $item['imceimage_path'] начинается со слеша, который приходится удалять
 */

  $a = '<a href="'. base_path() . substr($item['imceimage_path'],1) .'" class="imceimage-link">' . 'Link' . '</a>';
  return $a;
}
/*
  Эта функция будет вызвана для формата "Изображение IMCE" вместо
  theme_imceimage_formatter_default()
*/

function phptemplate_imceimage_formatter_default($element) {
  $item = $element['#item'];
  $field = $element['#field_name'];
/*
  Задаем пустой $id
*/

  $id = "";
/*
  Вызываем пользовательскую функцию для вывода изображения
*/

  return mytheme_imceimage_image(
    $item['imceimage_path'],
    $item['imceimage_width'],
    $item['imceimage_height'],
    $item['imceimage_alt'],
    $id
  );
}
/*
  По правилам название этой функции должно начинаться с имени темы,
  в которой она определяется. Пусть у нас это mytheme
*/

function mytheme_imceimage_image($s, $w='', $h='', $a='', $id='') {
/*
  Проверяем путь к файлу изображения на наличие значения
   При отсутствии возвращаем пустую строку
*/

  if(empty($s)) return '';
  $s = 'src="'. $s .'" ';
  $a = 'alt="'. $a .'" ';
  $id = !empty($id)? 'id="'. $id .'" ':'';
  $w = !empty($w)? 'width="'. $w .'" ':'';
  $h = !empty($h)? 'height="'. $h .'" ':'';

  return '<img '. $s . $a . $w . $h . $id .'/>';
}

Вот и все. Теперь ошибки разработчиков устранены и поле imceimage работает более корректно.
Не забудьте после изменения файла template.php выключить и включить вашу тему. Новые функции темизации станут доступны только в этом случае.

Источники

Статья в блоге автора

Imce CCK Image

IMCE

Content Construction Kit (CCK)

Комментарии

Аватар пользователя neochief neochief 8 августа 2008 в 3:54

Для вставок ссылок нужно использовать функцию l(). Для вставки картинок, нужно использовать theme('image'...), поэтому mytheme_imceimage_image вообще там лишняя.

Кстати, патч не хотите написать для модуля? Smile

Аватар пользователя direqtor direqtor 8 августа 2008 в 4:18

Кстати, проблема с отображением заголовка при пустом значении поля имеется еще у поля e-mail и даже у штатного text в формате отличном от plain text.
Сегодня буду копаться с этими полями.