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

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

improvement: calendar navigation now uses at maximum one navigation bar
together with a next/previous date links

improvement: calendar view styles now shown in DIV.titrePage (I still need
to move padding from H2 to DIV.titrePage ...)

fix: moved all calendar css colors from template to the theme

  • Property svn:eol-style set to native
File size: 16.3 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 date_field db column on which this calendar works
42   * @param string inner_sql used for queries (INNER JOIN or normal)
43   * @param array date_components
44   */
45  function initialize($date_field, $inner_sql, $date_components)
46  {
47    parent::initialize($date_field, $inner_sql, $date_components);
48    global $lang;
49    $this->calendar_levels = array(
50      array(
51          'sql'=> 'YEAR('.$this->date_field.')',
52          'labels' => null
53        ),
54      array(
55          'sql'=> 'MONTH('.$this->date_field.')',
56          'labels' => $lang['month']
57        ),
58      array(
59          'sql'=> 'DAYOFMONTH('.$this->date_field.')',
60          'labels' => null
61        ),
62     );
63  }
64
65/**
66 * Generate navigation bars for category page
67 * @return boolean false to indicate that thumbnails
68 * where not included here, true otherwise
69 */
70function generate_category_content($url_base, $view_type)
71{
72  global $conf;
73
74  $this->url_base = $url_base;
75
76  if ($view_type==CAL_VIEW_CALENDAR)
77  {
78    if ( count($this->date_components)==0 )
79    {//case A: no year given - display all years+months
80      if ($this->build_global_calendar())
81        return true;
82    }
83
84    if ( count($this->date_components)==1 )
85    {//case B: year given - display all days in given year
86      if ($this->build_year_calendar())
87      {
88        $this->build_nav_bar(CYEAR); // years
89        return true;
90      }
91    }
92
93    if ( count($this->date_components)==2 )
94    {//case C: year+month given - display a nice month calendar
95      $this->build_month_calendar();
96      //$this->build_nav_bar(CYEAR); // years
97      //$this->build_nav_bar(CMONTH); // month
98      $this->build_next_prev();
99      return true;
100    }
101  }
102
103  if ($view_type==CAL_VIEW_LIST or count($this->date_components)==3)
104  {
105    $has_nav_bar = false;
106    if ( count($this->date_components)==0 )
107    {
108      $this->build_nav_bar(CYEAR); // years
109    }
110    if ( count($this->date_components)==1)
111    {
112      $this->build_nav_bar(CMONTH); // month
113    }
114    if ( count($this->date_components)==2 )
115    {
116      $day_labels = range( 1, $this->get_all_days_in_month(
117              $this->date_components[CYEAR] ,$this->date_components[CMONTH] ) );
118      array_unshift($day_labels, 0);
119      unset( $day_labels[0] );
120      $this->build_nav_bar( CDAY, $day_labels ); // days
121    }
122    $this->build_next_prev();
123  }
124  return false;
125}
126
127
128/**
129 * Returns a sql where subquery for the date field
130 * @param int max_levels return the where up to this level
131 * (e.g. 2=only year and month)
132 * @return string
133 */
134function get_date_where($max_levels=3)
135{
136  $date = $this->date_components;
137  while (count($date)>$max_levels)
138  {
139    array_pop($date);
140  }
141  $res = '';
142  if (isset($date[CYEAR]) and $date[CYEAR]!='any')
143  {
144    $b = $date[CYEAR] . '-';
145    $e = $date[CYEAR] . '-';
146    if (isset($date[CMONTH]) and $date[CMONTH]!='any')
147    {
148      $b .= $date[CMONTH] . '-';
149      $e .= $date[CMONTH] . '-';
150      if (isset($date[CDAY]) and $date[CDAY]!='any')
151      {
152        $b .= $date[CDAY];
153        $e .= $date[CDAY];
154      }
155      else
156      {
157        $b .= '01';
158        $e .= '31';
159      }
160    }
161    else
162    {
163      $b .= '01-01';
164      $e .= '12-31';
165      if (isset($date[CMONTH]) and $date[CMONTH]!='any')
166      {
167        $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
168      }
169      if (isset($date[CDAY]) and $date[CDAY]!='any')
170      {
171        $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
172      }
173    }
174    $res = " AND $this->date_field BETWEEN '$b' AND '$e 23:59:59'" . $res;
175  }
176  else
177  {
178    $res = ' AND '.$this->date_field.' IS NOT NULL';
179    if (isset($date[CMONTH]) and $date[CMONTH]!='any')
180    {
181      $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
182    }
183    if (isset($date[CDAY]) and $date[CDAY]!='any')
184    {
185      $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
186    }
187  }
188  return $res;
189}
190
191
192
193//--------------------------------------------------------- private members ---
194
195// returns an array with alll the days in a given month
196function get_all_days_in_month($year, $month)
197{
198  $md= array(1=>31,28,31,30,31,30,31,31,30,31,30,31);
199
200  if ( is_numeric($year) and $month==2)
201  {
202    $nb_days = $md[2];
203    if ( ($year%4==0)  and ( ($year%100!=0) or ($year%400!=0) ) )
204    {
205      $nb_days++;
206    }
207  }
208  elseif ( is_numeric($month) )
209  {
210    $nb_days = $md[ $month ];
211  }
212  else
213  {
214    $nb_days = 31;
215  }
216  return $nb_days;
217}
218
219function build_global_calendar()
220{
221  assert( count($this->date_components) == 0 );
222  $query='SELECT DISTINCT(DATE_FORMAT('.$this->date_field.',"%Y%m")) as period,
223            COUNT( DISTINCT(id) ) as count';
224  $query.= $this->inner_sql;
225  $query.= $this->get_date_where();
226  $query.= '
227  GROUP BY period';
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    $this->date_components[CYEAR] = $y;
247    return false;
248  }
249
250  global $lang, $template;
251  foreach ( $items as $year=>$year_data)
252  {
253    $url_base = $this->url_base.$year;
254
255    $nav_bar = '<span class="calCalHead"><a href="'.$url_base.'">'.$year.'</a>';
256    $nav_bar .= ' ('.$year_data['nb_images'].')';
257    $nav_bar .= '</span><br>';
258
259    $url_base .= '-';
260    $nav_bar .= $this->get_nav_bar_from_items( $url_base,
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  assert( count($this->date_components) == 1 );
273  $query='SELECT DISTINCT(DATE_FORMAT('.$this->date_field.',"%m%d")) as period,
274            COUNT( DISTINCT(id) ) as count';
275  $query.= $this->inner_sql;
276  $query.= $this->get_date_where();
277  $query.= '
278  GROUP BY period';
279
280  $result = pwg_query($query);
281  $items=array();
282  while ($row = mysql_fetch_array($result))
283  {
284    $m = (int)substr($row['period'], 0, 2);
285    $d = substr($row['period'], 2, 2);
286    if ( ! isset($items[$m]) )
287    {
288      $items[$m] = array('nb_images'=>0, 'children'=>array() );
289    }
290    $items[$m]['children'][$d] = $row['count'];
291    $items[$m]['nb_images'] += $row['count'];
292  }
293  //echo ('<pre>'. var_export($items, true) . '</pre>');
294  if (count($items)==1)
295  { // only one month exists so bail out to month view
296    list($m) = array_keys($items);
297    $this->date_components[CMONTH] = $m;
298    return false;
299  }
300  global $lang, $template;
301  foreach ( $items as $month=>$month_data)
302  {
303    $url_base = $this->url_base.$this->date_components[CYEAR].'-'.$month;
304
305    $nav_bar = '<span class="calCalHead"><a href="'.$url_base.'">';
306    $nav_bar .= $lang['month'][$month].'</a>';
307    $nav_bar .= ' ('.$month_data['nb_images'].')';
308    $nav_bar .= '</span><br>';
309
310    $url_base .= '-';
311    $nav_bar .= $this->get_nav_bar_from_items( $url_base,
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  $query='SELECT DISTINCT(DAYOFMONTH('.$this->date_field.')) as period,
325            COUNT( DISTINCT(id) ) as count';
326  $query.= $this->inner_sql;
327  $query.= $this->get_date_where($this->date_components);
328  $query.= '
329  GROUP BY period';
330
331  $result = pwg_query($query);
332  while ($row = mysql_fetch_array($result))
333  {
334    $d = (int)$row['period'];
335    $items[$d] = array('nb_images'=>$row['count']);
336  }
337
338  foreach ( $items as $day=>$data)
339  {
340    $this->date_components[CDAY]=$day;
341    $query = '
342SELECT file,tn_ext,path, width, height, DAYOFWEEK('.$this->date_field.')-1 as dow';
343    $query.= $this->inner_sql;
344    $query.= $this->get_date_where();
345    $query.= '
346  ORDER BY RAND()
347  LIMIT 0,1';
348    unset ( $this->date_components[CDAY] );
349
350    $row = mysql_fetch_array(pwg_query($query));
351    $items[$day]['tn_path'] = get_thumbnail_src($row['path'], @$row['tn_ext']);
352    $items[$day]['tn_file'] = $row['file'];
353    $items[$day]['width'] = $row['width'];
354    $items[$day]['height'] = $row['height'];
355    $items[$day]['dow'] = $row['dow'];
356  }
357
358  global $lang, $template, $conf;
359
360  if ( !empty($items)
361      and $conf['calendar_month_cell_width']>0
362      and $conf['calendar_month_cell_height']>0)
363  {
364    list($known_day) = array_keys($items);
365    $known_dow = $items[$known_day]['dow'];
366    $first_day_dow = ($known_dow-($known_day-1))%7;
367    if ($first_day_dow<0)
368    {
369      $first_day_dow += 7;
370    }
371    //first_day_dow = week day corresponding to the first day of this month
372    $wday_labels = $lang['day'];
373
374    // BEGIN - pass now in week starting Monday
375    if ($first_day_dow==0)
376    {
377      $first_day_dow = 6;
378    }
379    else
380    {
381      $first_day_dow -= 1;
382    }
383    array_push( $wday_labels, array_shift($wday_labels) );
384    // END - pass now in week starting Monday
385
386    $cell_width = $conf['calendar_month_cell_width'];
387    $cell_height = $conf['calendar_month_cell_height'];
388
389    $template->set_filenames(
390      array(
391        'month_calendar'=>'month_calendar.tpl',
392        )
393      );
394
395    $template->assign_block_vars('calendar.thumbnails',
396        array(
397           'WIDTH'=>$cell_width,
398           'HEIGHT'=>$cell_height,
399          )
400      );
401
402    //fill the heading with day names
403    $template->assign_block_vars('calendar.thumbnails.head', array());
404    foreach( $wday_labels as $d => $label)
405    {
406      $template->assign_block_vars('calendar.thumbnails.head.col',
407                    array('LABEL'=>$label)
408                  );
409    }
410
411    $template->assign_block_vars('calendar.thumbnails.row', array());
412
413    //fill the empty days in the week before first day of this month
414    for ($i=0; $i<$first_day_dow; $i++)
415    {
416      $template->assign_block_vars('calendar.thumbnails.row.col', array());
417      $template->assign_block_vars('calendar.thumbnails.row.col.blank', array());
418    }
419    for ($day=1; $day<=$this->get_all_days_in_month(
420              $this->date_components[CYEAR] ,$this->date_components[CMONTH]); $day++)
421    {
422      $dow = ($first_day_dow + $day-1)%7;
423      if ($dow==0)
424      {
425        $template->assign_block_vars('calendar.thumbnails.row', array());
426      }
427      $template->assign_block_vars('calendar.thumbnails.row.col', array());
428      if ( !isset($items[$day]) )
429      {
430        $template->assign_block_vars('calendar.thumbnails.row.col.empty',
431              array('LABEL'=>$day));
432      }
433      else
434      {
435        // first try to guess thumbnail size
436        if ( !empty($items[$day]['width']) )
437        {
438          $tn_size = get_picture_size(
439                 $items[$day]['width'], $items[$day]['height'],
440                 $conf['tn_width'], $conf['tn_height'] );
441        }
442        else
443        {// item not an image (tn is either mime type or an image)
444          $tn_size = @getimagesize($items[$day]['tn_path']);
445        }
446        $tn_width = $tn_size[0];
447        $tn_height = $tn_size[1];
448
449        // now need to fit the thumbnail of size tn_size within
450        // a cell of size cell_size by playing with CSS position (left/top)
451        // and the width and height of <img>.
452        $ratio_w = $tn_width/$cell_width;
453        $ratio_h = $tn_height/$cell_height;
454
455        $pos_top=$pos_left=0;
456        $img_width=$img_height='';
457        if ( $ratio_w>1 and $ratio_h>1)
458        {// cell completely smaller than the thumbnail so we will let the browser
459         // resize the thumbnail
460          if ($ratio_w > $ratio_h )
461          {// thumbnail ratio compared to cell -> wide format
462            $img_height = 'height="'.$cell_height.'"';
463            $browser_img_width = $cell_height*$tn_width/$tn_height;
464            $pos_left = ($tn_width-$browser_img_width)/2;
465          }
466          else
467          {
468            $img_width = 'width="'.$cell_width.'"';
469            $browser_img_height = $cell_width*$tn_height/$tn_width;
470            $pos_top = ($tn_height-$browser_img_height)/2;
471          }
472        }
473        else
474        {
475          $pos_left = ($tn_width-$cell_width)/2;
476          $pos_top = ($tn_height-$cell_height)/2;
477        }
478
479        $css_style = '';
480        if ( round($pos_left)!=0)
481        {
482          $css_style.='left:'.round(-$pos_left).'px;';
483        }
484        if ( round($pos_top)!=0)
485        {
486          $css_style.='top:'.round(-$pos_top).'px;';
487        }
488        $url = $this->url_base.
489              $this->date_components[CYEAR].'-'.
490              $this->date_components[CMONTH].'-'.$day;
491        $alt = $wday_labels[$dow] . ' ' . $day.
492               ' ('.$items[$day]['nb_images'].')';
493        $template->assign_block_vars('calendar.thumbnails.row.col.full',
494              array(
495                'LABEL'     => $day,
496                'IMAGE'     => $items[$day]['tn_path'],
497                'U_IMG_LINK'=> $url,
498                'STYLE'     => $css_style,
499                'IMG_WIDTH' => $img_width,
500                'IMG_HEIGHT'=> $img_height,
501                'IMAGE_ALT' => $alt,
502              )
503            );
504      }
505    }
506    //fill the empty days in the week after the last day of this month
507    while ( $dow<6 )
508    {
509      $template->assign_block_vars('calendar.thumbnails.row.col', array());
510      $template->assign_block_vars('calendar.thumbnails.row.col.blank', array());
511      $dow++;
512    }
513    $template->assign_var_from_handle('MONTH_CALENDAR', 'month_calendar');
514  }
515  else
516  {
517    $template->assign_block_vars('thumbnails', array());
518    $template->assign_block_vars('thumbnails.line', array());
519    foreach ( $items as $day=>$data)
520    {
521      $url = $this->url_base.
522            $this->date_components[CYEAR].'-'.
523            $this->date_components[CMONTH].'-'.$day;
524
525      $thumbnail_title = $lang['day'][$data['dow']] . ' ' . $day;
526      $name = $thumbnail_title .' ('.$data['nb_images'].')';
527
528      $template->assign_block_vars(
529          'thumbnails.line.thumbnail',
530          array(
531            'IMAGE'=>$data['tn_path'],
532            'IMAGE_ALT'=>$data['tn_file'],
533            'IMAGE_TITLE'=>$thumbnail_title,
534            'U_IMG_LINK'=>$url
535           )
536          );
537      $template->assign_block_vars(
538          'thumbnails.line.thumbnail.category_name',
539          array(
540            'NAME' => $name
541            )
542          );
543    }
544  }
545
546  return true;
547}
548
549}
550?>
Note: See TracBrowser for help on using the repository browser.