Plugins de acciones para bulk operations

31/03/2022
Plugins de acciones para bulk operations

En este artículo vamos a describir cómo realizar un plugin de acción masiva en Drupal 8/9. ¿Qué entendemos por operación masiva? Pues aquella operación o evento que actúa sobre un determinado número de nodos o entidades de contenido para realizar una acción concreta, es decir que si nos interesa modificar 400 nodos lo podemos hacer de golpe y no teniendo que editar uno por uno cada nodo en su respectivo formulario de edición. Seguramente os habéis topado con ellas en la vista de admin/content, son estas:

Plugins de acciones para bulk operations - Imagen 1

‘Eliminar contenido’ es una operación masiva que eliminará del portal Drupal todos los nodos que se marquen el checkbox. Pero, ¿qué pasa si tenemos una serie de entidades con particularidades propias y nos interesa modificar valores de la misma que no están definidas en estas acciones por defecto que provee Drupal?

Para ese caso debemos definir nuestros propios plugins de acción.

Supongamos que tenemos un tipo de contenido que tiene un campo ‘Estado’, y nos interesa modificar ese campo desde un listado numeroso de nodos, de forma que podamos actualizar ese valor de una sola vez en numerosos nodos.

Definición de un Plugin Action:

Para generar este tipo de plugin, nos hará falta definirlo en:

  • Config schema
  • Config install
  • La propia clase del plugin

Definicion del plugin en config/install:

Debemos generar el archivo ‘system.action.test_action.yml’ en la carpeta ‘config/install' de nuestro módulo custom, por supuesto, donde la línea id: test_action es el nombre del id del plugin nuevo que vamos a crear.

langcode: es
status: true
dependencies:
 module:
   - node
id: test_action
label: 'Aprobar estado'
type: node
plugin: test_action
configuration: {  }

Mucho cuidado al generar este archivo, ya que suele generar confusión su nombre. No debe usar el nombre del módulo custom al comienzo, sino que debe ser como mencionamos antes: system.action.[nombre_modulo].

En el campo Id colocamos el mismo id que vamos a usar posteriormente en el fichero schema y en la definición de la clase.

Para este ejemplo el parámetro ‘type’ es ‘node’, pero para usuarios o taxonomías este valor cambia, por ejemplo un plugin action para cambiar masivamente usuarios sería type: ‘user’.

El label de este campo es lo que se nos mostrará cuando visitemos /admin/content y pinchemos sobre el select de ‘Acción’.

Definicion del plugin en config/schema:

Ahora debemos definir un nuevo fichero .yml en la ubicación ‘config/schema’ de nuestro módulo custom, tal que así:

action.configuration.test_action:
 type: test_action
 label: 'Aprueba el nodo de forma masiva'

El nombre de este fichero en nuestro ejemplo es test_action.schema.yml. Y en type hemos usado el mismo Id que figura en el fichero ‘system.action.test_action.yml’.

Con esto ya tenemos creado los ficheros relativos para que Drupal registre el nuevo plugin de acción. Ahora vamos a por la clase donde se definen a partir de sus métodos qué vamos a hacer con esos nodos, o mejor dicho cómo vamos a operar con ellos.

Definición de la clase Plugin Action:

Dentro de nuestro módulo custom vamos a definir en la carpeta /src/Plugin/Action el nuevo plugin que extenderá de la clase ActionBase, le nombramos por ejemplo ActionTest.php

Añadimos namespace, importamos las clases e interfaces que necesitemos , y añadimos en el Annotation el id que registramos anteriormente:

  • Id: test_action
  • Label: Una descripción de nuestro plugin.
  • Type: la entidad sobre la que actúa, en nuestro caso node.

La clase ActionBase nos viene con dos métodos:

  • access: Que nos permitirá controlar el acceso del usuario en cuestión para poder rechazar o permitir la acción que se desea realizar.
  • execute: Método donde podemos ya definir la acción que queremos realizar sobre cada nodo seleccionado, en nuestro caso comprobamos que tiene definido el campo field_status y le cambiamos su valor.
<?php

namespace Drupal\test_action\Plugin\Action;

/**
 * Action description.
 *
 * @Action(
 *   id = "test_action",
 *   label = @Translation("Test action"),
 *   type = "node"
 * )
 */
class ActionTest extends ActionBase {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function execute($entity = NULL) {

    if ($entity->hasField('field_estado')) {
      $entity->set('field_estado', '1');
      $entity->save();
    }

  /**
   * {@inheritdoc}
   */
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    if ($object->getEntityType()->id() === 'node' && $account->hasPermission('access_test')) {
      $access = $object->access('update', $account, TRUE)
        ->andIf($object->status->access('edit', $account, TRUE));
      return $return_as_object ? $access : $access->isAllowed();
    }
    return TRUE;
  }

}

 

Todo esto se mostrará así en la vista /admin/content:

Plugins de acciones para bulk operations - Imagen 2

Y como resultado de ejecutar la operación:

Plugins de acciones para bulk operations - Imagen 3

También lo podemos usar en una vista, agregando el campo ‘formulario de operaciones masivas:

Plugins de acciones para bulk operations - Imagen 4

Esto lo podemos agregar como campo en cualquier vista que tengamos sobre nodos y poder ejecutar igualmente acciones masivas sobre ellos.