Hero

Filtros contextuales en vistas con operador OR en Drupal 7

Enero 21, 2013

kenneth
Drupal
Vistas

Cuando usamos el modulo “View” en Drupal 7, tenemos varios tipos de filtros para poder obtener la información que necesitamos, además existe un grupo de filtros que se puede crear en virtud del contexto de la aplicación.

Los filtros contextuales trabajan en conjunto con los filtros regulares y los filtros expuestos para la generación de la consulta SQL .

Los filtros de contexto tienen como operador predeterminado el “AND”, obviamente esto representa un restricción, ya que en ciertas ocasiones es necesario utilizar el operador “OR”.

Lo ideal seria que en los filtros contextuales pudiéramos hacer un agrupamiento y sobre este agrupamiento definir un operador especifico “AND” u “OR”, como se permite en los filtros regulares.

Imaginemos una vista con tres filtros contextuales, como los siguientes filtros que se muetran en la imagen,

Drupal Contextual

En el Query #1 podemos observar el codigo SQL que generaria esta vista,

<pre title="Query #1">SELECT node.title AS node_title, node.nid AS nid, node.language AS node_language, 
 node.created AS node_created, 'node' AS field_data_field_administrador_node_entity_type, 'node' 
 AS field_data_field_propietario_node_entity_type, 'node' AS field_data_field_tecnico_node_entity_type, 
 'node' AS field_data_field_vencimiento_node_entity_type, 'dominios_de_usuario:block' AS view_name
FROM 
{node} node
LEFT JOIN {field_data_field_administrador} field_data_field_administrador ON node.nid = 
 field_data_field_administrador.entity_id AND (field_data_field_administrador.entity_type = 'node' 
 AND field_data_field_administrador.deleted = '0')
LEFT JOIN {field_data_field_propietario} field_data_field_propietario ON node.nid = field_data_field_propietario.entity_id 
 AND (field_data_field_propietario.entity_type = 'node' AND field_data_field_propietario.deleted = '0')
LEFT JOIN {field_data_field_tecnico} field_data_field_tecnico ON node.nid = field_data_field_tecnico.entity_id AND 
 (field_data_field_tecnico.entity_type = 'node' AND field_data_field_tecnico.deleted = '0')
WHERE 
(( 
 (field_data_field_administrador.field_administrador_target_id = '1' )
 AND 
 (field_data_field_propietario.field_propietario_target_id = '1' ) 
 AND 
 (field_data_field_tecnico.field_tecnico_target_id = '1' ) )
 AND
 (( (node.status = '1') 
 AND 
 (node.type IN  ('dominio')) )))
ORDER BY node_created DESC
LIMIT 5 OFFSET 0

Para hacer el cambio del operador mediante código fuente implementando los siguientes hooks en un módulo personalizado:

hook_views_query_alter();
hook_views_api();

En el Listado de código #1 pueden observar un ejemplo de cómo implementar el hook_views_query_alter:

<pre title="Listado de código #1">function modulo_personalizado_views_query_alter(&$view, &$query) {
 // Usamos el objeto "$view" que ha entrado por referencia,
 // para poder verificar que estamos cambiando la vista,
 // que deseamos alterar.
 if ($view->name == 'nombre_de_mi_vista') {
 // Los filtros contextuales se encuentran en where[0],
 // entonces cambiamos el "type" de condición de este
 // grupo por 'OR'.
 $query->where[0]['type'] = "OR";
 // De igual forma podriamos usar un "watchdog",
 // para observar el contenido de "$query->where",
 // y estar seguro de cual grupo de condiciones modificaremos.
 }
}

Debemos asegurarnon de usar el API de vistas “3.0” y para ello haremos la implementación del hook_views_api como se puede apreciar en el Listado de código #2:

<pre title="Listado de código #2">function modulo_personalizado_views_api() {
 return array("version" => "3.0");
}

Una vez aplicador el código fuente anterior en nuestro modulo personalizado,veremos como se modifica la condición en la sección de Query de nuestra vista como se puede apreciar en el Query #2,

<pre title="Query #2">SELECT node.title AS node_title, node.nid AS nid, node.language AS node_language, 
 node.created AS node_created, 'node' AS field_data_field_administrador_node_entity_type, 
 'node' AS field_data_field_propietario_node_entity_type, 'node' AS field_data_field_tecnico_node_entity_type, 
 'node' AS field_data_field_vencimiento_node_entity_type, 'dominios_de_usuario:block' AS view_name
FROM 
{node} node
LEFT JOIN {field_data_field_administrador} field_data_field_administrador ON node.nid = field_data_field_administrador.entity_id 
 AND (field_data_field_administrador.entity_type = 'node' AND field_data_field_administrador.deleted = '0')
LEFT JOIN {field_data_field_propietario} field_data_field_propietario ON node.nid = field_data_field_propietario.entity_id 
 AND (field_data_field_propietario.entity_type = 'node' AND field_data_field_propietario.deleted = '0')
LEFT JOIN {field_data_field_tecnico} field_data_field_tecnico ON node.nid = field_data_field_tecnico.entity_id AND 
 (field_data_field_tecnico.entity_type = 'node' AND field_data_field_tecnico.deleted = '0')
WHERE 
(( 
 (field_data_field_administrador.field_administrador_target_id = '1' ) 
 OR 
 (field_data_field_propietario.field_propietario_target_id = '1' ) 
 OR 
 (field_data_field_tecnico.field_tecnico_target_id = '1' ) )
 AND
 (( (node.status = '1') 
 AND (node.type IN  ('dominio')) )))
ORDER BY node_created DESC
LIMIT 5 OFFSET 0

Espero que les sea de mucha ayuda para los casos específicos donde se requieran condiciones OR en nuestros filtros contextuales.

Recibe consejos y oportunidades de trabajo 100% remotas y en dólares de weKnow Inc.