Building HAVING clause with Views

Events happening in the community are now at Drupal community events on www.drupal.org.
littlecoding's picture

I have a Drupal 7 site that is having a some problems with a calendar page managed by views. The sessions that make up an event our used to populate the events on a calendar. The sessions grouping into a single event gets mixed up when an event spans across multiple months.

When looking over the query Views generates, I see that date ranges is managed with a WHERE clause using the start+end dates of sessions. This is causing the calendar to show a new event start for the first instance of a session within an event. In other words, the event gets incorrect listings as starting in multiple months.

I know I want to change the start+end date WHERE clauses to a single HAVING MIN(start) date clause, but I don't know how to do this within Views. Does anyone have a tip or two on how to get this worked out?

Drupal 7, Views 3.13, Calendars 3.5

Comments

Hey Rob, I haven't used

pierremarcel's picture

Hey Rob, I haven't used Calendar module since D6, so I can't really remember how those views were done... I'll see if I have a drupal test install, if i do I'll through calendar module and check it for you.

Answer

littlecoding's picture

Well I got myself in the right area fast but then found every way not to get the full answer or at least that's how it felt.

<?php
function mymodule_views_query_alter(&$view, &$query) {
  if (
$view->name == 'myview_calendar' && $view->current_display == 'page_calendar') {
   
$where =& $query->where;
    foreach(
$where AS $k => $clause) {
      if (!empty(
$clause['conditions'][0]['value'][':field_startdate_date_argument'])) {
       
$query->add_having_expression(
         
0,
         
"DATE_FORMAT(MIN(node.field_startdate), '%Y-%m') = '{$view->args[2]}' ",
          array()
        );
        unset(
$where[$k]);
      }
    }
  }
}
?>

First off you are best off to work with hook_views_query_alter(). Started off with a checking the view name and current_display to target the correct view and display and created a foreach to run through all of the where clauses. Next I used the where clause created by contextual filter of the requested (or default) date compared to my starting date field to add the HAVING clause. I had a complex expression with the use of DATE_FORMAT and MIN do I had to use add_having_expression vs add_having for simple cases. And finally I used the key variable $k from the foreach to remove the where clause as it was not needed.

One thing that also gave me a headache was passing in the view argument for the date. It was simple to get from the $view object, but I did have to place it directly in the field variable of the add_having_expression function to avoid the variable being miscast and causing an error.

Hope this can help someone else some time.

Niagara and Hamilton Region

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: