Cómo Añadir Filtros Contextuales Personalizados para Views en Drupal

code-g8b60e92d4_1280

Crear vistas en Drupal ofrece una amplia gama de opciones para personalizar la presentación de contenido. A veces, es posible que necesites añadir filtros contextuales personalizados para lograr una funcionalidad específica. Aquí te mostraremos cómo puedes hacerlo.

Supongamos que queremos filtrar una vista de forma directa por un campo del usuario, por ejemplo el departamento. Lo primero que debemos hacer es crear una clase que extienda ArgumentPluginBase. La ubicación debe ser, dentro de tu módulo, en la ruta "/src/Plugin/views/argument". En este caso, este sería un ejemplo de la clase que podríamos tener: 

<?php

namespace Drupal\my_module\Plugin\views\argument;

use Drupal\Core\Session\AccountProxy;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Argument handler for Filtering the node by User Department.
*
* @ingroup views_argument_handlers
*
* @ViewsArgument("contextual_filter_department")
*/
class NodeFilterDepartment extends ArgumentPluginBase {

 	/**
  	* The current user data object.
  	*
  	* @var \Drupal\Core\Session\AccountProxy
  	*/
 	protected $currentUser;

 	/**
  	* The current database connection.
  	*
  	* @var \Drupal\Core\Database\Connection
  	*/
 	protected $database;

 	/**
  	* The entity type manager.
  	*
  	* @var \Drupal\Core\Entity\EntityTypeManagerInterface
  	*/
 	protected $entityTypeManager;

 	/**
  	* The logger factory.
  	*
  	* @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
  	*/
 	protected $loggerFactory;
 	
 	public function __construct(
   	  array $configuration,
   	  $plugin_id,
   	  $plugin_definition,
   	  AccountProxy $current_user,
   	  Connection $database,
   	  EntityTypeManagerInterface $entity_type_manager,
   	  LoggerChannelFactoryInterface $logger_factory
 	) {
   	  parent::__construct($configuration, $plugin_id, $plugin_definition);
   	  $this->currentUser = $current_user;
   	  $this->database = $database;
   	  $this->entityTypeManager = $entity_type_manager;
   	  $this->loggerFactory = $logger_factory;
 	}

 	public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
   	  return new static(
     	$configuration,
     	$plugin_id,
     	$plugin_definition,
     	$container->get('current_user'),
     	$container->get('database'),
     	$container->get('entity_type.manager'),
     	$container->get('logger.factory')
   	  );
 	}

 	public function query($group_by = FALSE) {
   	  $current_user_id = $this->currentUser->id();
   
   	  $tids_department_user = $this->getDepartmentIdForUser($current_user_id);
   	
   	  // Query to filter results.
   	  $nid_filter_query = $this->database->select('node', 'node');
   	  $nid_filter_query->leftJoin('node__department', 'node__department', 'node.nid = node__department.entity_id');
   	  $nid_filter_query->fields('node', ['nid']);
   	  $nid_filter_query->condition('node__department.department_target_id', $tids_department_user, 'IN');
   	  $result = $nid_filter_query->execute()->fetchAllAssoc('nid');
   	  $nid_filter_ids = array_keys($result);
   	  if (!empty($nid_filter_ids)) {
     	$this->query->addWhere(0, 'node_field_data.nid', $nid_filter_ids, 'IN');
   	  }
 	}

	/**
 	* Example method to retrieve the department IDs for a user.
 	*
 	* This method assumes that the department is stored as a field on the user
 	* entity (e.g., field_department). The method takes the user ID and returns
 	* an array of department IDs related to that user.
 	*
 	* @param int $user_id
 	*   The user ID for whom the department IDs should be retrieved.
 	*
 	* @return array
 	*   An array of department IDs related to the given user.
 	*/
	private function getDepartmentIdsForUser($user_id) {
  	  $department_ids = [];
	
  	  $user = $this->entityTypeManager->getStorage('user')->load($user_id);
  	  if ($user) {
    	$departments = $user->get('field_department')->getValue();
	
    	foreach ($departments as $department) {
      	  $department_ids[] = $department['target_id'];
        }
  	  }
	
  	  return $department_ids;
	}
}
 
Como puede verse en el ejemplo, dentro de la clase, necesitas implementar la lógica que determina cómo se aplica el filtro. Esto se hace en el método query. Puedes modificarla según tus necesidades para realizar un filtro o consulta diferente.

Después en el archivo .module de nuestro módulo, registraremos este filtro con el uso del siguiente código: 

/**
* Implements hook_views_data_alter().
*/
function my_module_views_data_alter(&$data) {
 $data['node']['contextual_filter_department'] = [
   'argument' => [
     'title' => t('Filter the results by User Department.'),
     'id' => 'contextual_filter_department',
   ],
 ];
}
 
Una vez hecho esto, ya podremos utilizar el filtro contextual en nuestras views. 
Comparte este artículo:
Publicado por CésarMSFelipe
Image

Hola a todos, soy desarrollador de Drupal, especializado en Backend, aunque a veces hago mis pinitos con Frontend, ¡Hasta sé centrar un div! Cuando no estoy sumergido en el código, probablemente me encontraréis explorando nuevos mundos en mis videojuegos favoritos o disfrutando de tiempo de calidad con los míos. Me apasiona combinar la tecnología con la creatividad, y siempre estoy buscando nuevas formas de aprender y crecer en mi campo. ¿Unimos fuerzas y creamos algo?
 

Si te gusta mi trabajo y quieres echar una mano:
Buy me a coffe!