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

Last change on this file since 11558 was 8728, checked in by plg, 13 years ago

Happy new year 2011

Change "Piwigo - a PHP based picture gallery" into "Piwigo - a PHP based photo gallery"

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