CCK formatters - 2

Normál esetben egy CCK mező sminkelése úgy történik, hogy a formatter lesminkel egy-egy mezőértéket, és a content-field.tpl.php pedig arról gondoskodik, hogy ezek az értékek hogyan legyenek elhelyezve egymáshoz képest. De ha egy filefield mező értéket szeretnénk több oszlopos táblázatban megjeleníteni (ikon, fájlnév, fájlméret, leírás, stb...), akkor érdemesebb egy saját formázót készíteni, mint a template fájlban bűvészkedni. De kezdésnek egy egyszerűbb példát mutatok.

A teszt rendszerhez kell egy tartalom típus (story) ami rendelkezik egy text típusú, egysoros, korlátlan CCK mezővel.

Azért, hogy mégse legyen olyan egyszerű a helyzet, és a Drupal smink rendszeréből is többet megismerjünk, nem egy, hanem két formázót is megvalósítok a modulban. Az egyik belefoglalja a CCK mező nevét a táblázatba, a másik pedig nem.

A formázók adatainak megadása:

A trükk abban van, hogy a 'multiple values' nem a szokásos CONTENT_HANDLE_CORE étéket kapja. A CONTENT_HANDLE_MODULE biztosítja azt, hogy a formázó smink függvény nem egyesével kapja meg a mező értékeket, hanem egyszere, ami az alapja annak, hogy az értékek kulturált módon legyenek betolva egy táblázatba.

/**
 * Implementation of hook_field_formatter_info().
 */
function myftr2_field_formatter_info() {
  return array(
    'text_table_cap_no' => array(
      'label'           => t('Table (without caption)'),
      'field types'     => array('text'),
      'multiple values' => CONTENT_HANDLE_MODULE,
    ),
 
    'text_table_cap_yes' => array(
      'label'           => t('Table (with caption)'),
      'field types'     => array('text'),
      'multiple values' => CONTENT_HANDLE_MODULE,
    ),
  );
}

Minden formázóhoz kell egy külön theme bejegyzés

Az 'arguments' rész egy kis magyarázatra szorul, és ez összefügg azzal, hogy mindkét formázó ugyanazt a smink függvényt használja. A két sminkelés csak egy apró dologban különbözik, ezért nem akartam két hasonló függvény írni. Inkább argumentumban kapja a függvény, hogy meg kell-e jeleníteni a mező nevét vagy sem. Ezzel lesznek még gondok.

/**
 * Implementation of hook_theme().
 */
function myftr2_theme() {
  $tpl = 'myftr2.formatter.text_table';
  $fnc = 'theme_myftr2_formatter_text_table';
  return array(
    'myftr2_formatter_text_table_cap_no' => array(
      'arguments' => array('element' => NULL, 'params' => array('caption' => FALSE)),
      'function' => 'theme_myftr2_formatter_text_table',
      //'template'   => $tpl,
    ),
 
    'myftr2_formatter_text_table_cap_yes' => array(
      'arguments' => array('element' => NULL, 'params' => array('caption' => TRUE)),
      'function' => 'theme_myftr2_formatter_text_table',
      //'template'   => $tpl,
    ),
  );
}

A smink függvény

A hook_theme leírásában az arguments résznél ez olvasható:

The array keys represent the name of the variable, and the value will be used as the default value if not specified to the theme() function.

Épp csak azt felejtették el oda írni, hogy ez csak template fájlokkal működik, függvényekkel nem. Jelen függvény első két sora ezt hívatott orvosolni.

/**
 * @ingroup themeable
 */
function theme_myftr2_formatter_text_table($element) {
  $hooks = myftr2_theme();
  $params = $hooks[$element['#theme']]['arguments']['params'];
 
  $field = content_fields($element['#field_name'], $element['#type_name']);
  $allowed_values = content_allowed_values($field);
 
  $rows = array();
  $delta = 0;
  foreach (element_children($element) as $delta) {
    $rows[$delta] = array(
      'class' => 'field-item',
      'data'  => array(($allowed_values) ? $allowed_values[$element[$delta]['#item']['value']] : $element[$delta]['#item']['safe']),
    );
  }
 
  if (!$rows) {
    return FALSE;
  }
 
  $rows[0]['class'] .= ' first';
  $rows[$delta]['class'] .= ' last';
 
  return theme('table',
    array(), //header
    $rows,
    array('class' => 'field-items'), //attributes
    ($params['caption']) ? $field['widget']['label'] : NULL //caption
  );
}

Template fájl

A myftr2_theme() megfelelő modosítása után az alábbi template fájl is használható. Itt mindenféle trükközés nélkül elérhető a $params változó.

<?php
// $Id$
 
/**
 * @file
 * ugyan az tpl fájlban
 */
 
$field = content_fields($element['#field_name'], $element['#type_name']);
$allowed_values = content_allowed_values($field);
 
$rows = array();
$delta = 0;
foreach (element_children($element) as $delta) {
  $rows[$delta] = array(
    'class' => 'field-item',
    'data'  => array(($allowed_values) ? $allowed_values[$element[$delta]['#item']['value']] : $element[$delta]['#item']['safe']),
  );
}
 
if (!$rows) {
  return;
}
 
$rows[0]['class'] .= ' first';
$rows[$delta]['class'] .= ' last';
 
echo theme('table',
  array(), //header
  $rows,
  array('class' => 'field-items'), //attributes
  ($params['caption']) ? $field['widget']['label'] : NULL //caption
);

Harmónia

CONTENT_HANDEL_MODULE típusú formázók esetén a content-field.tpl.php egy kis korrekcióra szorul, ugyanis csak a $items[0] tartalmaz 'view' értéket, és elég bénán néz ki az alábbi HTML kimenet

<div class="field-items"><div class="field-item"><table class="field-items">
A formázó azonosítója kiolvasható a $element['items']['#theme'] változóból.

A modul sminkelésének felülbírálás a sminkből

A sima kopipészt nem elég, a sminkben is meg kell valósítani a hook_theme() függvényt.

function mytheme_theme($existing, $type, $theme, $path) {
  $items = array();
  $items['myftr2_formatter_text_table_cap_yes'] = $existing['myftr2_formatter_text_table_cap_yes'];
  $items['myftr2_formatter_text_table_cap_no'] = $existing['myftr2_formatter_text_table_cap_no'];
 
  $items['myftr2_formatter_text_table_cap_yes']['function']
    = $items['myftr2_formatter_text_table_cap_no']['function']
    = 'phptemplate_myftr2_formatter_text_table'
  ;
  return $items;
}

Csatolmányok: