moved code up one level to eliminate the docs subdirectory
[acontent.git] / include / lib / output.inc.php
1 <?php
2 /************************************************************************/
3 /* AContent                                                             */
4 /************************************************************************/
5 /* Copyright (c) 2010                                                   */
6 /* Inclusive Design Institute                                           */
7 /*                                                                      */
8 /* This program is free software. You can redistribute it and/or        */
9 /* modify it under the terms of the GNU General Public License          */
10 /* as published by the Free Software Foundation.                        */
11 /************************************************************************/
12
13 if (!defined('TR_INCLUDE_PATH')) { exit; }
14 require_once(TR_INCLUDE_PATH . 'classes/DAO/LanguageTextDAO.class.php');
15 require_once(TR_INCLUDE_PATH . '../home/classes/ContentUtility.class.php');
16
17 /**********************************************************************************/
18 /* Output functions found in this file, in order:
19 /*
20 /*      - AC(term)
21 /*
22 /**********************************************************************************/
23
24 /**
25 * Converts language code to actual language message, caches them according to page url
26 * @access       public
27 * @param        args                            unlimited number of arguments allowed but first arg MUST be name of the language variable/term
28 *                                                               i.e             $args[0] = the term to the format string $_template[term]
29 *                                                                               $args[1..x] = optional arguments to the formatting string 
30 * @return       string|array            full resulting message
31 * @see          $db                             in include/vitals.inc.php
32 * @see          cache()                         in include/phpCache/phpCache.inc.php
33 * @see          cache_variable()        in include/phpCache/phpCache.inc.php
34 * @author       Joel Kronenberg
35 */
36 function _AT() {
37         global $_cache_template, $lang_et, $_rel_url;
38         static $_template;
39
40         $args = func_get_args();
41         
42         if ($args[0] == "") return "";
43         
44         $languageTextDAO = new LanguageTextDAO();
45         
46         // a feedback msg
47         if (!is_array($args[0])) {
48                 /**
49                  * Added functionality for translating language code String (TR_ERROR|TR_INFOS|TR_WARNING|TR_FEEDBACK).*
50                  * to its text and returning the result. No caching needed.
51                  * @author Jacek Materna
52                  */
53
54                 // Check for specific language prefix, extendible as needed
55                 // 0002767:  a substring+in_array test should be faster than a preg_match test.
56                 // replaced the preg_match with a test of the substring.
57                 $sub_arg = substr($args[0], 0, 7); // 7 is the shortest type of msg (TR_INFO)
58                 if (in_array($sub_arg, array('TR_ERRO','TR_INFO','TR_WARN','TR_FEED','TR_CONF'))) {
59                         global $_base_path, $addslashes;
60
61                         $args[0] = $addslashes($args[0]);
62                                         
63                         /* get $_msgs_new from the DB */
64                         $rows = $languageTextDAO->getMsgByTermAndLang($args[0], $_SESSION['lang']);
65                         $msgs = '';
66                                         
67                         if (is_array($rows)) 
68                         {
69                                 $row = $rows[0];
70                                 // do not cache key as a digit (no contstant(), use string)
71                                 $msgs = str_replace('SITE_URL/', $_base_path, $row['text']);
72                                 if (defined('TR_DEVEL') && TR_DEVEL) {
73                                         $msgs .= ' <small><small>('. $args[0] .')</small></small>';
74                                 }
75                         }
76
77                         return $msgs;
78                 }
79         }
80         
81         // a template variable
82         if (!isset($_template)) {
83                 $url_parts = parse_url(TR_BASE_HREF);
84                 $name = substr($_SERVER['PHP_SELF'], strlen($url_parts['path'])-1);
85
86                 if ( !($lang_et = cache(120, 'lang', $_SESSION['lang'].'_'.$name)) ) {
87                         /* get $_template from the DB */
88                         $rows = $languageTextDAO->getAllTemplateByLang($_SESSION['lang']);
89                         
90                         if (is_array($rows))
91                         {
92                                 foreach ($rows as $id => $row) 
93                                 {
94                                         //Do not overwrite the variable that existed in the cache_template already.
95                                         //The edited terms (_c_template) will always be at the top of the resultset
96                                         //0003279
97                                         if (isset($_cache_template[$row['term']])){
98                                                 continue;
99                                         }
100         
101                                         // saves us from doing an ORDER BY
102                                         if ($row['language_code'] == $_SESSION['lang']) {
103                                                 $_cache_template[$row['term']] = stripslashes($row['text']);
104                                         } else if (!isset($_cache_template[$row['term']])) {
105                                                 $_cache_template[$row['term']] = stripslashes($row['text']);
106                                         }
107                                 }
108                         }
109                 
110                         cache_variable('_cache_template');
111                         endcache(true, false);
112                 }
113                 $_template = $_cache_template;
114         }
115
116         $num_args = func_num_args();
117         if (is_array($args[0])) {
118                 $args = $args[0];
119                 $num_args = count($args);
120         }
121         $format   = array_shift($args);
122
123         if (isset($_template[$format]) && count($args) > 0) {
124                 $outString      = vsprintf($_template[$format], $args);
125                 $str = ob_get_contents();
126         } else {
127                 $outString = '';
128         }
129
130         if ($outString === false) {
131                 return ('[Error parsing language. Variable: <code>'.$format.'</code>. Language: <code>'.$_SESSION['lang'].'</code> ]');
132         }
133
134         if (empty($outString)) {
135
136                 $rows = $languageTextDAO->getByTermAndLang($format, $_SESSION['lang']);
137                 if (is_array($rows))
138                 {
139                         $row = $rows[0];
140                         $_template[$row['term']] = stripslashes($row['text']);
141                         $outString = $_template[$row['term']];
142                 }
143
144                 if (empty($outString)) {
145                         return ('[ '.$format.' ]');
146                 }
147         }
148
149         return $outString;
150 }
151
152 /* 
153         The following options were added as language dependant:
154         %D: A textual representation of a week, three letters Mon through Sun
155         %F: A full textual representation of a month, such as January or March January through December
156         %l (lowercase 'L'): A full textual representation of the day of the week Sunday through Saturday
157         %M: A short textual representation of a month, three letters Jan through Dec
158
159         Support for the following maybe added later:
160         ?? %S: English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j
161         ?? %a: Lowercase Ante meridiem and Post meridiem am or pm 
162         ?? %A: Uppercase Ante meridiem and Post meridiem AM or PM 
163
164         valid formTR_types:
165         TR_DATE_MYSQL_DATETIME:         YYYY-MM-DD HH:MM:SS
166         TR_DATE_MYSQL_TIMESTAMP_14:     YYYYMMDDHHMMSS
167         TR_DATE_UNIX_TIMESTAMP:         seconds since epoch
168         TR_DATE_INDEX_VALUE:            0-x, index into a date array
169 */
170 function AT_date($format='%Y-%M-%d', $timestamp = '', $format_type=TR_DATE_MYSQL_DATETIME) {    
171         static $day_name_ext, $day_name_con, $month_name_ext, $month_name_con;
172         global $_config;
173
174         if (!isset($day_name_ext)) {
175                 $day_name_ext = array(  'date_sunday', 
176                                                                 'date_monday', 
177                                                                 'date_tuesday', 
178                                                                 'date_wednesday', 
179                                                                 'date_thursday', 
180                                                                 'date_friday',
181                                                                 'date_saturday');
182
183                 $day_name_con = array(  'date_sun', 
184                                                                 'date_mon', 
185                                                                 'date_tue', 
186                                                                 'date_wed',
187                                                                 'date_thu', 
188                                                                 'date_fri', 
189                                                                 'date_sat');
190
191                 $month_name_ext = array('date_january', 
192                                                                 'date_february', 
193                                                                 'date_march', 
194                                                                 'date_april', 
195                                                                 'date_may',
196                                                                 'date_june', 
197                                                                 'date_july', 
198                                                                 'date_august', 
199                                                                 'date_september', 
200                                                                 'date_october', 
201                                                                 'date_november',
202                                                                 'date_december');
203
204                 $month_name_con = array('date_jan', 
205                                                                 'date_feb', 
206                                                                 'date_mar', 
207                                                                 'date_apr', 
208                                                                 'date_may_short',
209                                                                 'date_jun', 
210                                                                 'date_jul', 
211                                                                 'date_aug', 
212                                                                 'date_sep', 
213                                                                 'date_oct', 
214                                                                 'date_nov',
215                                                                 'date_dec');
216         }
217
218         if ($format_type == TR_DATE_INDEX_VALUE) {
219                 // apply timezone offset
220                 apply_timezone($timestamp);
221         
222                 if ($format == '%D') {
223                         return _AT($day_name_con[$timestamp-1]);
224                 } else if ($format == '%l') {
225                         return _AT($day_name_ext[$timestamp-1]);
226                 } else if ($format == '%F') {
227                         return _AT($month_name_ext[$timestamp-1]);
228                 } else if ($format == '%M') {
229                         return _AT($month_name_con[$timestamp-1]);
230                 }
231         }
232
233         if ($timestamp == '') {
234                 $timestamp = time();
235                 $format_type = TR_DATE_UNIX_TIMESTAMP;
236         }
237
238         /* convert the date to a Unix timestamp before we do anything with it */
239         if ($format_type == TR_DATE_MYSQL_DATETIME) {
240                 $year   = substr($timestamp,0,4);
241                 $month  = substr($timestamp,5,2);
242                 $day    = substr($timestamp,8,2);
243                 $hour   = substr($timestamp,11,2);
244                 $min    = substr($timestamp,14,2);
245                 $sec    = substr($timestamp,17,2);
246                 $timestamp      = mktime($hour, $min, $sec, $month, $day, $year);
247
248         } else if ($format_type == TR_DATE_MYSQL_TIMESTAMP_14) {
249             $year               = substr($timestamp,0,4);
250             $month              = substr($timestamp,4,2);
251             $day                = substr($timestamp,6,2);
252                 $hour           = substr($timestamp,8,2);
253             $minute             = substr($timestamp,10,2);
254             $second             = substr($timestamp,12,2);
255             $timestamp  = mktime($hour, $minute, $second, $month, $day, $year);  
256         }
257
258         // apply timezone offset
259         apply_timezone($timestamp);
260
261         /* pull out all the %X items from $format */
262         $first_token = strpos($format, '%');
263         if ($first_token === false) {
264                 /* no tokens found */
265                 return $timestamp;
266         } else {
267                 $tokened_format = substr($format, $first_token);
268         }
269         $tokens = explode('%', $tokened_format);
270         array_shift($tokens);
271         $num_tokens = count($tokens);
272
273         $output = $format;
274         
275         for ($i=0; $i<$num_tokens; $i++) {
276                 $tokens[$i] = substr($tokens[$i],0,1);
277
278                 if ($tokens[$i] == 'D') {
279                         $output = str_replace('%D', _AT($day_name_con[date('w', $timestamp)]),$output);
280                 
281                 } else if ($tokens[$i] == 'l') {
282                         $output = str_replace('%l', _AT($day_name_ext[date('w', $timestamp)]),$output);
283                 
284                 } else if ($tokens[$i] == 'F') {
285                         $output = str_replace('%F', _AT($month_name_ext[date('n', $timestamp)-1]),$output);             
286                 
287                 } else if ($tokens[$i] == 'M') {
288                         $output = str_replace('%M', _AT($month_name_con[date('n', $timestamp)-1]),$output);
289
290                 } else {
291                         /* this token doesn't need translating */
292                         $value = date($tokens[$i], $timestamp);
293                         if ($value != $tokens[$i]) {
294                                 $output = str_replace('%'.$tokens[$i], $value, $output);
295                         } /* else: this token isn't valid. so don't replace it. Eg. try %q */
296                 }
297         }
298
299         return $output;
300 }
301
302 /**********************************************************************************************************/
303         /**
304         *       Transforms text based on formatting preferences.  Original $input is also changed (passed by reference).
305         *       Can be called as:
306         *       1) $output = AT_print($input, $name);
307         *          echo $output;
308         *
309         *       2) echo AT_print($input, $name); // prefered method
310         *
311         * @access       public
312         * @param        string $input                   text being transformed
313         * @param        string $name                    the unique name of this field (convension: table_name.field_name)
314         * @param        boolean $runtime_html   forcefully disables html formatting for $input (only used by fields that 
315         *                                                                       have the 'formatting' option
316         * @return       string                                  transformed $input
317         * @see          TR_FORMAT constants             in include/lib/constants.inc.php
318         * @see          query_bit()                             in include/vitals.inc.php
319         * @author       Joel Kronenberg
320         */
321         function AT_print($input, $name, $runtime_html = true) {
322                 global $_field_formatting;
323
324                 if (!isset($_field_formatting[$name])) {
325                         /* field not set, check if there's a global setting */
326                         $parts = explode('.', $name);
327                         
328                         /* check if wildcard is set: */
329                         if (isset($_field_formatting[$parts[0].'.*'])) {
330                                 $name = $parts[0].'.*';
331                         } else {
332                                 /* field not set, and there's no global setting */
333                                 /* same as TR_FORMTR_NONE */
334                                 return $input;
335                         }
336                 }
337
338                 if (query_bit($_field_formatting[$name], TR_FORMTR_QUOTES)) {
339                         $input = str_replace('"', '&quot;', $input);
340                 }
341
342                 if (query_bit($_field_formatting[$name], TR_FORMTR_CONTENT_DIR)) {
343                         $input = str_replace('CONTENT_DIR/', '', $input);
344                 }
345
346                 if (query_bit($_field_formatting[$name], TR_FORMTR_HTML) && $runtime_html) {
347                         /* what special things do we have to do if this is HTML ? remove unwanted HTML? validate? */
348                 } else {
349                         $input = str_replace('<', '&lt;', $input);
350                         $input = nl2br($input);
351                 }
352
353                 /* this has to be here, only because TR_FORMTR_HTML is the only check that has an else-block */
354                 if ($_field_formatting[$name] === TR_FORMTR_NONE) {
355                         return $input;
356                 }
357
358                 if (query_bit($_field_formatting[$name], TR_FORMTR_EMOTICONS)) {
359                         $input = smile_replace($input);
360                 }
361
362                 if (query_bit($_field_formatting[$name], TR_FORMTR_ATCODES)) {
363                         $input = trim(ContentUtility::myCodes(' ' . $input . ' '));
364                 }
365
366                 if (query_bit($_field_formatting[$name], TR_FORMTR_LINKS)) {
367                         $input = trim(ContentUtility::makeClickable(' ' . $input . ' '));
368                 }
369
370                 if (query_bit($_field_formatting[$name], TR_FORMTR_IMAGES)) {
371                         $input = trim(ContentUtility::imageReplace(' ' . $input . ' '));
372                 }
373
374         
375                 return $input;
376         }
377
378 /********************************************************************************************/
379 // Global variables for emoticons
380  
381 global $smile_pics;
382 global $smile_codes;
383 if (!isset($smile_pics)) {
384         $smile_pics[0] = $_base_path.'images/forum/smile.gif';
385         $smile_pics[1] = $_base_path.'images/forum/wink.gif';
386         $smile_pics[2] = $_base_path.'images/forum/frown.gif';
387         $smile_pics[3] = $_base_path.'images/forum/ohwell.gif';
388         $smile_pics[4] = $_base_path.'images/forum/tongue.gif';
389         $smile_pics[5] = $_base_path.'images/forum/51.gif';
390         $smile_pics[6] = $_base_path.'images/forum/52.gif';
391         $smile_pics[7] = $_base_path.'images/forum/54.gif';
392         $smile_pics[8] = $_base_path.'images/forum/27.gif';
393         $smile_pics[9] = $_base_path.'images/forum/19.gif';
394         $smile_pics[10] = $_base_path.'images/forum/3.gif';
395         $smile_pics[11] = $_base_path.'images/forum/56.gif';
396 }
397
398 if (!isset($smile_codes)) {
399         $smile_codes[0] = ':)';
400         $smile_codes[1] = ';)';
401         $smile_codes[2] = ':(';
402         $smile_codes[3] = '::ohwell::';
403         $smile_codes[4] = ':P';
404         $smile_codes[5] = '::evil::';
405         $smile_codes[6] = '::angry::';
406         $smile_codes[7] = '::lol::';
407         $smile_codes[8] = '::crazy::';
408         $smile_codes[9] = '::tired::';
409         $smile_codes[10] = '::confused::';
410         $smile_codes[11] = '::muah::';
411 }
412
413 /**
414 * Replaces smile-code text into smilie image.
415 * @access       public
416 * @param        string $text            smile text to be transformed
417 * @return       string                          transformed $text
418 * @see          $smile_pics                     in include/lib/output.inc.php (above)
419 * @see          $smile_codes            in include/lib/output.inc.php (above)
420 * @author       Joel Kronenberg
421 */
422 function smile_replace($text) {
423         global $smile_pics;
424         global $smile_codes;
425         static $smiles;
426
427         $smiles[0] = '<img src="'.$smile_pics[0].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_smile').'" />';
428         $smiles[1] = '<img src="'.$smile_pics[1].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_wink').'" />';
429         $smiles[2] = '<img src="'.$smile_pics[2].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_frown').'" />';
430         $smiles[3]= '<img src="'.$smile_pics[3].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_oh_well').'" />';
431         $smiles[4]= '<img src="'.$smile_pics[4].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tongue').'" />';
432         $smiles[5]= '<img src="'.$smile_pics[5].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_evil').'" />';
433         $smiles[6]= '<img src="'.$smile_pics[6].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_angry').'" />';
434         $smiles[7]= '<img src="'.$smile_pics[7].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_lol').'" />';
435         $smiles[8]= '<img src="'.$smile_pics[8].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_crazy').'" />';
436         $smiles[9]= '<img src="'.$smile_pics[9].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_tired').'" />';
437         $smiles[10]= '<img src="'.$smile_pics[10].'" border="0" height="17" width="19" align="bottom" alt="'._AT('smile_confused').'" />';
438         $smiles[11]= '<img src="'.$smile_pics[11].'" border="0" height="15" width="15" align="bottom" alt="'._AT('smile_muah').'" />';
439
440         $text = str_replace($smile_codes[0],$smiles[0],$text);
441         $text = str_replace($smile_codes[1],$smiles[1],$text);
442         $text = str_replace($smile_codes[2],$smiles[2],$text);
443         $text = str_replace($smile_codes[3],$smiles[3],$text);
444         $text = str_replace($smile_codes[4],$smiles[4],$text);
445         $text = str_replace($smile_codes[5],$smiles[5],$text);
446         $text = str_replace($smile_codes[6],$smiles[6],$text);
447         $text = str_replace($smile_codes[7],$smiles[7],$text);
448         $text = str_replace($smile_codes[8],$smiles[8],$text);
449         $text = str_replace($smile_codes[9],$smiles[9],$text);
450         $text = str_replace($smile_codes[10],$smiles[10],$text);
451         $text = str_replace($smile_codes[11],$smiles[11],$text);
452
453         return $text;
454 }
455
456 function html_get_list($array) {
457         $list = '';
458         foreach ($array as $value) {
459                 $list .= '<li>'.$value.'</li>';
460         }
461         return $list;
462 }
463
464 /**
465  * print_paginator
466  *
467  * print out list of page links
468  */
469 function print_paginator($current_page, $num_rows, $request_args, $rows_per_page = 50, $window = 5) {
470         $num_pages = ceil($num_rows / $rows_per_page);
471         $request_args = '?'.$request_args;
472
473         if ($num_pages == 1) return;
474         if ($num_rows) {
475                 echo '<div class="paging">';
476             echo '<ul>';
477                 
478                 $i=max($current_page-$window - max($window-$num_pages+$current_page,0), 1);
479
480             if ($current_page > 1)
481                         echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page-1).'">'._AT('prev').'</a>&nbsp;&nbsp;&nbsp;</li>';
482     
483                 if ($i > 1) {
484                         echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p=1">1</a></li>';
485                         if ($i > 2) {
486                         echo '<li>&hellip;</li>';
487                         }
488                 }
489
490                 for ($i; $i<= min($current_page+$window -min($current_page-$window,0),$num_pages); $i++) {
491                         if ($current_page == $i) {
492                                 echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'" class="current"><em>'.$current_page.'</em></a></li>';
493                         } else {
494                                 echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$i.'">'.$i.'</a></li>';
495                         }
496                 }
497         if ($i <= $num_pages) {
498                         if ($i < $num_pages) {
499                         echo '<li>&hellip;</li>';
500                 }
501                         echo '<li><a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.$num_pages.'">'.$num_pages.'</a></li>';
502                 }
503                 
504                 if ($current_page < $num_pages)
505                         echo '<li>&nbsp;&nbsp;&nbsp;<a href="'.$_SERVER['PHP_SELF'].$request_args.htmlspecialchars(SEP).'p='.($current_page+1).'">'._AT('next').'</a></li>';
506                 
507                 echo '</ul>';
508                 echo '</div>';
509         }
510 }
511
512 /**
513 * apply_timezone
514 * converts a unix timestamp into another UNIX timestamp with timezone offset added up.
515 * Adds the user's timezone offset, then converts back to a MYSQL timestamp
516 * Available both as a system config option, and a user preference, if both are set
517 * they are added together
518 * @param   date  MYSQL timestamp.
519 * @return  date  MYSQL timestamp plus user's and/or system's timezone offset.
520 * @author  Greg Gay  .
521 */
522 function apply_timezone($timestamp){
523         global $_config;
524
525         if($_config['time_zone']){
526                 $timestamp = ($timestamp + ($_config['time_zone']*3600));
527         }
528
529         if(isset($_SESSION['prefs']['PREF_TIMEZONE'])){
530                 $timestamp = ($timestamp + ($_SESSION['prefs']['PREF_TIMEZONE']*3600));
531         }
532
533         return $timestamp;
534 }
535 ?>