source: trunk/include/calendar_monthly.class.php @ 1558

Last change on this file since 1558 was 1558, checked in by rvelices, 18 years ago

bug 549: fix uninitialized variable PHP warning in calendar

  • Property svn:eol-style set to native
File size: 16.9 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | PhpWebGallery - a PHP based picture gallery                           |
4// | Copyright (C) 2003-2006 PhpWebGallery Team - http://phpwebgallery.net |
5// +-----------------------------------------------------------------------+
6// | branch        : BSF (Best So Far)
7// | file          : $RCSfile$
8// | last update   : $Date: 2006-01-27 02:11:43 +0100 (ven, 27 jan 2006) $
9// | last modifier : $Author: rvelices $
10// | revision      : $Revision: 1014 $
11// +-----------------------------------------------------------------------+
12// | This program is free software; you can redistribute it and/or modify  |
13// | it under the terms of the GNU General Public License as published by  |
14// | the Free Software Foundation                                          |
15// |                                                                       |
16// | This program is distributed in the hope that it will be useful, but   |
17// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
18// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
19// | General Public License for more details.                              |
20// |                                                                       |
21// | You should have received a copy of the GNU General Public License     |
22// | along with this program; if not, write to the Free Software           |
23// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
24// | USA.                                                                  |
25// +-----------------------------------------------------------------------+
26
27include_once(PHPWG_ROOT_PATH.'include/calendar_base.class.php');
28
29define ('CYEAR',  0);
30define ('CMONTH', 1);
31define ('CDAY',   2);
32
33/**
34 * Monthly calendar style (composed of years/months and days)
35 */
36class Calendar extends CalendarBase
37{
38
39  /**
40   * Initialize the calendar
41   * @param string inner_sql used for queries (INNER JOIN or normal)
42   */
43  function initialize($inner_sql)
44  {
45    parent::initialize($inner_sql);
46    global $lang;
47    $this->calendar_levels = array(
48      array(
49          'sql'=> 'YEAR('.$this->date_field.')',
50          'labels' => null
51        ),
52      array(
53          'sql'=> 'MONTH('.$this->date_field.')',
54          'labels' => $lang['month']
55        ),
56      array(
57          'sql'=> 'DAYOFMONTH('.$this->date_field.')',
58          'labels' => null
59        ),
60     );
61  }
62
63/**
64 * Generate navigation bars for category page
65 * @return boolean false to indicate that thumbnails
66 * where not included here, true otherwise
67 */
68function generate_category_content()
69{
70  global $conf, $page;
71
72  $view_type = $page['chronology_view'];
73  if ($view_type==CAL_VIEW_CALENDAR)
74  {
75    if ( count($page['chronology_date'])==0 )
76    {//case A: no year given - display all years+months
77      if ($this->build_global_calendar())
78        return true;
79    }
80
81    if ( count($page['chronology_date'])==1 )
82    {//case B: year given - display all days in given year
83      if ($this->build_year_calendar())
84      {
85        $this->build_nav_bar(CYEAR); // years
86        return true;
87      }
88    }
89
90    if ( count($page['chronology_date'])==2 )
91    {//case C: year+month given - display a nice month calendar
92      $this->build_month_calendar();
93      //$this->build_nav_bar(CYEAR); // years
94      //$this->build_nav_bar(CMONTH); // month
95      $this->build_next_prev();
96      return true;
97    }
98  }
99
100  if ($view_type==CAL_VIEW_LIST or count($page['chronology_date'])==3)
101  {
102    $has_nav_bar = false;
103    if ( count($page['chronology_date'])==0 )
104    {
105      $this->build_nav_bar(CYEAR); // years
106    }
107    if ( count($page['chronology_date'])==1)
108    {
109      $this->build_nav_bar(CMONTH); // month
110    }
111    if ( count($page['chronology_date'])==2 )
112    {
113      $day_labels = range( 1, $this->get_all_days_in_month(
114              $page['chronology_date'][CYEAR] ,$page['chronology_date'][CMONTH] ) );
115      array_unshift($day_labels, 0);
116      unset( $day_labels[0] );
117      $this->build_nav_bar( CDAY, $day_labels ); // days
118    }
119    $this->build_next_prev();
120  }
121  return false;
122}
123
124
125/**
126 * Returns a sql where subquery for the date field
127 * @param int max_levels return the where up to this level
128 * (e.g. 2=only year and month)
129 * @return string
130 */
131function get_date_where($max_levels=3)
132{
133  global $page;
134  $date = $page['chronology_date'];
135  while (count($date)>$max_levels)
136  {
137    array_pop($date);
138  }
139  $res = '';
140  if (isset($date[CYEAR]) and $date[CYEAR]!=='any')
141  {
142    $b = $date[CYEAR] . '-';
143    $e = $date[CYEAR] . '-';
144    if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
145    {
146      $b .= $date[CMONTH] . '-';
147      $e .= $date[CMONTH] . '-';
148      if (isset($date[CDAY]) and $date[CDAY]!=='any')
149      {
150        $b .= $date[CDAY];
151        $e .= $date[CDAY];
152      }
153      else
154      {
155        $b .= '01';
156        $e .= '31';
157      }
158    }
159    else
160    {
161      $b .= '01-01';
162      $e .= '12-31';
163      if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
164      {
165        $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
166      }
167      if (isset($date[CDAY]) and $date[CDAY]!=='any')
168      {
169        $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
170      }
171    }
172    $res = " AND $this->date_field BETWEEN '$b' AND '$e 23:59:59'" . $res;
173  }
174  else
175  {
176    $res = ' AND '.$this->date_field.' IS NOT NULL';
177    if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
178    {
179      $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
180    }
181    if (isset($date[CDAY]) and $date[CDAY]!=='any')
182    {
183      $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
184    }
185  }
186  return $res;
187}
188
189
190
191//--------------------------------------------------------- private members ---
192
193// returns an array with alll the days in a given month
194function get_all_days_in_month($year, $month)
195{
196  $md= array(1=>31,28,31,30,31,30,31,31,30,31,30,31);
197
198  if ( is_numeric($year) and $month==2)
199  {
200    $nb_days = $md[2];
201    if ( ($year%4==0)  and ( ($year%100!=0) or ($year%400!=0) ) )
202    {
203      $nb_days++;
204    }
205  }
206  elseif ( is_numeric($month) )
207  {
208    $nb_days = $md[ $month ];
209  }
210  else
211  {
212    $nb_days = 31;
213  }
214  return $nb_days;
215}
216
217function build_global_calendar()
218{
219  global $page;
220  assert( count($page['chronology_date']) == 0 );
221  $query='SELECT DISTINCT(DATE_FORMAT('.$this->date_field.',"%Y%m")) as period,
222            COUNT( DISTINCT(id) ) as count';
223  $query.= $this->inner_sql;
224  $query.= $this->get_date_where();
225  $query.= '
226  GROUP BY period
227  ORDER BY YEAR('.$this->date_field.') DESC, MONTH('.$this->date_field.')';
228
229  $result = pwg_query($query);
230  $items=array();
231  while ($row = mysql_fetch_array($result))
232  {
233    $y = substr($row['period'], 0, 4);
234    $m = (int)substr($row['period'], 4, 2);
235    if ( ! isset($items[$y]) )
236    {
237      $items[$y] = array('nb_images'=>0, 'children'=>array() );
238    }
239    $items[$y]['children'][$m] = $row['count'];
240    $items[$y]['nb_images'] += $row['count'];
241  }
242  //echo ('<pre>'. var_export($items, true) . '</pre>');
243  if (count($items)==1)
244  {// only one year exists so bail out to year view
245    list($y) = array_keys($items);
246    $page['chronology_date'][CYEAR] = $y;
247    return false;
248  }
249
250  global $lang, $template;
251  foreach ( $items as $year=>$year_data)
252  {
253    $chronology_date = array( $year );
254    $url = duplicate_index_url( array('chronology_date'=>$chronology_date) );
255
256    $nav_bar = '<span class="calCalHead"><a href="'.$url.'">'.$year.'</a>';
257    $nav_bar .= ' ('.$year_data['nb_images'].')';
258    $nav_bar .= '</span><br>';
259
260    $nav_bar .= $this->get_nav_bar_from_items( $chronology_date,
261            $year_data['children'], null, 'calCal', false, false, $lang['month'] );
262
263    $template->assign_block_vars( 'calendar.calbar',
264         array( 'BAR' => $nav_bar)
265         );
266  }
267  return true;
268}
269
270function build_year_calendar()
271{
272  global $page;
273  assert( count($page['chronology_date']) == 1 );
274  $query='SELECT DISTINCT(DATE_FORMAT('.$this->date_field.',"%m%d")) as period,
275            COUNT( DISTINCT(id) ) as count';
276  $query.= $this->inner_sql;
277  $query.= $this->get_date_where();
278  $query.= '
279  GROUP BY period';
280
281  $result = pwg_query($query);
282  $items=array();
283  while ($row = mysql_fetch_array($result))
284  {
285    $m = (int)substr($row['period'], 0, 2);
286    $d = substr($row['period'], 2, 2);
287    if ( ! isset($items[$m]) )
288    {
289      $items[$m] = array('nb_images'=>0, 'children'=>array() );
290    }
291    $items[$m]['children'][$d] = $row['count'];
292    $items[$m]['nb_images'] += $row['count'];
293  }
294  if (count($items)==1)
295  { // only one month exists so bail out to month view
296    list($m) = array_keys($items);
297    $page['chronology_date'][CMONTH] = $m;
298    return false;
299  }
300  global $lang, $template;
301  foreach ( $items as $month=>$month_data)
302  {
303    $chronology_date = array( $page['chronology_date'][CYEAR], $month );
304    $url = duplicate_index_url( array('chronology_date'=>$chronology_date) );
305
306    $nav_bar = '<span class="calCalHead"><a href="'.$url.'">';
307    $nav_bar .= $lang['month'][$month].'</a>';
308    $nav_bar .= ' ('.$month_data['nb_images'].')';
309    $nav_bar .= '</span><br>';
310
311    $nav_bar .= $this->get_nav_bar_from_items( $chronology_date,
312                     $month_data['children'], null, 'calCal', false );
313
314    $template->assign_block_vars( 'calendar.calbar',
315         array( 'BAR' => $nav_bar)
316         );
317  }
318  return true;
319
320}
321
322function build_month_calendar()
323{
324  global $page;
325  $query='SELECT DISTINCT(DAYOFMONTH('.$this->date_field.')) as period,
326            COUNT( DISTINCT(id) ) as count';
327  $query.= $this->inner_sql;
328  $query.= $this->get_date_where();
329  $query.= '
330  GROUP BY period';
331
332  $items=array();
333  $result = pwg_query($query);
334  while ($row = mysql_fetch_array($result))
335  {
336    $d = (int)$row['period'];
337    $items[$d] = array('nb_images'=>$row['count']);
338  }
339
340  foreach ( $items as $day=>$data)
341  {
342    $page['chronology_date'][CDAY]=$day;
343    $query = '
344SELECT file,tn_ext,path, width, height, DAYOFWEEK('.$this->date_field.')-1 as dow';
345    $query.= $this->inner_sql;
346    $query.= $this->get_date_where();
347    $query.= '
348  ORDER BY RAND()
349  LIMIT 0,1';
350    unset ( $page['chronology_date'][CDAY] );
351
352    $row = mysql_fetch_array(pwg_query($query));
353    $items[$day]['tn_path'] = get_thumbnail_src($row['path'], @$row['tn_ext']);
354    $items[$day]['file'] = $row['file'];
355    $items[$day]['path'] = $row['path'];
356    $items[$day]['tn_ext'] = @$row['tn_ext'];
357    $items[$day]['width'] = $row['width'];
358    $items[$day]['height'] = $row['height'];
359    $items[$day]['dow'] = $row['dow'];
360  }
361
362  global $lang, $template, $conf;
363
364  if ( !empty($items)
365      and $conf['calendar_month_cell_width']>0
366      and $conf['calendar_month_cell_height']>0)
367  {
368    list($known_day) = array_keys($items);
369    $known_dow = $items[$known_day]['dow'];
370    $first_day_dow = ($known_dow-($known_day-1))%7;
371    if ($first_day_dow<0)
372    {
373      $first_day_dow += 7;
374    }
375    //first_day_dow = week day corresponding to the first day of this month
376    $wday_labels = $lang['day'];
377
378    // BEGIN - pass now in week starting Monday
379    if ($first_day_dow==0)
380    {
381      $first_day_dow = 6;
382    }
383    else
384    {
385      $first_day_dow -= 1;
386    }
387    array_push( $wday_labels, array_shift($wday_labels) );
388    // END - pass now in week starting Monday
389
390    $cell_width = $conf['calendar_month_cell_width'];
391    $cell_height = $conf['calendar_month_cell_height'];
392
393    $template->set_filenames(
394      array(
395        'month_calendar'=>'month_calendar.tpl',
396        )
397      );
398
399    $template->assign_block_vars('calendar.thumbnails',
400        array(
401           'WIDTH'=>$cell_width,
402           'HEIGHT'=>$cell_height,
403          )
404      );
405
406    //fill the heading with day names
407    $template->assign_block_vars('calendar.thumbnails.head', array());
408    foreach( $wday_labels as $d => $label)
409    {
410      $template->assign_block_vars('calendar.thumbnails.head.col',
411                    array('LABEL'=>$label)
412                  );
413    }
414
415    $template->assign_block_vars('calendar.thumbnails.row', array());
416
417    //fill the empty days in the week before first day of this month
418    for ($i=0; $i<$first_day_dow; $i++)
419    {
420      $template->assign_block_vars('calendar.thumbnails.row.col', array());
421      $template->assign_block_vars('calendar.thumbnails.row.col.blank', array());
422    }
423    for ( $day = 1;
424          $day <= $this->get_all_days_in_month(
425            $page['chronology_date'][CYEAR], $page['chronology_date'][CMONTH]
426              );
427          $day++)
428    {
429      $dow = ($first_day_dow + $day-1)%7;
430      if ($dow==0 and $day!=1)
431      {
432        $template->assign_block_vars('calendar.thumbnails.row', array());
433      }
434      $template->assign_block_vars('calendar.thumbnails.row.col', array());
435      if ( !isset($items[$day]) )
436      {
437        $template->assign_block_vars('calendar.thumbnails.row.col.empty',
438              array('LABEL'=>$day));
439      }
440      else
441      {
442        // first try to guess thumbnail size
443        if ( !empty($items[$day]['width']) )
444        {
445          $tn_size = get_picture_size(
446                 $items[$day]['width'], $items[$day]['height'],
447                 $conf['tn_width'], $conf['tn_height'] );
448        }
449        else
450        {// item not an image (tn is either mime type or an image)
451          $thumb = get_thumbnail_src(
452                $items[$day]['path'], @$items[$day]['tn_ext'], false
453              );
454          $tn_size = @getimagesize($thumb);
455        }
456        $tn_width = $tn_size[0];
457        $tn_height = $tn_size[1];
458
459        // now need to fit the thumbnail of size tn_size within
460        // a cell of size cell_size by playing with CSS position (left/top)
461        // and the width and height of <img>.
462        $ratio_w = $tn_width/$cell_width;
463        $ratio_h = $tn_height/$cell_height;
464
465
466        $pos_top=$pos_left=0;
467        $img_width=$img_height='';
468        if ( $ratio_w>1 and $ratio_h>1)
469        {// cell completely smaller than the thumbnail so we will let the browser
470         // resize the thumbnail
471          if ($ratio_w > $ratio_h )
472          {// thumbnail ratio compared to cell -> wide format
473            $img_height = 'height="'.$cell_height.'"';
474            $browser_img_width = $cell_height*$tn_width/$tn_height;
475            $pos_left = ($browser_img_width-$cell_width)/2;
476          }
477          else
478          {
479            $img_width = 'width="'.$cell_width.'"';
480            $browser_img_height = $cell_width*$tn_height/$tn_width;
481            $pos_top = ($browser_img_height-$cell_height)/2;
482          }
483        }
484        else
485        {
486          $pos_left = ($tn_width-$cell_width)/2;
487          $pos_top = ($tn_height-$cell_height)/2;
488        }
489
490        $css_style = '';
491        if ( round($pos_left)!=0)
492        {
493          $css_style.='left:'.round(-$pos_left).'px;';
494        }
495        if ( round($pos_top)!=0)
496        {
497          $css_style.='top:'.round(-$pos_top).'px;';
498        }
499        $url = duplicate_index_url(
500            array(
501              'chronology_date' =>
502                array(
503                  $page['chronology_date'][CYEAR],
504                  $page['chronology_date'][CMONTH],
505                  $day
506                )
507            )
508          );
509        $alt = $wday_labels[$dow] . ' ' . $day.
510               ' ('.$items[$day]['nb_images'].')';
511        $template->assign_block_vars('calendar.thumbnails.row.col.full',
512              array(
513                'LABEL'     => $day,
514                'IMAGE'     => $items[$day]['tn_path'],
515                'U_IMG_LINK'=> $url,
516                'STYLE'     => $css_style,
517                'IMG_WIDTH' => $img_width,
518                'IMG_HEIGHT'=> $img_height,
519                'IMAGE_ALT' => $alt,
520              )
521            );
522      }
523    }
524    //fill the empty days in the week after the last day of this month
525    while ( $dow<6 )
526    {
527      $template->assign_block_vars('calendar.thumbnails.row.col', array());
528      $template->assign_block_vars('calendar.thumbnails.row.col.blank', array());
529      $dow++;
530    }
531    $template->assign_var_from_handle('MONTH_CALENDAR', 'month_calendar');
532  }
533  else
534  {
535    $template->assign_block_vars('thumbnails', array());
536    $template->assign_block_vars('thumbnails.line', array());
537    foreach ( $items as $day=>$data)
538    {
539      $url = duplicate_index_url(
540          array(
541            'chronology_date' =>
542              array(
543                $page['chronology_date'][CYEAR],
544                $page['chronology_date'][CMONTH],
545                $day
546              )
547          )
548        );
549
550      $thumbnail_title = $lang['day'][$data['dow']] . ' ' . $day;
551      $name = $thumbnail_title .' ('.$data['nb_images'].')';
552
553      $template->assign_block_vars(
554          'thumbnails.line.thumbnail',
555          array(
556            'IMAGE'=>$data['tn_path'],
557            'IMAGE_ALT'=>$data['file'],
558            'IMAGE_TITLE'=>$thumbnail_title,
559            'U_IMG_LINK'=>$url
560           )
561          );
562      $template->assign_block_vars(
563          'thumbnails.line.thumbnail.category_name',
564          array(
565            'NAME' => $name
566            )
567          );
568    }
569  }
570
571  return true;
572}
573
574}
575?>
Note: See TracBrowser for help on using the repository browser.