source: trunk/include/functions_html.inc.php @ 17748

Revision 17748, 15.8 KB checked in by rvelices, 7 years ago (diff)

bug 2735: fix/improve non latin language tags

  1. non latin tags (greek/cyrillic...) are not sorted case-insesitive and group by letter view in tag list is not case insesitive
  2. quick searching tag names does not perform correctly accent folding (e.g. Köln and Koln do not match) and case insesitivity for non latin letters
  3. missing from remove_accents characters in romanian language (Latin Extended-B) ? c8 98 = LATIN CAPITAL LETTER S WITH COMMA BELOW ? c8 99 = LATIN SMALL LETTER S WITH COMMA BELOW ? c8 9a = LATIN CAPITAL LETTER T WITH COMMA BELOW ? c8 9b = LATIN SMALL LETTER T WITH COMMA BELOW
  4. str2url allow non latin letters in output only if the input does not contain any valid lating letter/digit. we should always allow non latin letters in output
  • Property svn:eol-style set to LF
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2012 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 * returns the list of categories as a HTML string
26 *
27 * categories string returned contains categories as given in the input
28 * array $cat_informations. $cat_informations array must be an array
29 * of array( id=>?, name=>?, permalink=>?). If url input parameter is null,
30 * returns only the categories name without links.
31 *
32 * @param array cat_informations
33 * @param string url
34 * @param boolean replace_space
35 * @return string
36 */
37function get_cat_display_name($cat_informations,
38                              $url = '',
39                              $replace_space = true)
40{
41  global $conf;
42
43  //$output = '<a href="'.get_absolute_root_url().$conf['home_page'].'">'.l10n('Home').'</a>';
44  $output = '';
45  $is_first=true;
46
47  foreach ($cat_informations as $cat)
48  {
49    is_array($cat) or trigger_error(
50        'get_cat_display_name wrong type for category ', E_USER_WARNING
51      );
52
53    $cat['name'] = trigger_event(
54      'render_category_name',
55      $cat['name'],
56      'get_cat_display_name'
57      );
58
59    if ($is_first)
60    {
61      $is_first=false;
62    }
63    else
64    {
65      $output.= $conf['level_separator'];
66    }
67
68    if ( !isset($url) )
69    {
70      $output.= $cat['name'];
71    }
72    elseif ($url == '')
73    {
74      $output.= '<a href="'
75            .make_index_url(
76                array(
77                  'category' => $cat,
78                  )
79              )
80            .'">';
81      $output.= $cat['name'].'</a>';
82    }
83    else
84    {
85      $output.= '<a href="'.PHPWG_ROOT_PATH.$url.$cat['id'].'">';
86      $output.= $cat['name'].'</a>';
87    }
88  }
89  if ($replace_space)
90  {
91    return replace_space($output);
92  }
93  else
94  {
95    return $output;
96  }
97}
98
99/**
100 * returns the list of categories as a HTML string, with cache of names
101 *
102 * categories string returned contains categories as given in the input
103 * array $cat_informations. $uppercats is the list of category ids to
104 * display in the right order. If url input parameter is empty, returns only
105 * the categories name without links.
106 *
107 * @param string uppercats
108 * @param string url
109 * @param boolean replace_space
110 * @return string
111 */
112function get_cat_display_name_cache($uppercats,
113                                    $url = '',
114                                    $replace_space = true,
115                                    $single_link = false,
116                                    $link_class = null)
117{
118  global $cache, $conf;
119
120  if (!isset($cache['cat_names']))
121  {
122    $query = '
123SELECT id, name, permalink
124  FROM '.CATEGORIES_TABLE.'
125;';
126    $cache['cat_names'] = hash_from_query($query, 'id');
127  }
128
129  $output = '';
130  if ($single_link)
131  {
132    $single_url = get_root_url().$url.array_pop(explode(',', $uppercats));
133    $output.= '<a href="'.$single_url.'"';
134    if (isset($link_class))
135    {
136      $output.= ' class="'.$link_class.'"';
137    }
138    $output.= '>';
139  }
140  $is_first = true;
141  foreach (explode(',', $uppercats) as $category_id)
142  {
143    $cat = $cache['cat_names'][$category_id];
144
145    $cat['name'] = trigger_event(
146      'render_category_name',
147      $cat['name'],
148      'get_cat_display_name_cache'
149      );
150
151    if ($is_first)
152    {
153      $is_first = false;
154    }
155    else
156    {
157      $output.= $conf['level_separator'];
158    }
159
160    if ( !isset($url) or $single_link )
161    {
162      $output.= $cat['name'];
163    }
164    elseif ($url == '')
165    {
166      $output.= '
167<a href="'
168      .make_index_url(
169          array(
170            'category' => $cat,
171            )
172        )
173      .'">'.$cat['name'].'</a>';
174    }
175    else
176    {
177      $output.= '
178<a href="'.PHPWG_ROOT_PATH.$url.$category_id.'">'.$cat['name'].'</a>';
179    }
180  }
181
182  if ($single_link and isset($single_url))
183  {
184    $output.= '</a>';
185  }
186
187  if ($replace_space)
188  {
189    return replace_space($output);
190  }
191  else
192  {
193    return $output;
194  }
195}
196
197/**
198 * returns HTMLized comment contents retrieved from database
199 *
200 * newlines becomes br tags, _word_ becomes underline, /word/ becomes
201 * italic, *word* becomes bolded
202 *
203 * @param string content
204 * @return string
205 */
206function render_comment_content($content)
207{
208  $content = htmlspecialchars($content);
209  $pattern = '/(https?:\/\/\S*)/';
210  $replacement = '<a href="$1" rel="nofollow">$1</a>';
211  $content = preg_replace($pattern, $replacement, $content);
212
213  $content = nl2br($content);
214
215  // replace _word_ by an underlined word
216  $pattern = '/\b_(\S*)_\b/';
217  $replacement = '<span style="text-decoration:underline;">$1</span>';
218  $content = preg_replace($pattern, $replacement, $content);
219
220  // replace *word* by a bolded word
221  $pattern = '/\b\*(\S*)\*\b/';
222  $replacement = '<span style="font-weight:bold;">$1</span>';
223  $content = preg_replace($pattern, $replacement, $content);
224
225  // replace /word/ by an italic word
226  $pattern = "/\/(\S*)\/(\s)/";
227  $replacement = '<span style="font-style:italic;">$1$2</span>';
228  $content = preg_replace($pattern, $replacement, $content);
229
230  return $content;
231}
232
233function get_cat_display_name_from_id($cat_id,
234                                      $url = '',
235                                      $replace_space = true)
236{
237  $cat_info = get_cat_info($cat_id);
238  return get_cat_display_name($cat_info['upper_names'], $url, $replace_space);
239}
240
241/**
242 * Returns an HTML list of tags. It can be a multi select field or a list of
243 * checkboxes.
244 *
245 * @param string HTML field name
246 * @param array selected tag ids
247 * @return array
248 */
249function get_html_tag_selection(
250  $tags,
251  $fieldname,
252  $selecteds = array(),
253  $forbidden_categories = null
254  )
255{
256  global $conf;
257
258  if (count ($tags) == 0 )
259  {
260    return '';
261  }
262  $output = '<ul class="tagSelection">';
263  foreach ($tags as $tag)
264  {
265    $output.=
266      '<li>'
267      .'<label>'
268      .'<input type="checkbox" name="'.$fieldname.'[]"'
269      .' value="'.$tag['id'].'"'
270      ;
271
272    if (in_array($tag['id'], $selecteds))
273    {
274      $output.= ' checked="checked"';
275    }
276
277    $output.=
278      '> '
279      .$tag['name']
280      .'</label>'
281      .'</li>'
282      ."\n"
283      ;
284  }
285  $output.= '</ul>';
286
287  return $output;
288}
289
290function name_compare($a, $b)
291{
292  return strcmp(strtolower($a['name']), strtolower($b['name']));
293}
294
295function tag_alpha_compare($a, $b)
296{
297  global $cache;
298
299  foreach (array($a, $b) as $tag)
300  {
301    if (!isset($cache[__FUNCTION__][ $tag['name'] ]))
302    {
303      $cache[__FUNCTION__][ $tag['name'] ] = transliterate($tag['name']);
304    }
305  }
306
307  return strcmp($cache[__FUNCTION__][ $a['name'] ], $cache[__FUNCTION__][ $b['name'] ]);
308}
309
310/**
311 * exits the current script (either exit or redirect)
312 */
313function access_denied()
314{
315  global $user;
316
317  $login_url =
318      get_root_url().'identification.php?redirect='
319      .urlencode(urlencode($_SERVER['REQUEST_URI']));
320
321  set_status_header(401);
322  if ( isset($user) and !is_a_guest() )
323  {
324    echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
325    echo '<div style="text-align:center;">'.l10n('You are not authorized to access the requested page').'<br>';
326    echo '<a href="'.get_root_url().'identification.php">'.l10n('Identification').'</a>&nbsp;';
327    echo '<a href="'.make_index_url().'">'.l10n('Home').'</a></div>';
328    echo str_repeat( ' ', 512); //IE6 doesn't error output if below a size
329    exit();
330  }
331  else
332  {
333    redirect_html($login_url);
334  }
335}
336
337/**
338 * exits the current script with 403 code
339 * @param string msg a message to display
340 * @param string alternate_url redirect to this url
341 */
342function page_forbidden($msg, $alternate_url=null)
343{
344  set_status_header(403);
345  if ($alternate_url==null)
346    $alternate_url = make_index_url();
347  redirect_html( $alternate_url,
348    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
349<h1 style="text-align:left; font-size:36px;">'.l10n('Forbidden').'</h1><br>'
350.$msg.'</div>',
351    5 );
352}
353
354/**
355 * exits the current script with 400 code
356 * @param string msg a message to display
357 * @param string alternate_url redirect to this url
358 */
359function bad_request($msg, $alternate_url=null)
360{
361  set_status_header(400);
362  if ($alternate_url==null)
363    $alternate_url = make_index_url();
364  redirect_html( $alternate_url,
365    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
366<h1 style="text-align:left; font-size:36px;">'.l10n('Bad request').'</h1><br>'
367.$msg.'</div>',
368    5 );
369}
370
371/**
372 * exits the current script with 404 code when a page cannot be found
373 * @param string msg a message to display
374 * @param string alternate_url redirect to this url
375 */
376function page_not_found($msg, $alternate_url=null)
377{
378  set_status_header(404);
379  if ($alternate_url==null)
380    $alternate_url = make_index_url();
381  redirect_html( $alternate_url,
382    '<div style="text-align:left; margin-left:5em;margin-bottom:5em;">
383<h1 style="text-align:left; font-size:36px;">'.l10n('Page not found').'</h1><br>'
384.$msg.'</div>',
385    5 );
386}
387
388/**
389 * exits the current script with 500 http code
390 * this method can be called at any time (does not use template/language/user etc...)
391 * @param string msg a message to display
392 */
393function fatal_error($msg, $title=null, $show_trace=true)
394{
395  if (empty($title))
396  {
397    $title = l10n('Piwigo encountered a non recoverable error');
398  }
399
400  $btrace_msg = '';
401  if ($show_trace and function_exists('debug_backtrace'))
402  {
403    $bt = debug_backtrace();
404    for ($i=1; $i<count($bt); $i++)
405    {
406      $class = isset($bt[$i]['class']) ? (@$bt[$i]['class'].'::') : '';
407      $btrace_msg .= "#$i\t".$class.@$bt[$i]['function'].' '.@$bt[$i]['file']."(".@$bt[$i]['line'].")\n";
408    }
409    $btrace_msg = trim($btrace_msg);
410    $msg .= "\n";
411  }
412
413  $display = "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
414<h1>$title</h1>
415<pre style='font-size:larger;background:white;color:red;padding:1em;margin:0;clear:both;display:block;width:auto;height:auto;overflow:auto'>
416<b>$msg</b>
417$btrace_msg
418</pre>\n";
419
420  @set_status_header(500);
421  echo $display.str_repeat( ' ', 300); //IE6 doesn't error output if below a size
422
423  if ( function_exists('ini_set') )
424  {// if possible turn off error display (we display it)
425    ini_set('display_errors', false);
426  }
427  error_reporting( E_ALL );
428  trigger_error( strip_tags($msg).$btrace_msg, E_USER_ERROR );
429  die(0); // just in case
430}
431
432/* returns the title to be displayed above thumbnails on tag page
433 */
434function get_tags_content_title()
435{
436  global $page;
437  $title = count($page['tags']) > 1 ? l10n('Tag') : l10n('Tag');
438  $title.= ' ';
439
440  for ($i=0; $i<count($page['tags']); $i++)
441  {
442    $title.= $i>0 ? ' + ' : '';
443
444    $title.=
445      '<a href="'
446      .make_index_url(
447        array(
448          'tags' => array( $page['tags'][$i] )
449          )
450        )
451      .'" title="'
452      .l10n('display photos linked to this tag')
453      .'">'
454      .trigger_event('render_tag_name', $page['tags'][$i]['name'])
455      .'</a>';
456
457    $remove_url = null;
458    if (count($page['tags']) == 1)
459    {
460      $remove_url = get_root_url().'tags.php';
461    }
462    else
463    {
464      $other_tags = $page['tags'];
465      unset($other_tags[$i]);
466      $remove_url = make_index_url(
467        array(
468          'tags' => $other_tags
469          )
470        );
471    }
472
473    $title.=
474      '<a href="'.$remove_url.'" style="border:none;" title="'
475      .l10n('remove this tag from the list')
476      .'"><img src="'
477        .get_root_url().get_themeconf('icon_dir').'/remove_s.png'
478      .'" alt="x" style="vertical-align:bottom;">'
479      .'</a>';
480  }
481  return $title;
482}
483
484/**
485  Sets the http status header (200,401,...)
486 */
487function set_status_header($code, $text='')
488{
489  if (empty($text))
490  {
491    switch ($code)
492    {
493      case 200: $text='OK';break;
494      case 301: $text='Moved permanently';break;
495      case 302: $text='Moved temporarily';break;
496      case 304: $text='Not modified';break;
497      case 400: $text='Bad request';break;
498      case 401: $text='Authorization required';break;
499      case 403: $text='Forbidden';break;
500      case 404: $text='Not found';break;
501      case 500: $text='Server error';break;
502      case 501: $text='Not implemented';break;
503      case 503: $text='Service unavailable';break;
504    }
505  }
506  $protocol = $_SERVER["SERVER_PROTOCOL"];
507  if ( ('HTTP/1.1' != $protocol) && ('HTTP/1.0' != $protocol) )
508    $protocol = 'HTTP/1.0';
509
510  header( "$protocol $code $text", true, $code );
511  trigger_action('set_status_header', $code, $text);
512}
513
514/** returns the category comment for rendering in html textual mode (subcatify)
515 * this is an event handler. don't call directly
516 */
517function render_category_literal_description($desc)
518{
519  return strip_tags($desc, '<span><p><a><br><b><i><small><big><strong><em>');
520}
521
522/*event handler for menu*/
523function register_default_menubar_blocks( $menu_ref_arr )
524{
525  $menu = & $menu_ref_arr[0];
526  if ($menu->get_id() != 'menubar')
527    return;
528  $menu->register_block( new RegisteredBlock( 'mbLinks', 'Links', 'piwigo'));
529  $menu->register_block( new RegisteredBlock( 'mbCategories', 'Albums', 'piwigo'));
530  $menu->register_block( new RegisteredBlock( 'mbTags', 'Related tags', 'piwigo'));
531  $menu->register_block( new RegisteredBlock( 'mbSpecials', 'Specials', 'piwigo'));
532  $menu->register_block( new RegisteredBlock( 'mbMenu', 'Menu', 'piwigo'));
533  $menu->register_block( new RegisteredBlock( 'mbIdentification', 'Identification', 'piwigo') );
534}
535
536/**
537 */
538function render_element_name($info)
539{
540  $name = $info['name'];
541  if (!empty($name))
542  {
543    $name = trigger_event('render_element_description', $name);
544    return $name;
545  }
546
547  return get_name_from_file($info['file']);
548}
549
550function render_element_description($info)
551{
552  $comment = $info['comment'];
553  if (!empty($comment))
554  {
555    $comment = trigger_event('render_element_description', $comment);
556    return $comment;
557  }
558  return '';
559}
560
561/**
562 * returns the title of the thumbnail based on photo properties
563 */
564function get_thumbnail_title($info, $title, $comment)
565{
566  global $conf, $user;
567
568  $details = array();
569
570  if (!empty($info['hit']))
571  {
572    $details[] = $info['hit'].' '.strtolower(l10n('Visits'));
573  }
574
575  if ($conf['rate'] and !empty($info['rating_score']))
576  {
577    $details[] = strtolower(l10n('Rating score')).' '.$info['rating_score'];
578  }
579
580  if (isset($info['nb_comments']) and $info['nb_comments'] != 0)
581  {
582    $details[] = l10n_dec('%d comment', '%d comments', $info['nb_comments']);
583  }
584
585  if (count($details) > 0)
586  {
587    $title.= ' ('.implode(', ', $details).')';
588  }
589
590  if (!empty($comment))
591  {
592    $title.= ' '.substr($info['comment'], 0, 100).(strlen($info['comment']) > 100 ? '...' : '');
593  }
594
595  $title = htmlspecialchars(strip_tags($title));
596  $title = trigger_event('get_thumbnail_title', $title, $info);
597  return $title;
598}
599
600?>
Note: See TracBrowser for help on using the repository browser.