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

Last change on this file since 2297 was 2297, checked in by plg, 16 years ago

Modification: new header on PHP files, PhpWebGallery renamed Piwigo.

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