Field API Practical usage
Presenter Pavel Makhrinsky Senior Drupal developer Berlingske Media
Introducing Field API ● CCK module successor ● The way to store and represent Entities properties ● Utilize Form API mechanism
Some terminology Entities Field Types Field Storage Field Instances Bundles
Some terminology: structure
Field API Field Types API Field Info API Field CRUD API Field Storage API Field API bulk data deletion Field Language API
Practical tips How to use
Implement formatter Create a presentation of term_reference as a comma-delimited items 1. hook_field_formatter_info() 2. hook_field_formatter_view() (option) 3. hook_field_formatter_prepare_view()
Implement formatter: info function smth_field_formatter_info() { return array( 'taxonomy_comma_links' => array( 'label' => t('Comma-links'), 'field types' => array('taxonomy_term_reference'), ), ); }
Implement formatter: view function smth_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display){ $element = array(); switch ($display['type']) { case 'taxonomy_comma_links': { $links = array(); foreach ($items as $delta => $item) { $term = taxonomy_term_load($item['tid']); $uri = entity_uri('taxonomy_term', $term); $links[] = l($term->name, $uri['path']); } $element[] = array( '#markup' => implode(', ', $links), ); break; } } return $element; }
Implement widget: view hook_field_widget_info() hook_field_widget_form() hook_field_is_empty()
Implement widget: info function textf_field_widget_info() { return array( 'textf' => array( 'label' => t('Text field'), 'field types' => array('text'), 'settings' => array('size' => 60), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT, ), ), ); }
Implement widget: form function textf_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { switch ($instance['widget']['type']) { case 'textf': $element['textf'] = array( '#type' => 'textfield', '#title' => $element['#title'], '#description' => $element['#description'], '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#required' => $element['#required'], '#weight' => isset($element['#weight']) ? $element['#weight'] : 0, '#delta' => $delta, ); break; } return $element;
Language API
Language handling: Multilingual types Localized Single language site Multilingual site Site with different content for different languages Multilingual site with translation Site with translated content
Language handling
Language handling Locale module is disabled 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'und'
Language handling Locale and Content translation modules enabled 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'en'
Language handling Locale and Entity translation modules enabled Shared fields 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'en' Translatable fields 1. $entity->body[en][0][value]; 2. $entity->body[de][0][value]; 3. $langcode = entity_language('entity_type', $entity); 4. $langcode == 'en'
Getting field data function field_get_items($entity_type, $entity, $field_name, $langcode = NULL) function field_view_field($entity_type, $entity, $field_name, $display = array(), $langcode = NULL) function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL)
Entity API: metadata 1. // hook_entity_property_info_alter 2. class InviteMetadataController extends EntityDefaultMetadataController { 3. public function entityPropertyInfo() { 4. $info = parent::entityPropertyInfo(); 5. $properties = &$info[$this->type]['properties']; 6. 7. $properties['inviter'] = array( 8. 'label' => t('Inviter'), 9. 'type' => 'user', 10. 'getter callback' => 'entity_property_getter_method', 11. 'setter callback' => 'entity_property_setter_method', 12. 'schema field' => 'uid', 13. 'required' => TRUE, 14. ); 15. 16. $properties['invite_accept_link'] = array( 17. 'label' => t('Invite action link: accept'), 18. 'getter callback' => 'invite_metadata_entity_get_properties', 19. 'type' => 'uri', 20. 'computed' => TRUE, 21. 'entity views field' => TRUE, 22. ); 23. 24. return $info; 25. }
Entity API: metadata 1. $invite = entity_metadata_wrapper('invite', $entity); 2. 3. // Get the value of field_name of the inviter profile. 4. $invite ->inviter->profile->field_name->value(); 5. $invite ->inviter->profile->field_name->set('New name'); 6. 7. // Value of the invite summary in german language. 8. $invite ->language('de')->body->summary->value(); 9. 10. // Check whether we can edit inviter email address. 11. $invite ->inviter->mail->access('edit') ? TRUE : FALSE; 12. 13. // Get roles of inviter. 14. $invite ->inviter->roles->optionsList(); 15. 16. // Set description of the first file in field field_files. 17. $invite ->field_files[0]->description = 'The first file'; 18. $invite ->save(); 19. 20. // Get invite object. 21. $invite = $invite->value();
Update a field without Entity $node = node_load($nid); $node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'value'; node_save($node); $node = node_load($nid); $node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'value'; field_attach_update('node', $node); Note: - be careful with security - be careful with caching
Add AJAX validation to a specific field function smth_link_form_alter(&$form, &$form_state, $form_id) { if ('example_node_form' == $form_id) { $form['field_link'][$language][0]['#process'] =array('link_field_process', '_smth_link_field_link_process'); } } function _smth_link_field_link_process($element, &$form_state, $form) { $element['url']['#description'] = '<div id="example-link"></div>'; $element['url']['#ajax'] = array( 'callback' => 'smth_link_ajax_callback', 'wrapper' => 'example-link', ); return $element; }
Add AJAX validation to a specific field function kf_link_ajax_callback(&$form, $form_state) { $values = $form_state['values']; $field_link = $values['field_link']; $language = $values['language']; $url = $field_link[$language][0]['url']; $duplicate_nodes = _kf_link_get_url_nid($url); foreach ($duplicate_nodes as $duplicate_node) { if (isset($duplicate_node->nid) && ($duplicate_node->nid !=$values['nid'])) { drupal_set_message(t('This URL already exists in <a href="!url">!title</a>', array('! title' => $duplicate_node->title, '!url' =>"node/{$duplicate_node->nid}")), 'error'); } } $commands = array(); $commands[] = ajax_command_html(NULL, theme('status_messages')); return array( '#type' => 'ajax', '#commands' => $commands, ); }
Useful links http://drupal.org/node/443536 http://drupal.org/project/entity http://api.drupal.org/api/drupal/modules%21field%21field. module/group/field/7 http://drupal.org/project/examples http://drupal.org/project/edit http://drupal.org/project/layout
Questions? Pavel Makhrinsky drupal.org: http://drupal.org/user/773216 facebook: https://www.facebook.com/gumanist

Drupal Field API. Practical usage

  • 1.
  • 2.
    Presenter Pavel Makhrinsky Senior Drupaldeveloper Berlingske Media
  • 3.
    Introducing Field API ●CCK module successor ● The way to store and represent Entities properties ● Utilize Form API mechanism
  • 4.
    Some terminology Entities Field Types FieldStorage Field Instances Bundles
  • 5.
  • 6.
    Field API Field TypesAPI Field Info API Field CRUD API Field Storage API Field API bulk data deletion Field Language API
  • 7.
    Practical tips How to use
  • 8.
    Implement formatter Create apresentation of term_reference as a comma-delimited items 1. hook_field_formatter_info() 2. hook_field_formatter_view() (option) 3. hook_field_formatter_prepare_view()
  • 9.
    Implement formatter: info functionsmth_field_formatter_info() { return array( 'taxonomy_comma_links' => array( 'label' => t('Comma-links'), 'field types' => array('taxonomy_term_reference'), ), ); }
  • 10.
    Implement formatter: view functionsmth_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display){ $element = array(); switch ($display['type']) { case 'taxonomy_comma_links': { $links = array(); foreach ($items as $delta => $item) { $term = taxonomy_term_load($item['tid']); $uri = entity_uri('taxonomy_term', $term); $links[] = l($term->name, $uri['path']); } $element[] = array( '#markup' => implode(', ', $links), ); break; } } return $element; }
  • 11.
  • 12.
    Implement widget: info functiontextf_field_widget_info() { return array( 'textf' => array( 'label' => t('Text field'), 'field types' => array('text'), 'settings' => array('size' => 60), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT, ), ), ); }
  • 13.
    Implement widget: form functiontextf_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { switch ($instance['widget']['type']) { case 'textf': $element['textf'] = array( '#type' => 'textfield', '#title' => $element['#title'], '#description' => $element['#description'], '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, '#required' => $element['#required'], '#weight' => isset($element['#weight']) ? $element['#weight'] : 0, '#delta' => $delta, ); break; } return $element;
  • 14.
  • 15.
    Language handling: Multilingual types Localized Singlelanguage site Multilingual site Site with different content for different languages Multilingual site with translation Site with translated content
  • 16.
  • 17.
    Language handling Locale moduleis disabled 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'und'
  • 18.
    Language handling Locale andContent translation modules enabled 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'en'
  • 19.
    Language handling Locale andEntity translation modules enabled Shared fields 1. $entity->body[und][0][value]; 2. $langcode = entity_language('entity_type', $entity); 3. $langcode == 'en' Translatable fields 1. $entity->body[en][0][value]; 2. $entity->body[de][0][value]; 3. $langcode = entity_language('entity_type', $entity); 4. $langcode == 'en'
  • 20.
    Getting field data functionfield_get_items($entity_type, $entity, $field_name, $langcode = NULL) function field_view_field($entity_type, $entity, $field_name, $display = array(), $langcode = NULL) function field_view_value($entity_type, $entity, $field_name, $item, $display = array(), $langcode = NULL)
  • 21.
    Entity API: metadata 1. // hook_entity_property_info_alter 2. class InviteMetadataController extends EntityDefaultMetadataController { 3. public function entityPropertyInfo() { 4. $info = parent::entityPropertyInfo(); 5. $properties = &$info[$this->type]['properties']; 6. 7. $properties['inviter'] = array( 8. 'label' => t('Inviter'), 9. 'type' => 'user', 10. 'getter callback' => 'entity_property_getter_method', 11. 'setter callback' => 'entity_property_setter_method', 12. 'schema field' => 'uid', 13. 'required' => TRUE, 14. ); 15. 16. $properties['invite_accept_link'] = array( 17. 'label' => t('Invite action link: accept'), 18. 'getter callback' => 'invite_metadata_entity_get_properties', 19. 'type' => 'uri', 20. 'computed' => TRUE, 21. 'entity views field' => TRUE, 22. ); 23. 24. return $info; 25. }
  • 22.
    Entity API: metadata 1. $invite = entity_metadata_wrapper('invite', $entity); 2. 3. // Get the value of field_name of the inviter profile. 4. $invite ->inviter->profile->field_name->value(); 5. $invite ->inviter->profile->field_name->set('New name'); 6. 7. // Value of the invite summary in german language. 8. $invite ->language('de')->body->summary->value(); 9. 10. // Check whether we can edit inviter email address. 11. $invite ->inviter->mail->access('edit') ? TRUE : FALSE; 12. 13. // Get roles of inviter. 14. $invite ->inviter->roles->optionsList(); 15. 16. // Set description of the first file in field field_files. 17. $invite ->field_files[0]->description = 'The first file'; 18. $invite ->save(); 19. 20. // Get invite object. 21. $invite = $invite->value();
  • 23.
    Update a fieldwithout Entity $node = node_load($nid); $node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'value'; node_save($node); $node = node_load($nid); $node->field_fieldname[LANGUAGE_NONE][0]['value'] = 'value'; field_attach_update('node', $node); Note: - be careful with security - be careful with caching
  • 24.
    Add AJAX validationto a specific field function smth_link_form_alter(&$form, &$form_state, $form_id) { if ('example_node_form' == $form_id) { $form['field_link'][$language][0]['#process'] =array('link_field_process', '_smth_link_field_link_process'); } } function _smth_link_field_link_process($element, &$form_state, $form) { $element['url']['#description'] = '<div id="example-link"></div>'; $element['url']['#ajax'] = array( 'callback' => 'smth_link_ajax_callback', 'wrapper' => 'example-link', ); return $element; }
  • 25.
    Add AJAX validationto a specific field function kf_link_ajax_callback(&$form, $form_state) { $values = $form_state['values']; $field_link = $values['field_link']; $language = $values['language']; $url = $field_link[$language][0]['url']; $duplicate_nodes = _kf_link_get_url_nid($url); foreach ($duplicate_nodes as $duplicate_node) { if (isset($duplicate_node->nid) && ($duplicate_node->nid !=$values['nid'])) { drupal_set_message(t('This URL already exists in <a href="!url">!title</a>', array('! title' => $duplicate_node->title, '!url' =>"node/{$duplicate_node->nid}")), 'error'); } } $commands = array(); $commands[] = ajax_command_html(NULL, theme('status_messages')); return array( '#type' => 'ajax', '#commands' => $commands, ); }
  • 26.
  • 27.