source: branches/2.0/include/functions_html.inc.php @ 21659

Last change on this file since 21659 was 5938, checked in by laurent.duretz, 15 years ago

Issue 1521 : report trunk on branch 2.0

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 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
24function get_icon($date, $is_child_date = false)
25{
26  global $cache, $user;
27
28  if (empty($date))
29  {
30    return '';
31  }
32
33  if (isset($cache['get_icon'][$date]))
34  {
35    if (! $cache['get_icon'][$date] )
36      return '';
37    return $cache['get_icon']['_icons_'][$is_child_date];
38  }
39
40  if (!isset($cache['get_icon']['sql_recent_date']))
41  {
42    // Use MySql date in order to standardize all recent "actions/queries"
43    list($cache['get_icon']['sql_recent_date']) =
44      mysql_fetch_array(pwg_query('select SUBDATE(
45      CURRENT_DATE,INTERVAL '.$user['recent_period'].' DAY)'));
46  }
47
48  $cache['get_icon'][$date] = false;
49  if ( $date > $cache['get_icon']['sql_recent_date'] )
50  {
51    if ( !isset($cache['get_icon']['_icons_'] ) )
52    {
53      $icons = array(false => 'recent', true => 'recent_by_child' );
54      $title = sprintf(
55        l10n('elements posted during the last %d days'),
56        $user['recent_period']
57        );
58      foreach ($icons as $key => $icon)
59      {
60        $icon_url = get_themeconf('icon_dir').'/'.$icon.'.png';
61        $size = getimagesize( PHPWG_ROOT_PATH.$icon_url );
62        $icon_url = get_root_url().$icon_url;
63        $output = '<img title="'.$title.'" src="'.$icon_url.'" class="icon" style="border:0;';
64        $output.= 'height:'.$size[1].'px;width:'.$size[0].'px" alt="(!)" />';
65        $cache['get_icon']['_icons_'][$key] = $output;
66      }
67    }
68    $cache['get_icon'][$date] = true;
69  }
70
71  if (! $cache['get_icon'][$date] )
72    return '';
73  return $cache['get_icon']['_icons_'][$is_child_date];
74}
75
76function create_navigation_bar(
77  $url, $nb_element, $start, $nb_element_page, $clean_url = false
78  )
79{
80  global $conf;
81
82  $pages_around = $conf['paginate_pages_around'];
83  $start_str = $clean_url ? '/start-' :
84    ( ( strpos($url, '?')===false ? '?':'&amp;') . 'start=' );
85
86  $navbar = '';
87
88  // current page detection
89  if (!isset($start)
90      or !is_numeric($start)
91      or (is_numeric($start) and $start < 0))
92  {
93    $start = 0;
94  }
95
96  // navigation bar useful only if more than one page to display !
97  if ($nb_element > $nb_element_page)
98  {
99    // current page and last page
100    $cur_page = ceil($start / $nb_element_page) + 1;
101    $maximum = ceil($nb_element / $nb_element_page);
102
103    // link to first page ?
104    if ($cur_page != 1)
105    {
106      $navbar.=
107        '<a href="'.$url.'" rel="first">'
108        .l10n('first_page')
109        .'</a>';
110    }
111    else
112    {
113      $navbar.= l10n('first_page');
114    }
115    $navbar.= ' | ';
116    // link on previous page ?
117    if ($start != 0)
118    {
119      $previous = $start - $nb_element_page;
120
121      $navbar.=
122        '<a href="'
123        .$url.($previous > 0 ? $start_str.$previous : '')
124        .'" rel="prev">'
125        .l10n('previous_page')
126        .'</a>';
127    }
128    else
129    {
130      $navbar.= l10n('previous_page');
131    }
132    $navbar.= ' |';
133
134    if ($cur_page > $pages_around + 1)
135    {
136      $navbar.= '&nbsp;<a href="'.$url.'">1</a>';
137
138      if ($cur_page > $pages_around + 2)
139      {
140        $navbar.= ' ...';
141      }
142    }
143
144    // inspired from punbb source code
145    for ($i = $cur_page - $pages_around, $stop = $cur_page + $pages_around + 1;
146         $i < $stop;
147         $i++)
148    {
149      if ($i < 1 or $i > $maximum)
150      {
151        continue;
152      }
153      else if ($i != $cur_page)
154      {
155        $temp_start = ($i - 1) * $nb_element_page;
156
157        $navbar.=
158          '&nbsp;'
159          .'<a href="'.$url
160          .($temp_start > 0 ? $start_str.$temp_start : '')
161          .'">'
162          .$i
163          .'</a>';
164      }
165      else
166      {
167        $navbar.=
168          '&nbsp;'
169          .'<span class="pageNumberSelected">'
170          .$i
171          .'</span>';
172      }
173    }
174
175    if ($cur_page < ($maximum - $pages_around))
176    {
177      $temp_start = ($maximum - 1) * $nb_element_page;
178
179      if ($cur_page < ($maximum - $pages_around - 1))
180      {
181        $navbar.= ' ...';
182      }
183
184      $navbar.= ' <a href="'.$url.$start_str.$temp_start.'">'.$maximum.'</a>';
185    }
186
187    $navbar.= ' | ';
188    // link on next page ?
189    if ($nb_element > $nb_element_page
190        and $start + $nb_element_page < $nb_element)
191    {
192      $next = $start + $nb_element_page;
193
194      $navbar.=
195        '<a href="'.$url.$start_str.$next.'" rel="next">'
196        .l10n('next_page')
197        .'</a>';
198    }
199    else
200    {
201      $navbar.= l10n('next_page');
202    }
203
204    $navbar.= ' | ';
205    // link to last page ?
206    if ($cur_page != $maximum)
207    {
208      $temp_start = ($maximum - 1) * $nb_element_page;
209
210      $navbar.=
211        '<a href="'.$url.$start_str.$temp_start.'" rel="last">'
212        .l10n('last_page')
213        .'</a>';
214    }
215    else
216    {
217      $navbar.= l10n('last_page');
218    }
219  }
220  return $navbar;
221}
222
223/**
224 * returns the list of categories as a HTML string
225 *
226 * categories string returned contains categories as given in the input
227 * array $cat_informations. $cat_informations array must be an array
228 * of array( id=>?, name=>?, permalink=>?). If url input parameter is null,
229 * returns only the categories name without links.
230 *
231 * @param array cat_informations
232 * @param string url
233 * @param boolean replace_space
234 * @return string
235 */
236function get_cat_display_name($cat_informations,
237                              $url = '',
238                              $replace_space = true)
239{
240  global $conf;
241
242  $output = '';
243  $is_first = true;
244
245  foreach ($cat_informations as $cat)
246  {
247    is_array($cat) or trigger_error(
248        'get_cat_display_name wrong type for category ', E_USER_WARNING
249      );
250
251    $cat['name'] = trigger_event(
252      'render_category_name',
253      $cat['name'],
254      'get_cat_display_name'
255      );
256
257    if ($is_first)
258    {
259      $is_first=false;
260    }
261    else
262    {
263      $output.= $conf['level_separator'];
264    }
265
266    if ( !isset($url) )
267    {
268      $output.= $cat['name'];
269    }
270    elseif ($url == '')
271    {
272      $output.= '<a href="'
273            .make_index_url(
274                array(
275                  'category' => $cat,
276                  )
277              )
278            .'">';
279      $output.= $cat['name'].'</a>';
280    }
281    else
282    {
283      $output.= '<a href="'.PHPWG_ROOT_PATH.$url.$cat['id'].'">';
284      $output.= $cat['name'].'</a>';
285    }
286  }
287  if ($replace_space)
288  {
289    return replace_space($output);
290  }
291  else
292  {
293    return $output;
294  }
295}
296
297/**
298 * returns the list of categories as a HTML string, with cache of names
299 *
300 * categories string returned contains categories as given in the input
301 * array $cat_informations. $uppercats is the list of category ids to
302 * display in the right order. If url input parameter is empty, returns only
303 * the categories name without links.
304 *
305 * @param string uppercats
306 * @param string url
307 * @param boolean replace_space
308 * @return string
309 */
310function get_cat_display_name_cache($uppercats,
311                                    $url = '',
312                                    $replace_space = true)
313{
314  global $cache, $conf;
315
316  if (!isset($cache['cat_names']))
317  {
318    $query = '
319SELECT id, name, permalink
320  FROM '.CATEGORIES_TABLE.'
321;';
322    $cache['cat_names'] = hash_from_query($query, 'id');
323  }
324
325  $output = '';
326  $is_first = true;
327  foreach (explode(',', $uppercats) as $category_id)
328  {
329    $cat = $cache['cat_names'][$category_id];
330
331    $cat['name'] = trigger_event(
332      'render_category_name',
333      $cat['name'],
334      'get_cat_display_name_cache'
335      );
336
337    if ($is_first)
338    {
339      $is_first = false;
340    }
341    else
342    {
343      $output.= $conf['level_separator'];
344    }
345
346    if ( !isset($url) )
347    {
348      $output.= $cat['name'];
349    }
350    elseif ($url == '')
351    {
352      $output.= '
353<a href="'
354      .make_index_url(
355          array(
356            'category' => $cat,
357            )
358        )
359      .'">'.$cat['name'].'</a>';
360    }
361    else
362    {
363      $output.= '
364<a href="'.PHPWG_ROOT_PATH.$url.$category_id.'">'.$cat['name'].'</a>';
365    }
366  }
367  if ($replace_space)
368  {
369    return replace_space($output);
370  }
371  else
372  {
373    return $output;
374  }
375}
376
377/**
378 * returns the HTML code for a category item in the menu (for the main page)
379 *
380 * HTML code generated uses logical list tags ul and each category is an
381 * item li. The paramter given is the category informations as an array,
382 * used keys are : id, name, nb_images, max_date_last, date_last
383 * count_images, count_categories
384 *
385 * @param array categories
386 * @return string
387 */
388function get_html_menu_category($categories, $selected_category)
389{
390  $ref_level = 0;
391  $level = 0;
392
393  $menu = trigger_event('get_html_menu_category', '',
394            $categories, $selected_category);
395  if (strlen($menu))
396  {
397    return $menu;
398  }
399
400  foreach ($categories as $category)
401  {
402    $level = substr_count($category['global_rank'], '.') + 1;
403    if ($level > $ref_level)
404    {
405      $menu.= "\n<ul>";
406    }
407    else if ($level == $ref_level)
408    {
409      $menu.= "\n</li>";
410    }
411    else if ($level < $ref_level)
412    {
413      // we may have to close more than one level at the same time...
414      $menu.= "\n</li>";
415      $menu.= str_repeat("\n</ul></li>",($ref_level-$level));
416    }
417    $ref_level = $level;
418
419    $menu.= "\n\n".'<li';
420    if ($category['id'] == @$selected_category['id'])
421    {
422      $menu.= ' class="selected"';
423    }
424    $menu.= '>';
425
426    $url = make_index_url(
427            array(
428              'category' => $category
429              )
430            );
431
432    $title = get_display_images_count
433                (
434                  $category['nb_images'],
435                  $category['count_images'],
436                  $category['count_categories'],
437                  false,
438                  ' / '
439                );
440
441    $menu.= '<a href="'.$url.'"';
442    if ($selected_category!=null
443        and $category['id'] == $selected_category['id_uppercat'])
444    {
445      $menu.= ' rel="up"';
446    }
447    $menu.= ' title="'.$title.'">';
448    $menu.= trigger_event(
449      'render_category_name',
450      $category['name'],
451      'get_html_menu_category'
452      );
453    $menu.= '</a>';
454
455    if ( $category['count_images']>0 )
456    {// at least one direct or indirect image
457      $menu.= "\n".'<span class="';
458      // at least one image in this category -> class menuInfoCat
459      $menu.= ($category['nb_images'] > 0 ? "menuInfoCat"
460                                          : "menuInfoCatByChild").'"';
461      $menu.= ' title=" '.$title.'">';
462      // show total number of images
463      $menu.= '['.$category['count_images'].']';
464      $menu.= '</span>';
465    }
466    $child_date_last = @$category['max_date_last']> @$category['date_last'];
467    $menu.= get_icon($category['max_date_last'], $child_date_last);
468  }
469
470  $menu.= str_repeat("\n</li></ul>",($level));
471
472  return $menu;
473}
474
475/**
476 * returns HTMLized comment contents retrieved from database
477 *
478 * newlines becomes br tags, _word_ becomes underline, /word/ becomes
479 * italic, *word* becomes bolded
480 *
481 * @param string content
482 * @return string
483 */
484function parse_comment_content($content)
485{
486  $pattern = '/(https?:\/\/\S*)/';
487  $replacement = '<a href="$1" rel="nofollow">$1</a>';
488  $content = preg_replace($pattern, $replacement, $content);
489
490  $content = nl2br($content);
491
492  // replace _word_ by an underlined word
493  $pattern = '/\b_(\S*)_\b/';
494  $replacement = '<span style="text-decoration:underline;">$1</span>';
495  $content = preg_replace($pattern, $replacement, $content);
496
497  // replace *word* by a bolded word
498  $pattern = '/\b\*(\S*)\*\b/';
499  $replacement = '<span style="font-weight:bold;">$1</span>';
500  $content = preg_replace($pattern, $replacement, $content);
501
502  // replace /word/ by an italic word
503  $pattern = "/\/(\S*)\/(\s)/";
504  $replacement = '<span style="font-style:italic;">$1$2</span>';
505  $content = preg_replace($pattern, $replacement, $content);
506
507  $content = '<div>'.$content.'</div>';
508  return $content;
509}
510
511function get_cat_display_name_from_id($cat_id,
512                                      $url = '',
513                                      $replace_space = true)
514{
515  $cat_info = get_cat_info($cat_id);
516  return get_cat_display_name($cat_info['upper_names'], $url, $replace_space);
517}
518
519/**
520 * Returns an HTML list of tags. It can be a multi select field or a list of
521 * checkboxes.
522 *
523 * @param string HTML field name
524 * @param array selected tag ids
525 * @return array
526 */
527function get_html_tag_selection(
528  $tags,
529  $fieldname,
530  $selecteds = array(),
531  $forbidden_categories = null
532  )
533{
534  global $conf;
535
536  if (count ($tags) == 0 )
537  {
538    return '';
539  }
540  $output = '<ul class="tagSelection">';
541  foreach ($tags as $tag)
542  {
543    $output.=
544      '<li>'
545      .'<label>'
546      .'<input type="checkbox" name="'.$fieldname.'[]"'
547      .' value="'.$tag['id'].'"'
548      ;
549
550    if (in_array($tag['id'], $selecteds))
551    {
552      $output.= ' checked="checked"';
553    }
554
555    $output.=
556      ' />'
557      .' '. $tag['name']
558      .'</label>'
559      .'</li>'
560      ."\n"
561      ;
562  }
563  $output.= '</ul>';
564
565  return $output;
566}
567
568function name_compare($a, $b)
569{
570  return strcmp(strtolower($a['name']), strtolower($b['name']));
571}
572
573function tag_alpha_compare($a, $b)
574{
575  return strcmp(strtolower($a['url_name']), strtolower($b['url_name']));
576}
577
578/**
579 * exits the current script (either exit or redirect)
580 */
581function access_denied()
582{
583  global $user;
584
585  $login_url =
586      get_root_url().'identification.php?redirect='
587      .urlencode(urlencode($_SERVER['REQUEST_URI']));
588
589  set_status_header(401);
590  if ( isset($user) and !is_a_guest() )
591  {
592    echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
593    echo '<div style="text-align:center;">'.l10n('access_forbiden').'<br />';
594    echo '<a href="'.get_root_url().'identification.php">'.l10n('identification').'</a>&nbsp;';
595    echo '<a href="'.make_index_url().'">'.l10n('home').'</a></div>';
596    echo str_repeat( ' ', 512); //IE6 doesn't error output if below a size
597    exit();
598  }
599  else
600  {
601    redirect_html($login_url);
602  }
603}
604
605/**
606 * exits the current script with 403 code
607 * @param string msg a message to display
608 * @param string alternate_url redirect to this url
609 */
610function page_forbidden($msg, $alternate_url=null)
611{
612  set_status_header(403);
613  if ($alternate_url==null)
614    $alternate_url = make_index_url();
615  redirect_html( $alternate_url,
616    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
617<h1 style="text-align:left; font-size:36px;">Forbidden</h1><br/>'
618.$msg.'</div>',
619    5 );
620}
621
622/**
623 * exits the current script with 400 code
624 * @param string msg a message to display
625 * @param string alternate_url redirect to this url
626 */
627function bad_request($msg, $alternate_url=null)
628{
629  set_status_header(400);
630  if ($alternate_url==null)
631    $alternate_url = make_index_url();
632  redirect_html( $alternate_url,
633    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
634<h1 style="text-align:left; font-size:36px;">Bad request</h1><br/>'
635.$msg.'</div>',
636    5 );
637}
638
639/**
640 * exits the current script with 404 code when a page cannot be found
641 * @param string msg a message to display
642 * @param string alternate_url redirect to this url
643 */
644function page_not_found($msg, $alternate_url=null)
645{
646  set_status_header(404);
647  if ($alternate_url==null)
648    $alternate_url = make_index_url();
649  redirect_html( $alternate_url,
650    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
651<h1 style="text-align:left; font-size:36px;">Page not found</h1><br/>'
652.$msg.'</div>',
653    5 );
654}
655
656/**
657 * exits the current script with 500 http code
658 * this method can be called at any time (does not use template/language/user etc...)
659 * @param string msg a message to display
660 */
661function fatal_error($msg)
662{
663  $btrace_msg = '';
664  if (function_exists('debug_backtrace'))
665  {
666    $bt = debug_backtrace();
667    for ($i=1; $i<count($bt); $i++)
668    {
669      $class = isset($bt[$i]['class']) ? (@$bt[$i]['class'].'::') : '';
670      $btrace_msg .= "#$i\t".$class.@$bt[$i]['function'].' '.@$bt[$i]['file']."(".@$bt[$i]['line'].")\n";
671    }
672    $btrace_msg = trim($btrace_msg);
673    $msg .= "\n";
674  }
675
676  $display = "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
677<h1>Piwigo encountered a non recoverable error</h1>
678<pre style='font-size:larger;background:white;color:red;padding:1em;margin:0;clear:both;display:block;width:auto;height:auto;overflow:auto'>
679<b>$msg</b>
680$btrace_msg
681</pre>\n";
682
683  @set_status_header(500);
684  echo $display.str_repeat( ' ', 300); //IE6 doesn't error output if below a size
685
686  if ( function_exists('ini_set') )
687  {// if possible turn off error display (we display it)
688    ini_set('display_errors', false);
689  }
690  error_reporting( E_ALL );
691  trigger_error( strip_tags($msg).$btrace_msg, E_USER_ERROR );
692  die(0); // just in case
693}
694
695/* returns the title to be displayed above thumbnails on tag page
696 */
697function get_tags_content_title()
698{
699  global $page;
700  $title = count($page['tags']) > 1 ? l10n('Tags') : l10n('Tag');
701  $title.= ' ';
702
703  for ($i=0; $i<count($page['tags']); $i++)
704  {
705    $title.= $i>0 ? ' + ' : '';
706
707    $title.=
708      '<a href="'
709      .make_index_url(
710        array(
711          'tags' => array( $page['tags'][$i] )
712          )
713        )
714      .'" title="'
715      .l10n('See elements linked to this tag only')
716      .'">'
717      .$page['tags'][$i]['name']
718      .'</a>';
719
720    if ( count($page['tags'])>2 )
721    {
722      $other_tags = $page['tags'];
723      unset ( $other_tags[$i] );
724      $title.=
725        '<a href="'
726        .make_index_url(
727          array(
728            'tags' => $other_tags
729            )
730          )
731        .'" style="border:none;" title="'
732        .l10n('remove this tag')
733        .'"><img src="'
734        .get_root_url().get_themeconf('icon_dir').'/remove_s.png'
735        .'" alt="x" style="vertical-align:bottom;" class="button"/>'
736        .'</a>';
737    }
738
739  }
740  return $title;
741}
742
743/**
744  Sets the http status header (200,401,...)
745 */
746function set_status_header($code, $text='')
747{
748  if (empty($text))
749  {
750    switch ($code)
751    {
752      case 200: $text='OK';break;
753      case 301: $text='Moved permanently';break;
754      case 302: $text='Moved temporarily';break;
755      case 304: $text='Not modified';break;
756      case 400: $text='Bad request';break;
757      case 401: $text='Authorization required';break;
758      case 403: $text='Forbidden';break;
759      case 404: $text='Not found';break;
760      case 500: $text='Server error';break;
761      case 501: $text='Not implemented';break;
762      case 503: $text='Service unavailable';break;
763    }
764  }
765        $protocol = $_SERVER["SERVER_PROTOCOL"];
766        if ( ('HTTP/1.1' != $protocol) && ('HTTP/1.0' != $protocol) )
767                $protocol = 'HTTP/1.0';
768
769        if ( version_compare( phpversion(), '4.3.0', '>=' ) )
770  {
771                header( "$protocol $code $text", true, $code );
772        }
773  else
774  {
775                header( "$protocol $code $text" );
776        }
777  trigger_action('set_status_header', $code, $text);
778}
779
780/** returns the category comment for rendering in html textual mode (subcatify)
781 * this is an event handler. don't call directly
782 */
783function render_category_literal_description($desc)
784{
785  return strip_tags($desc, '<span><p><a><br><b><i><small><big><strong><em>');
786}
787
788/** returns the argument_ids array with new sequenced keys based on related
789 * names. Sequence is not case sensitive.
790 * Warning: By definition, this function breaks original keys
791 */
792function order_by_name($element_ids,$name)
793{
794  $ordered_element_ids = array();
795  foreach ($element_ids as $k_id => $element_id)
796  {
797    $key = strtolower($name[$element_id]) .'-'. $name[$element_id] .'-'. $k_id;
798    $ordered_element_ids[$key] = $element_id;
799  }
800  ksort($ordered_element_ids);
801  return $ordered_element_ids;
802}
803
804/*event handler for menu*/
805function register_default_menubar_blocks( $menu_ref_arr )
806{
807  $menu = & $menu_ref_arr[0];
808  if ($menu->get_id() != 'menubar')
809    return;
810  $menu->register_block( new RegisteredBlock( 'mbLinks', 'Links', 'piwigo'));
811  $menu->register_block( new RegisteredBlock( 'mbCategories', 'Categories', 'piwigo'));
812  $menu->register_block( new RegisteredBlock( 'mbTags', 'Related tags', 'piwigo'));
813  $menu->register_block( new RegisteredBlock( 'mbSpecials', 'special_categories', 'piwigo'));
814  $menu->register_block( new RegisteredBlock( 'mbMenu', 'title_menu', 'piwigo'));
815  $menu->register_block( new RegisteredBlock( 'mbIdentification', 'identification', 'piwigo') );
816}
817
818?>
Note: See TracBrowser for help on using the repository browser.