Drupal7: Field Node Entity Beispiel (Example / Kickstarter) Module

So, 29.04.2012 - 16:21 -- admin

Da ich doch immer wieder mal "auf die schnelle" ein neues Feld an Drupal Node anhängen möchte hier mal eine einfach Lösung mit allen Hooks. Alle üblichen Beispiel, die ich so gefunden habe, nutzen meist nur ein Feld, dieses Module zeigt beispielhaft wie es auch mit zwei Feldern geht. Die Namen der Funktionen, Themes, Array-Keys habe ich nun sinnvoller bekannt, so dass man besser durchblicken kann.

Das komplette Module hängt dem Betrag an. Es implementiert lediglich wie erwähnt zwei neue Feldtypen als einfache Inputfelder und gibt diese dann im Node-View aus. Mehr gibt es auch noch hier: Field API - Eigene Felder in Drupal 7 erstellen

Hook Übersicht

Hier nochmal alle genutzen Hooks im Überblick.

  • hook_field_info
  • hook_field_formatter_info
  • hook_field_widget_info
  • hook_element_info
  • hook_field_widget_form
  • hook_field_formatter_view
  • hook_is_empty

snip.module

/**
 * Implements hook_field_schema().
 */
function snip_field_schema($field) {
 
 $columns = array();
 
 if ($field['type'] == 'cssfield') {
  $columns = array(
    'columns' => array(
      'css' => array(
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
      ),
    ),
  );
 }
 
 if ($field['type'] == 'htmlfield') {
  $columns = array(
    'columns' => array(
      'html' => array(
        'type' => 'text',
        'size' => 'big',
        'not null' => FALSE,
      ),
    ),
  );
 }
 
 return $columns;
}

snip.module

/**
 * Implements hook_theme().
 */
function snip_theme() {
 return array(
   'snip_formatter_snip_formatter_css' => array(
     'render element' => 'element',
   ),
   'snip_formatter_snip_formatter_html' => array(
     'render element' => 'element',
   ),
 );
}
 
/**
 * Implementation of hook_field_info().
 * 
 * Our main field, same key as in "module".install file
 */
function snip_field_info() {
 return array(
   'cssfield' => array(
     'label' => t('CSS Field'),
     'description' => t('Snipper'),
     'default_widget' => 'snip_widget_css',
     'default_formatter' => 'snip_formatter_css',
   ),
   'htmlfield' => array(
     'label' => t('HTML Field'),
     'description' => t('snip'),
     'default_widget' => 'snip_widget_html',
     'default_formatter' => 'snip_formatter_html',
   ),
 );
}
 
/**
 * Implements hook_field_formatter_info().
 * 
 * The main output handler. Map each formatter to a field
 * Rendering will run on hook_field_formatter_view()
 */
function snip_field_formatter_info() {
 return array(
   'snip_formatter_css' => array(
     'label' => 'Formatter: cssfield',
     'description' => 'Formatter: cssfield',
     'field types' => array('cssfield'),
   ),
   'snip_formatter_html' => array(
     'label' => 'Formatter: htmlfield',
     'description' => 'Formatter: htmlfield',
     'field types' => array('htmlfield'),
   ),
 );
}
 
/**
 * Implementation of hook_field_widget_info().
 * 
 * Main input / form for fields. We can provide diffrent forms here
 * Rendering will ron on hook_field_widget_form()
 */
function snip_field_widget_info() {
 return array(
   'snip_widget_css' => array(
     'label' => 'Widget: CSS',
     'field types' => array('cssfield'),
     #'multiple values' => FIELD_BEHAVIOR_DEFAULT,
   ),
   'snip_widget_html' => array(
     'label' => 'Widget: HTML',
     'field types' => array('htmlfield'),
     #'multiple values' => FIELD_BEHAVIOR_DEFAULT,
   ),
 );
}
 
 
/**
 * Implementation of hook_element_info().
 * 
 * You only need this hook if you need to filter widget types on hook_field_widget_form().
 * Use  #type as your array key and map a #process function to it
 * 
 */
function snip_element_info() {
 return array(
   'snip_widget_css' => array(
     '#input' => TRUE,
     '#process' => array('snip_cssfield_field_widget_form'),
   ),
   'snip_widget_html' => array(
     '#input' => TRUE,
     '#process' => array('snip_htmlfield_field_widget_form'),
   ),
 );
}
 
/**
 * Implements hook_field_widget_form().
 * 
 * You can also add field form directly here.
 * 
 * $element['css'] = array(
 *   '#type' => 'textfield',
 *   [...]
 * );
 * 
 * But if your module provides more than one widget for fields better use a hook_elements_info() wrapper named by #type
 * 
 * 
 */
function snip_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
 
 $element += array(
   '#type' => $instance['widget']['type'],
   '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
 );
 
  /* or without hook_elements_info()
   $element['css'] = array(
   '#type' => 'textfield',
   '#title' => t('css'),
   '#default_value' => isset($defaults['css']) ? $defaults['css'] : '',
   '#required' => $element['#required'],
   '#description' => t($field['description']),
   );
  */
 
 return $element;
}
 
/**
 * Implements hook_field_formatter_view().
 * 
 * Output all different output formatter on a theme function;
 * You can also use it without theme(); #markup is your friend
 * 
 */
function snip_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
 $elements = array();
 
 foreach ($items as $delta => $item) {
  $elements[$delta] = array(
    '#markup' => theme('snip_formatter_' . $display['type'], array('element' => $item, 'field' => $instance, 'entity' => $entity)),
  );
 }
 
 return $elements;
}
 
/**
 * Implemented on snip_element_info()
 * 
 * Our form additional form elements on node forms
 */
function snip_htmlfield_field_widget_form($element, $form_state, $complete_form) {
 
 $defaults = $element['#value'];
 $field = field_widget_instance($element, $form_state);
 
 $element['html'] = array(
   '#type' => 'textfield',
   '#title' => t('html'),
   '#default_value' => isset($defaults['html']) ? $defaults['html'] : '',
   '#required' => $element['#required'],
   '#description' => t($field['description']),
 );
 
 return $element;
}
 
/**
 * Implemented on snip_element_info()
 * 
 * Our form additional form elements on node forms
 */
function snip_cssfield_field_widget_form($element, $form_state, $complete_form) {
 
 $defaults = $element['#value'];
 $field = field_widget_instance($element, $form_state);
 
 $element['css'] = array(
   '#type' => 'textfield',
   '#title' => t('css'),
   '#default_value' => isset($defaults['css']) ? $defaults['css'] : '',
   '#required' => $element['#required'],
   '#description' => t($field['description']),
 );
 
 return $element;
}
 
 
/**
 * Implementation of hook_is_empty().
 * 
 * Give Drupal a chance to check if field is empty.
 * Hook is perform e.g. on node save form (not on rendering / viewing)
 * 
 */
function snip_field_is_empty($item, $field) {
 
 if ($field['type'] == 'cssfield') {
  return empty($item['css']);
 }
 
 if ($field['type'] == 'htmlfield') {
  return empty($item['html']);
 }
 
 return false;
}
 
/**
 * Define function in hook_theme() and call on hook_field_formatter_view()
 */
function theme_snip_formatter_snip_formatter_css($variables) {
 // notice: if you need the node object use $variables['entity']
 return $variables['element']['css'];
}
 
/**
 * Define function in hook_theme() and call on hook_field_formatter_view()
 */
function theme_snip_formatter_snip_formatter_html($variables) {
 return $variables['element']['html'];
}