Drupal7 tip: Verander een veld widget

Posted by: 
Dominique De Cooman

We wilden een functie aan onze bestand widget toevoegen zodat het kan registreren wanneer het een bestand kan uitsluiten van de zoekresultaten. Bestanden worden geïndexeerd en doorzocht door middel van apachesolr en tika. Ons idee was om een selectievakje aan de bestand widget toe te voegen en zijn waardes op te slaan. Een hook apachesolr update index weet dan of een bestand in de index geplaatst kan worden of niet. We bewaren de uitgesloten bestanden als een veld in de file_managed tabel.

Het maken van de tabel:

<?php
/**
 * Add exclude from search  field
 */
function glue_update_7006() {
  
db_add_field('file_managed''exclude', array('type' => 'int''not null' => TRUE'description' => 'Exclude.'));
}
?>

Hoe kunt u de widget veranderen
Het op een normale wijze veranderen van een veld widget werkt niet, daar de render array nog niet volledig is aangemaakt. Wat we moeten doen is gebruik maken van de #afterbuild functies die door de render api geleverd worden. In deze fase is alle informatie die nodig is om de widgets vorm te veranderen aanwezig. Hier volgt hoe u dit doet:

<?php
/**
 * Implements hook_form_alter
 */
function glue_form_measure_node_form_alter(&$form, &$form_state$form_id) {
  
//Get lang
  
if (is_numeric(arg(1))) {
    
//Put in form state so the add another will able to use it since then the path is not node/[id]/edit but /system/ajax
    
$form_state['glue_measure_nid'] = arg(1);
  }
  
//Node is already in static cache so we can load it
  
$node node_load($form_state['glue_measure_nid']);   
    
  
//Add exclude search checkbox
  
$field_attachments_lang field_language('node'$node'field_attachments');  
  
$form_state['field_attachments_lang'] = $field_attachments_lang;
  
$form['field_attachments'][$field_attachments_lang]['#after_build'][] = 'glue_afterbuild_search_exclude';
  
$form['#submit'][] = 'glue_afterbuild_search_exclude_submit'
}
?>

Met een hook form alter voegen we een aangepaste afterbuild functie en een submit functie toe. Houd er rekening mee dat we de talen van het veld opslaan in de form state daar we deze in de afterbuild functie nodig hebben.

<?php
/**
 * Afterbuild function for exclude files from search
 */
function glue_afterbuild_search_exclude($element, &$form_state) {
  foreach (
$element as $key => $item) {
    if (
is_numeric($key) && $item['#value']['fid']) {
      
$element[$key]['display_search']['#type'] = 'checkbox';
      
$element[$key]['display_search']['#checked'] = false;
      
$element[$key]['display_search']['#title'] = t('Exclude in search results');

      
$result db_select('file_managed''f')
          ->
fields('f')
          ->
condition('fid'$element[$key]['#value']['fid'], '=')
          ->
execute();
      
$file $result->fetch();

      if (
$file->exclude == 1) {
        
$element[$key]['display_search']['#value'] = 0;
        
$element[$key]['display_search']['#checked'] = true;
      }
      
      
$element[$key]['display_search']['#attributes']['class'][0] = 'field-attach-exclude-search';
      
$element[$key]['display_search']['#id'] = $element[$key]['display']['#id'] . '-exlude-search';

      
$element[$key]['display_search']['#name'] = 'field_attachments[' $element[$key]['#language'] . '][' $key '][display-exclude-search]';
    }
  }

  return 
$element;
}
?>

In de afterbuild functie kunnen we op een effectieve manier de render array veranderen door ons selectievakje toe te voegen.

Tenslotte slaan we onze waardes op in de submit functie.

<?php
/**
 * Form submit for exclude files from search
 */
function glue_afterbuild_search_exclude_submit($form$form_state) {
  foreach (
$form_state['values']['field_attachments'][$form_state['field_attachments_lang']] as $key => $item) {    
    
$file file_load($item['fid']);
    if (
$file) {
      if (isset(
$item['display-exclude-search']) && $item['display-exclude-search'] == 1) {
        
$value 1;
      }
      else {
        
$value 0;
      }
      
db_update('file_managed')
          ->
fields(array('exclude' => $value,))
          ->
condition('fid'$file->fid'=')
          ->
execute();
    }
  }
}
?>

Het resultaat:

Reactie toevoegen