Dotclear

source: inc/public/lib.tpl.context.php @ 3752:5b508fcc60c0

Revision 3752:5b508fcc60c0, 17.3 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

Allows space(s) as separator in smilies.txt

Line 
1<?php
2/**
3 * @package Dotclear
4 * @subpackage Public
5 *
6 * @copyright Olivier Meunier & Association Dotclear
7 * @copyright GPL-2.0-only
8 */
9
10if (!defined('DC_RC_PATH')) {return;}
11
12class context
13{
14    public $stack = array();
15
16    public function __set($name, $var)
17    {
18        if ($var === null) {
19            $this->pop($name);
20        } else {
21            $this->stack[$name][] = &$var;
22            if ($var instanceof record) {
23                $this->stack['cur_loop'][] = &$var;
24            }
25        }
26    }
27
28    public function __get($name)
29    {
30        if (!isset($this->stack[$name])) {
31            return;
32        }
33
34        $n = count($this->stack[$name]);
35        if ($n > 0) {
36            return $this->stack[$name][($n - 1)];
37        }
38
39        return;
40    }
41
42    public function exists($name)
43    {
44        return isset($this->stack[$name][0]);
45    }
46
47    public function pop($name)
48    {
49        if (isset($this->stack[$name])) {
50            $v = array_pop($this->stack[$name]);
51            if ($v instanceof record) {
52                array_pop($this->stack['cur_loop']);
53            }
54            unset($v);
55        }
56    }
57
58    # Loop position tests
59    public function loopPosition($start, $length = null, $even = null, $modulo = null)
60    {
61        if (!$this->cur_loop) {
62            return false;
63        }
64
65        $index = $this->cur_loop->index();
66        $size  = $this->cur_loop->count();
67
68        $test = false;
69        if ($start >= 0) {
70            $test = $index >= $start;
71            if ($length !== null) {
72                if ($length >= 0) {
73                    $test = $test && $index < $start + $length;
74                } else {
75                    $test = $test && $index < $size + $length;
76                }
77            }
78        } else {
79            $test = $index >= $size + $start;
80            if ($length !== null) {
81                if ($length >= 0) {
82                    $test = $test && $index < $size + $start + $length;
83                } else {
84                    $test = $test && $index < $size + $length;
85                }
86            }
87        }
88
89        if ($even !== null) {
90            $test = $test && $index % 2 == $even;
91        }
92
93        if ($modulo !== null) {
94            $test = $test && ($index % $modulo == 0);
95        }
96
97        return $test;
98    }
99
100    /**
101    @deprecated since version 2.11 , use tpl_context::global_filters instead
102     */
103    public static function global_filter($str,
104        $encode_xml, $remove_html, $cut_string, $lower_case, $upper_case, $encode_url, $tag = '') {
105        return self::global_filters(
106            $str,
107            array(0       => null,
108                'encode_xml'  => $encode_xml,
109                'remove_html' => $remove_html,
110                'cut_string'  => $cut_string,
111                'lower_case'  => $lower_case,
112                'upper_case'  => ($upper_case == 1 ? 1 : 0),
113                'capitalize'  => ($upper_case == 2 ? 1 : 0),
114                'encode_url'  => $encode_url),
115            $tag);
116    }
117
118    public static function global_filters($str, $args, $tag = '')
119    {
120        $args[0] = &$str;
121        $params  = new ArrayObject($args);
122
123        # --BEHAVIOR-- publicBeforeContentFilter
124        $res = $GLOBALS['core']->callBehavior('publicBeforeContentFilter', $GLOBALS['core'], $tag, $params);
125        $str = $params[0];
126
127        if ($params['strip_tags']) {
128            $str = self::strip_tags($str);
129        }
130        if ($params['remove_html']) {
131            $str = self::remove_html($str);
132            $str = preg_replace('/\s+/', ' ', $str);
133        }
134        if ($params['encode_xml'] || $params['encode_html']) {
135            $str = self::encode_xml($str);
136        }
137
138        if ($params['cut_string'] > 0) {
139            $str = self::cut_string($str, (integer) $params['cut_string']);
140        }
141
142        if ($params['lower_case']) {
143            $str = self::lower_case($str);
144        } elseif ($params['capitalize']) {
145            $str = self::capitalize($str);
146        } elseif ($params['upper_case']) {
147            $str = self::upper_case($str);
148        }
149
150        if ($params['encode_url']) {
151            $str = self::encode_url($str);
152        }
153
154        # --BEHAVIOR-- publicAfterContentFilter
155        $res = $GLOBALS['core']->callBehavior('publicAfterContentFilter', $GLOBALS['core'], $tag, $params);
156        $str = $params[0];
157
158        return $str;
159    }
160
161    public static function encode_url($str)
162    {
163        return urlencode($str);
164    }
165
166    public static function cut_string($str, $l)
167    {
168        return text::cutString($str, $l);
169    }
170
171    public static function encode_xml($str)
172    {
173        return html::escapeHTML($str);
174    }
175
176    public static function remove_html($str)
177    {
178        return html::decodeEntities(html::clean($str));
179    }
180
181    public static function strip_tags($str)
182    {
183        return trim(preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t"), ' ', html::clean($str))));
184    }
185
186    public static function lower_case($str)
187    {
188        return mb_strtolower($str);
189    }
190
191    public static function upper_case($str)
192    {
193        return mb_strtoupper($str);
194    }
195
196    public static function capitalize($str)
197    {
198        if ($str != '') {
199            $str[0] = mb_strtoupper($str[0]);
200        }
201        return $str;
202    }
203
204    public static function categoryPostParam(&$p)
205    {
206        $not = substr($p['cat_url'], 0, 1) == '!';
207        if ($not) {
208            $p['cat_url'] = substr($p['cat_url'], 1);
209        }
210
211        $p['cat_url'] = preg_split('/\s*,\s*/', $p['cat_url'], -1, PREG_SPLIT_NO_EMPTY);
212
213        foreach ($p['cat_url'] as &$v) {
214            if ($not) {
215                $v .= ' ?not';
216            }
217            if ($GLOBALS['_ctx']->exists('categories') && preg_match('/#self/', $v)) {
218                $v = preg_replace('/#self/', $GLOBALS['_ctx']->categories->cat_url, $v);
219            } elseif ($GLOBALS['_ctx']->exists('posts') && preg_match('/#self/', $v)) {
220                $v = preg_replace('/#self/', $GLOBALS['_ctx']->posts->cat_url, $v);
221            }
222        }
223    }
224
225    # Static methods for pagination
226    public static function PaginationNbPages()
227    {
228        global $_ctx;
229
230        if ($_ctx->pagination === null) {
231            return false;
232        }
233
234        $nb_posts = $_ctx->pagination->f(0);
235        if (($GLOBALS['core']->url->type == 'default') || ($GLOBALS['core']->url->type == 'default-page')) {
236            $nb_pages = ceil(($nb_posts - $_ctx->nb_entry_first_page) / $_ctx->nb_entry_per_page + 1);
237        } else {
238            $nb_pages = ceil($nb_posts / $_ctx->nb_entry_per_page);
239        }
240
241        return $nb_pages;
242    }
243
244    public static function PaginationPosition($offset = 0)
245    {
246        if (isset($GLOBALS['_page_number'])) {
247            $p = $GLOBALS['_page_number'];
248        } else {
249            $p = 1;
250        }
251
252        $p = $p + $offset;
253
254        $n = self::PaginationNbPages();
255        if (!$n) {
256            return $p;
257        }
258
259        if ($p > $n || $p <= 0) {
260            return 1;
261        } else {
262            return $p;
263        }
264    }
265
266    public static function PaginationStart()
267    {
268        if (isset($GLOBALS['_page_number'])) {
269            return self::PaginationPosition() == 1;
270        }
271
272        return true;
273    }
274
275    public static function PaginationEnd()
276    {
277        if (isset($GLOBALS['_page_number'])) {
278            return self::PaginationPosition() == self::PaginationNbPages();
279        }
280
281        return false;
282    }
283
284    public static function PaginationURL($offset = 0)
285    {
286        $args = $_SERVER['URL_REQUEST_PART'];
287
288        $n = self::PaginationPosition($offset);
289
290        $args = preg_replace('#(^|/)page/([0-9]+)$#', '', $args);
291
292        $url = $GLOBALS['core']->blog->url . $args;
293
294        if ($n > 1) {
295            $url = preg_replace('#/$#', '', $url);
296            $url .= '/page/' . $n;
297        }
298
299        # If search param
300        if (!empty($_GET['q'])) {
301            $s = strpos($url, '?') !== false ? '&amp;' : '?';
302            $url .= $s . 'q=' . rawurlencode($_GET['q']);
303        }
304        return $url;
305    }
306
307    # Robots policy
308    public static function robotsPolicy($base, $over)
309    {
310        $pol  = array('INDEX' => 'INDEX', 'FOLLOW' => 'FOLLOW', 'ARCHIVE' => 'ARCHIVE');
311        $base = array_flip(preg_split('/\s*,\s*/', $base));
312        $over = array_flip(preg_split('/\s*,\s*/', $over));
313
314        foreach ($pol as $k => &$v) {
315            if (isset($base[$k]) || isset($base['NO' . $k])) {
316                $v = isset($base['NO' . $k]) ? 'NO' . $k : $k;
317            }
318            if (isset($over[$k]) || isset($over['NO' . $k])) {
319                $v = isset($over['NO' . $k]) ? 'NO' . $k : $k;
320            }
321        }
322
323        if ($pol['ARCHIVE'] == 'ARCHIVE') {
324            unset($pol['ARCHIVE']);
325        }
326
327        return implode(', ', $pol);
328    }
329
330    # Smilies static methods
331    public static function getSmilies($blog)
332    {
333        $path = array();
334        if (isset($GLOBALS['__theme'])) {
335            $path[] = $GLOBALS['__theme'];
336            if (isset($GLOBALS['__parent_theme'])) {
337                $path[] = $GLOBALS['__parent_theme'];
338            }
339        }
340        $path[]     = 'default';
341        $definition = $blog->themes_path . '/%s/smilies/smilies.txt';
342        $base_url   = $blog->settings->system->themes_url . '/%s/smilies/';
343
344        $res = array();
345
346        foreach ($path as $t) {
347            if (file_exists(sprintf($definition, $t))) {
348                $base_url = sprintf($base_url, $t);
349                return self::smiliesDefinition(sprintf($definition, $t), $base_url);
350            }
351        }
352        return false;
353    }
354
355    public static function smiliesDefinition($f, $url)
356    {
357        $def = file($f);
358
359        $res = array();
360        foreach ($def as $v) {
361            $v = trim($v);
362            if (preg_match('|^([^\t\s]*)[\t\s]+(.*)$|', $v, $matches)) {
363                $r = '/(\G|[\s]+|>)(' . preg_quote($matches[1], '/') . ')([\s]+|[<]|\Z)/ms';
364                $s = '$1<img src="' . $url . $matches[2] . '" ' .
365                    'alt="$2" class="smiley" />$3';
366                $res[$r] = $s;
367            }
368        }
369
370        return $res;
371    }
372
373    public static function addSmilies($str)
374    {
375        if (!isset($GLOBALS['__smilies']) || !is_array($GLOBALS['__smilies'])) {
376            return $str;
377        }
378
379        # Process part adapted from SmartyPants engine (J. Gruber et al.) :
380
381        $tokens = self::tokenizeHTML($str);
382        $result = '';
383        $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags.
384
385        foreach ($tokens as $cur_token) {
386            if ($cur_token[0] == "tag") {
387                # Don't mess with quotes inside tags.
388                $result .= $cur_token[1];
389                if (preg_match('@<(/?)(?:pre|code|kbd|script|math)[\s>]@', $cur_token[1], $matches)) {
390                    $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
391                }
392            } else {
393                $t = $cur_token[1];
394                if (!$in_pre) {
395                    $t = preg_replace(array_keys($GLOBALS['__smilies']), array_values($GLOBALS['__smilies']), $t);
396                }
397                $result .= $t;
398            }
399        }
400
401        return $result;
402    }
403
404    private static function tokenizeHTML($str)
405    {
406        # Function from SmartyPants engine (J. Gruber et al.)
407        #
408        #   Parameter:  String containing HTML markup.
409        #   Returns:    An array of the tokens comprising the input
410        #               string. Each token is either a tag (possibly with nested,
411        #               tags contained therein, such as <a href="<MTFoo>">, or a
412        #               run of text between tags. Each element of the array is a
413        #               two-element array; the first is either 'tag' or 'text';
414        #               the second is the actual value.
415        #
416        #
417        #   Regular expression derived from the _tokenize() subroutine in
418        #   Brad Choate's MTRegex plugin.
419        #   <http://www.bradchoate.com/past/mtregex.php>
420        #
421        $index  = 0;
422        $tokens = array();
423
424        $match = '(?s:<!(?:--.*?--\s*)+>)|' . # comment
425        '(?s:<\?.*?\?>)|' . # processing instruction
426        # regular tags
427        '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)';
428
429        $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
430
431        foreach ($parts as $part) {
432            if (++$index % 2 && $part != '') {
433                $tokens[] = array('text', $part);
434            } else {
435                $tokens[] = array('tag', $part);
436            }
437
438        }
439        return $tokens;
440    }
441
442    # First post image helpers
443    public static function EntryFirstImageHelper($size, $with_category, $class = "", $no_tag = false, $content_only = false, $cat_only = false)
444    {
445        global $core, $_ctx;
446
447        try {
448            $media = new dcMedia($core);
449            $sizes = implode('|', array_keys($media->thumb_sizes)) . '|o';
450            if (!preg_match('/^' . $sizes . '$/', $size)) {
451                $size = 's';
452            }
453            $p_url  = $core->blog->settings->system->public_url;
454            $p_site = preg_replace('#^(.+?//.+?)/(.*)$#', '$1', $core->blog->url);
455            $p_root = $core->blog->public_path;
456
457            $pattern = '(?:' . preg_quote($p_site, '/') . ')?' . preg_quote($p_url, '/');
458            $pattern = sprintf('/<img.+?src="%s(.*?\.(?:jpg|jpeg|gif|png))"[^>]+/msui', $pattern);
459
460            $src = '';
461            $alt = '';
462
463            # We first look in post content
464            if (!$cat_only && $_ctx->posts) {
465                $subject = ($content_only ? '' : $_ctx->posts->post_excerpt_xhtml) . $_ctx->posts->post_content_xhtml;
466                if (preg_match_all($pattern, $subject, $m) > 0) {
467                    foreach ($m[1] as $i => $img) {
468                        if (($src = self::ContentFirstImageLookup($p_root, $img, $size)) !== false) {
469                            $dirname = str_replace('\\', '/', dirname($img));
470                            $src     = $p_url . ($dirname != '/' ? $dirname : '') . '/' . $src;
471                            if (preg_match('/alt="([^"]+)"/', $m[0][$i], $malt)) {
472                                $alt = $malt[1];
473                            }
474                            break;
475                        }
476                    }
477                }
478            }
479
480            # No src, look in category description if available
481            if (!$src && $with_category && $_ctx->posts->cat_desc) {
482                if (preg_match_all($pattern, $_ctx->posts->cat_desc, $m) > 0) {
483                    foreach ($m[1] as $i => $img) {
484                        if (($src = self::ContentFirstImageLookup($p_root, $img, $size)) !== false) {
485                            $dirname = str_replace('\\', '/', dirname($img));
486                            $src     = $p_url . ($dirname != '/' ? $dirname : '') . '/' . $src;
487                            if (preg_match('/alt="([^"]+)"/', $m[0][$i], $malt)) {
488                                $alt = $malt[1];
489                            }
490                            break;
491                        }
492                    }
493                };
494            }
495
496            if ($src) {
497                if ($no_tag) {
498                    return $src;
499                } else {
500                    return '<img alt="' . $alt . '" src="' . $src . '" class="' . $class . '" />';
501                }
502            }
503
504        } catch (Exception $e) {
505            $core->error->add($e->getMessage());
506        }
507    }
508
509    private static function ContentFirstImageLookup($root, $img, $size)
510    {
511        global $core;
512
513        # Get base name and extension
514        $info = path::info($img);
515        $base = $info['base'];
516
517        try {
518            $media = new dcMedia($core);
519            $sizes = implode('|', array_keys($media->thumb_sizes));
520            if (preg_match('/^\.(.+)_(' . $sizes . ')$/', $base, $m)) {
521                $base = $m[1];
522            }
523
524            $res = false;
525            if ($size != 'o' && file_exists($root . '/' . $info['dirname'] . '/.' . $base . '_' . $size . '.jpg')) {
526                $res = '.' . $base . '_' . $size . '.jpg';
527            } elseif ($size != 'o' && file_exists($root . '/' . $info['dirname'] . '/.' . $base . '_' . $size . '.png')) {
528                $res = '.' . $base . '_' . $size . '.png';
529            } else {
530                $f = $root . '/' . $info['dirname'] . '/' . $base;
531                if (file_exists($f . '.' . $info['extension'])) {
532                    $res = $base . '.' . $info['extension'];
533                } elseif (file_exists($f . '.jpg')) {
534                    $res = $base . '.jpg';
535                } elseif (file_exists($f . '.jpeg')) {
536                    $res = $base . '.jpeg';
537                } elseif (file_exists($f . '.png')) {
538                    $res = $base . '.png';
539                } elseif (file_exists($f . '.gif')) {
540                    $res = $base . '.gif';
541                } elseif (file_exists($f . '.JPG')) {
542                    $res = $base . '.JPG';
543                } elseif (file_exists($f . '.JPEG')) {
544                    $res = $base . '.JPEG';
545                } elseif (file_exists($f . '.PNG')) {
546                    $res = $base . '.PNG';
547                } elseif (file_exists($f . '.GIF')) {
548                    $res = $base . '.GIF';
549                }
550            }
551        } catch (Exception $e) {
552            $core->error->add($e->getMessage());
553        }
554
555        if ($res) {
556            return $res;
557        }
558        return false;
559    }
560}
Note: See TracBrowser for help on using the repository browser.

Sites map