3

I'm in a spot of bother customizing the calendar block module for my needs. I've written a custom module that queries my database for published nodes that possess a specific taxonomy term. This works as desired; 3 node objects are returned as an array. However, this array is returned a total of 35 times. When I execute the query in my SQL manager the 3 rows are returned without repetition. Is there anything blatantly amiss in my code I haven't been able to spot?

/*
*
* Implementation of hook_calendar_block
*
*/

function calendar_block_mod_calendar_block(&$calendar, &$date, $op) {
  switch($op) {

   case 'alter':
                $sql = "SELECT DISTINCT node.nid AS nid 
                                FROM {node}
                                INNER JOIN term_node term_node ON node.vid = term_node.vid 
                                WHERE (node.status <> 0) AND (term_node.tid = 5)"; 

                $results = db_query($sql);

        while ($node = db_fetch_object($results))
        {    
          $events[] = node_load(array('nid' => $node->nid));
        }

        foreach ($events as $var){
                $thisPath = $var->path;
                                $nodeTitle = $var->title;
                $thisDate = substr($var->field_event_date[0]['value'],0,10);
                                $realDay = substr($thisDate, 8,2);
                $realDate = substr($thisDate, 5, 2) . "-" . ( $realDay < 10 ? substr($realDay, 1,1) : $realDay ) ."-". substr($thisDate, 0, 4);

                                //$dayInfo[] = array ('date' => $realDate, 'title' => $nodeTitle,  'path' => $thisPath );

                                if ($date->date == $realDate) {

                                    $date->content = '<span class="tooltip">'. l($date->day, $thisPath) .'</span>';
                                    $date->content .= '<div class="tooltip_hidden">'. l($nodeTitle, $thisPath) .'</div>';

                                }
                            }
          break;

        case 'load':

        // Change the weekday's format and set the first day of the week to sunday.
        $calendar->weekdays =  array(
            'su' => 'S',
            'mo' => 'M',
            'tu' => 'T',
            'we' => 'W',
            'th' => 'T',
            'fr' => 'F',
            'sa' => 'S',
        );

        break;
  }

}

Edited to include all the code from my module - If anything I hope this can give others a similar starting point. if the code looks like a mess it's because it's my first module.

The code works: nodes with the desired taxonomy term are pulled from the database and each date on the calendar becomes a link to its corresponding node. However on closer inspection the 3 rows are returned 35 times, so doing anything beyond this (e.g. a choice of nodes if there are multiple ones on a single date) becomes a challenge / impossible.

8
  • 1
    In Drupal, you should write the table name between curly brackets. – apaderno May 10 '11 at 17:59
  • Is the code executed inside a hook or a function that is invoked from a hook? – apaderno May 10 '11 at 18:03
  • The code's executed inside the hook function I believe – Storsey May 10 '11 at 18:12
  • 1
    Which hook is, exactly? I ask because it's not clear to me when you say that the code works and it returns an array with 3 objects, but the array is returned 35 times. It seems the code is executed 35 times, then. – apaderno May 10 '11 at 18:14
  • 2
    Could it be that you run your code on every operation $op in the hook? Is there a if($op=='foo') or a switch - case anywhere in the hook? – nonsenz May 10 '11 at 21:19
2

I just took a quick look at the calendar_block module. From what I can tell, hook_calendar_block op alter is called for every single day in the calendar. I guess this makes sense at it allows you to alter the appearance of any day.

My guess is that the calendar on your site has 35 days in it which is why your query is run 35 times.

You could make use of a static variable to only do your stuff once or save the query etc.

Something like this could work:

function calendar_block_mod_calendar_block(&$calendar, &$date, $op) {
  switch($op) {
    case 'alter':
      static $events;
      if (empty($events)) {
        $sql = "SELECT DISTINCT node.nid AS nid 
              FROM {node}
              INNER JOIN term_node term_node ON node.vid = term_node.vid 
              WHERE (node.status <> 0) AND (term_node.tid = 5)"; 

        $results = db_query($sql);

        while ($node = db_fetch_object($results)) {    
          $events[] = node_load(array('nid' => $node->nid));
        }
      }
      ....
  }
}

The above code doesn't catch the case where there is no result and is just meant as a proof of concept.

Update:
If you only want to run the entire code once, you could do something like this:

function calendar_block_mod_calendar_block(&$calendar, &$date, $op) {
  switch($op) {
    case 'alter':
      static $code_executed;
      if (!$code_executed) {
        ...
        $code_executed = TRUE;
      }
  }
}
2
  • Thanks googletorp :).. I should have noticed that the number of executions correlated to the number of days shown on each calendar month. The query is now executed only once and successfully returns the correct results, however my foreach statement is again executed 35 times. – Storsey May 11 '11 at 16:45
  • @Steve you only need to run the entire code once, you can just put all if it in an if statement. – googletorp May 11 '11 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.