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

Last change on this file since 26497 was 26461, checked in by mistic100, 11 years ago

Update headers to 2014. Happy new year!!

  • Property svn:eol-style set to LF
File size: 14.1 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 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/**
25 * @package functions\calendar
26 */
27
28include_once(PHPWG_ROOT_PATH.'include/calendar_base.class.php');
29
30/** level of year view */
31define('CYEAR',  0);
32/** level of month view */
33define('CMONTH', 1);
34/** level of day view */
35define('CDAY',   2);
36
37
38/**
39 * Monthly calendar style (composed of years/months and days)
40 */
41class Calendar extends CalendarBase
42{
43  /**
44   * Initialize the calendar.
45   * @param string $inner_sql
46   */
47  function initialize($inner_sql)
48  {
49    parent::initialize($inner_sql);
50    global $lang;
51    $this->calendar_levels = array(
52      array(
53          'sql'=> pwg_db_get_year($this->date_field),
54          'labels' => null
55        ),
56      array(
57          'sql'=> pwg_db_get_month($this->date_field),
58          'labels' => $lang['month']
59        ),
60      array(
61          'sql'=> pwg_db_get_dayofmonth($this->date_field),
62          'labels' => null
63        ),
64     );
65  }
66
67  /**
68   * Generate navigation bars for category page.
69   *
70   * @return boolean false indicates that thumbnails where not included
71   */
72  function generate_category_content()
73  {
74    global $conf, $page;
75
76    $view_type = $page['chronology_view'];
77    if ($view_type==CAL_VIEW_CALENDAR)
78    {
79      global $template;
80      $tpl_var = array();
81      if ( count($page['chronology_date'])==0 )
82      {//case A: no year given - display all years+months
83        if ($this->build_global_calendar($tpl_var))
84        {
85          $template->assign('chronology_calendar', $tpl_var);
86          return true;
87        }
88      }
89
90      if ( count($page['chronology_date'])==1 )
91      {//case B: year given - display all days in given year
92        if ($this->build_year_calendar($tpl_var))
93        {
94          $template->assign('chronology_calendar', $tpl_var);
95          $this->build_nav_bar(CYEAR); // years
96          return true;
97        }
98      }
99
100      if ( count($page['chronology_date'])==2 )
101      {//case C: year+month given - display a nice month calendar
102        if ( $this->build_month_calendar($tpl_var) )
103        {
104          $template->assign('chronology_calendar', $tpl_var);
105        }
106        $this->build_next_prev();
107        return true;
108      }
109    }
110
111    if ($view_type==CAL_VIEW_LIST or count($page['chronology_date'])==3)
112    {
113      if ( count($page['chronology_date'])==0 )
114      {
115        $this->build_nav_bar(CYEAR); // years
116      }
117      if ( count($page['chronology_date'])==1)
118      {
119        $this->build_nav_bar(CMONTH); // month
120      }
121      if ( count($page['chronology_date'])==2 )
122      {
123        $day_labels = range( 1, $this->get_all_days_in_month(
124                $page['chronology_date'][CYEAR] ,$page['chronology_date'][CMONTH] ) );
125        array_unshift($day_labels, 0);
126        unset( $day_labels[0] );
127        $this->build_nav_bar( CDAY, $day_labels ); // days
128      }
129      $this->build_next_prev();
130    }
131    return false;
132  }
133
134  /**
135   * Returns a sql WHERE subquery for the date field.
136   *
137   * @param int $max_levels (e.g. 2=only year and month)
138   * @return string
139   */
140  function get_date_where($max_levels=3)
141  {
142    global $page;
143
144    $date = $page['chronology_date'];
145    while (count($date)>$max_levels)
146    {
147      array_pop($date);
148    }
149    $res = '';
150    if (isset($date[CYEAR]) and $date[CYEAR]!=='any')
151    {
152      $b = $date[CYEAR] . '-';
153      $e = $date[CYEAR] . '-';
154      if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
155      {
156        $b .= sprintf('%02d-', $date[CMONTH]);
157        $e .= sprintf('%02d-', $date[CMONTH]);
158        if (isset($date[CDAY]) and $date[CDAY]!=='any')
159        {
160          $b .= sprintf('%02d', $date[CDAY]);
161          $e .= sprintf('%02d', $date[CDAY]);
162        }
163        else
164        {
165          $b .= '01';
166          $e .= $this->get_all_days_in_month($date[CYEAR], $date[CMONTH]);
167        }
168      }
169      else
170      {
171        $b .= '01-01';
172        $e .= '12-31';
173        if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
174        {
175          $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
176        }
177        if (isset($date[CDAY]) and $date[CDAY]!=='any')
178        {
179          $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
180        }
181      }
182      $res = " AND $this->date_field BETWEEN '$b' AND '$e 23:59:59'" . $res;
183    }
184    else
185    {
186      $res = ' AND '.$this->date_field.' IS NOT NULL';
187      if (isset($date[CMONTH]) and $date[CMONTH]!=='any')
188      {
189        $res .= ' AND '.$this->calendar_levels[CMONTH]['sql'].'='.$date[CMONTH];
190      }
191      if (isset($date[CDAY]) and $date[CDAY]!=='any')
192      {
193        $res .= ' AND '.$this->calendar_levels[CDAY]['sql'].'='.$date[CDAY];
194      }
195    }
196    return $res;
197  }
198
199  /**
200   * Returns an array with all the days in a given month.
201   *
202   * @param int $year
203   * @param int $month
204   * @return int[]
205   */
206  protected function get_all_days_in_month($year, $month)
207  {
208    $md= array(1=>31,28,31,30,31,30,31,31,30,31,30,31);
209
210    if ( is_numeric($year) and $month==2)
211    {
212      $nb_days = $md[2];
213      if ( ($year%4==0)  and ( ($year%100!=0) or ($year%400!=0) ) )
214      {
215        $nb_days++;
216      }
217    }
218    elseif ( is_numeric($month) )
219    {
220      $nb_days = $md[ $month ];
221    }
222    else
223    {
224      $nb_days = 31;
225    }
226    return $nb_days;
227  }
228
229  /**
230   * Build global calendar and assign the result in _$tpl_var_
231   *
232   * @param array $tpl_var
233   * @return bool
234   */
235  protected function build_global_calendar(&$tpl_var)
236  {
237    global $page;
238
239    assert( count($page['chronology_date']) == 0 );
240    $query='
241  SELECT '.pwg_db_get_date_YYYYMM($this->date_field).' as period,
242    COUNT(distinct id) as count';
243    $query.= $this->inner_sql;
244    $query.= $this->get_date_where();
245    $query.= '
246    GROUP BY period
247    ORDER BY '.pwg_db_get_year($this->date_field).' DESC, '.pwg_db_get_month($this->date_field).' ASC';
248
249    $result = pwg_query($query);
250    $items=array();
251    while ($row = pwg_db_fetch_assoc($result))
252    {
253      $y = substr($row['period'], 0, 4);
254      $m = (int)substr($row['period'], 4, 2);
255      if ( ! isset($items[$y]) )
256      {
257        $items[$y] = array('nb_images'=>0, 'children'=>array() );
258      }
259      $items[$y]['children'][$m] = $row['count'];
260      $items[$y]['nb_images'] += $row['count'];
261    }
262    //echo ('<pre>'. var_export($items, true) . '</pre>');
263    if (count($items)==1)
264    {// only one year exists so bail out to year view
265      list($y) = array_keys($items);
266      $page['chronology_date'][CYEAR] = $y;
267      return false;
268    }
269
270    global $lang;
271    foreach ( $items as $year=>$year_data)
272    {
273      $chronology_date = array( $year );
274      $url = duplicate_index_url( array('chronology_date'=>$chronology_date) );
275
276      $nav_bar = $this->get_nav_bar_from_items( $chronology_date,
277              $year_data['children'], false, false, $lang['month'] );
278
279      $tpl_var['calendar_bars'][] =
280        array(
281          'U_HEAD'  => $url,
282          'NB_IMAGES' => $year_data['nb_images'],
283          'HEAD_LABEL' => $year,
284          'items' => $nav_bar,
285        );
286    }
287
288    return true;
289  }
290
291  /**
292   * Build year calendar and assign the result in _$tpl_var_
293   *
294   * @param array $tpl_var
295   * @return bool
296   */
297  protected function build_year_calendar(&$tpl_var)
298  {
299    global $page;
300
301    assert( count($page['chronology_date']) == 1 );
302    $query='SELECT '.pwg_db_get_date_MMDD($this->date_field).' as period,
303              COUNT(DISTINCT id) as count';
304    $query.= $this->inner_sql;
305    $query.= $this->get_date_where();
306    $query.= '
307    GROUP BY period
308    ORDER BY period ASC';
309
310    $result = pwg_query($query);
311    $items=array();
312    while ($row = pwg_db_fetch_assoc($result))
313    {
314      $m = (int)substr($row['period'], 0, 2);
315      $d = substr($row['period'], 2, 2);
316      if ( ! isset($items[$m]) )
317      {
318        $items[$m] = array('nb_images'=>0, 'children'=>array() );
319      }
320      $items[$m]['children'][$d] = $row['count'];
321      $items[$m]['nb_images'] += $row['count'];
322    }
323    if (count($items)==1)
324    { // only one month exists so bail out to month view
325      list($m) = array_keys($items);
326      $page['chronology_date'][CMONTH] = $m;
327      return false;
328    }
329    global $lang;
330    foreach ( $items as $month=>$month_data)
331    {
332      $chronology_date = array( $page['chronology_date'][CYEAR], $month );
333      $url = duplicate_index_url( array('chronology_date'=>$chronology_date) );
334
335      $nav_bar = $this->get_nav_bar_from_items( $chronology_date,
336                       $month_data['children'], false );
337
338      $tpl_var['calendar_bars'][] =
339        array(
340          'U_HEAD'  => $url,
341          'NB_IMAGES' => $month_data['nb_images'],
342          'HEAD_LABEL' => $lang['month'][$month],
343          'items' => $nav_bar,
344        );
345    }
346
347    return true;
348  }
349
350  /**
351   * Build month calendar and assign the result in _$tpl_var_
352   *
353   * @param array $tpl_var
354   * @return bool
355   */
356  protected function build_month_calendar(&$tpl_var)
357  {
358    global $page, $lang, $conf;
359
360    $query='SELECT '.pwg_db_get_dayofmonth($this->date_field).' as period,
361              COUNT(DISTINCT id) as count';
362    $query.= $this->inner_sql;
363    $query.= $this->get_date_where();
364    $query.= '
365    GROUP BY period
366    ORDER BY period ASC';
367
368    $items=array();
369    $result = pwg_query($query);
370    while ($row = pwg_db_fetch_assoc($result))
371    {
372      $d = (int)$row['period'];
373      $items[$d] = array('nb_images'=>$row['count']);
374    }
375
376    foreach ( $items as $day=>$data)
377    {
378      $page['chronology_date'][CDAY]=$day;
379      $query = '
380  SELECT id, file,representative_ext,path,width,height,rotation, '.pwg_db_get_dayofweek($this->date_field).'-1 as dow';
381      $query.= $this->inner_sql;
382      $query.= $this->get_date_where();
383      $query.= '
384    ORDER BY '.DB_RANDOM_FUNCTION.'()
385    LIMIT 1';
386      unset ( $page['chronology_date'][CDAY] );
387
388      $row = pwg_db_fetch_assoc(pwg_query($query));
389      $derivative = new DerivativeImage(IMG_SQUARE, new SrcImage($row));
390      $items[$day]['derivative'] = $derivative;
391      $items[$day]['file'] = $row['file'];
392      $items[$day]['dow'] = $row['dow'];
393    }
394
395    if ( !empty($items) )
396    {
397      list($known_day) = array_keys($items);
398      $known_dow = $items[$known_day]['dow'];
399      $first_day_dow = ($known_dow-($known_day-1))%7;
400      if ($first_day_dow<0)
401      {
402        $first_day_dow += 7;
403      }
404      //first_day_dow = week day corresponding to the first day of this month
405      $wday_labels = $lang['day'];
406
407      if ('monday' == $conf['week_starts_on'])
408      {
409        if ($first_day_dow==0)
410        {
411          $first_day_dow = 6;
412        }
413        else
414        {
415          $first_day_dow -= 1;
416        }
417
418        $wday_labels[] = array_shift($wday_labels);
419      }
420
421      list($cell_width, $cell_height) = ImageStdParams::get_by_type(IMG_SQUARE)->sizing->ideal_size;
422
423      $tpl_weeks    = array();
424      $tpl_crt_week = array();
425
426      //fill the empty days in the week before first day of this month
427      for ($i=0; $i<$first_day_dow; $i++)
428      {
429        $tpl_crt_week[] = array();
430      }
431
432      for ( $day = 1;
433            $day <= $this->get_all_days_in_month(
434              $page['chronology_date'][CYEAR], $page['chronology_date'][CMONTH]
435                );
436            $day++)
437      {
438        $dow = ($first_day_dow + $day-1)%7;
439        if ($dow==0 and $day!=1)
440        {
441          $tpl_weeks[]    = $tpl_crt_week; // add finished week to week list
442          $tpl_crt_week   = array(); // start new week
443        }
444
445        if ( !isset($items[$day]) )
446        {// empty day
447          $tpl_crt_week[]   =
448            array(
449                'DAY' => $day
450              );
451        }
452        else
453        {
454          $url = duplicate_index_url(
455              array(
456                'chronology_date' =>
457                  array(
458                    $page['chronology_date'][CYEAR],
459                    $page['chronology_date'][CMONTH],
460                    $day
461                  )
462              )
463            );
464
465          $tpl_crt_week[]   =
466            array(
467                'DAY'         => $day,
468                'DOW'         => $dow,
469                'NB_ELEMENTS' => $items[$day]['nb_images'],
470                'IMAGE'       => $items[$day]['derivative']->get_url(),
471                'U_IMG_LINK'  => $url,
472                'IMAGE_ALT'   => $items[$day]['file'],
473              );
474        }
475      }
476      //fill the empty days in the week after the last day of this month
477      while ( $dow<6 )
478      {
479        $tpl_crt_week[] = array();
480        $dow++;
481      }
482      $tpl_weeks[]    = $tpl_crt_week;
483
484      $tpl_var['month_view'] =
485          array(
486             'CELL_WIDTH'   => $cell_width,
487             'CELL_HEIGHT' => $cell_height,
488             'wday_labels' => $wday_labels,
489             'weeks' => $tpl_weeks,
490            );
491    }
492
493    return true;
494  }
495}
496
497?>
Note: See TracBrowser for help on using the repository browser.