Cargar dinámicamente los valores permitidos de un campo lista de cadenas en Drupal

drupal2020.jpg
Solucionex
06
Ene 22

Al diseñar nuestros tipos de contenido, uno de los campos a tener en cuenta para la selección única o múltiple de valores dinámicos no relacionados con ninguna entidad es la lista de cadenas, o List (String).

Por defecto, este campo está definido para que declares los valores permitidos en un área de texto añadiendo pares "clave"|"valor". Pero ¿Y si queremos trabajar con una lista dinámica de valores permitidos? Ya sean datos del propio Drupal o datos que nos traemos de otro sistema vía consulta a una API.

Para resolver esto haremos uso de la función callback_allowed_values_function que nos proporciona Drupal.

Vamos a ver un ejemplo en el que para un tipo de contenido Post tenemos un campo Tags en el que los elementos los cargamos mediante una petición GET a una API.

Nos creamos un módulo para la ocasión, por ejemplo el módulo blog_fixes. En el archivo blog_fixes.module tenemos que hacer uso del hook_form_alter para habilitar la propiedad allowed_values_function en nuestro campo, como podéis ver en el siguiente fragmento de código:

function blog_fixes_form_alter(&$form, &$form_state, $form_id){

  if($form_id == 'node_post_form' || $form_id == 'node_post_edit_form'){
    $field = FieldStorageConfig::loadByName('node','field_post_tags');
    $field->setSetting('allowed_values_function', 'blog_fixes_allowed_values_function');
    $field->save();
  }

}

Una vez tenemos "activada" la opción de carga de valores mediante una función, tenemos que definirla y cargar los valores:

function blog_fixes_allowed_values_function(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable){
  if($definition->get('id') == 'node.field_post_tags'){
    try {
      $client = \Drupal::service('http_client');
      $tags = $client->get('https://sistema.biz/api/v1/tags')->result;
      $options = [];
      foreach($tags for $key->$value){
           $options[$key]=$value;
      } 
      return $options;
    } catch (\Throwable $th) {
      \Drupal::logger('blog_fixes')->error($th->getMessage());
    }
  }
}

Con esto ya tendremos nuestro selector de Tags proporcionadas por un sistema externo a Drupal.