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

Last change on this file since 4325 was 4325, checked in by nikrou, 14 years ago

Feature 1244 resolved
Replace all mysql functions in core code by ones independant of database engine

Fix small php code synxtax : hash must be accessed with [ ] and not { }.

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