Dotclear

source: inc/public/class.dc.template.php @ 3479:ef52bedb5f53

Revision 3479:ef52bedb5f53, 91.5 KB checked in by franck <carnet.franck.paul@…>, 9 years ago (diff)

Add not (!) test on tpl:SysIf blog_lang attribute, closes #2230

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2015 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12
13class dcTemplate extends template
14{
15     private $core;
16     private $current_tag;
17
18     protected $unknown_value_handler = null;
19     protected $unknown_block_handler = null;
20
21     function __construct($cache_dir,$self_name,$core)
22     {
23          parent::__construct($cache_dir,$self_name);
24
25          $this->remove_php = !$core->blog->settings->system->tpl_allow_php;
26          $this->use_cache = $core->blog->settings->system->tpl_use_cache;
27
28          $this->tag_block = '<tpl:(\w+)(?:(\s+.*?)>|>)((?:[^<]|<(?!/?tpl:\1)|(?R))*)</tpl:\1>';
29          $this->tag_value = '{{tpl:(\w+)(\s(.*?))?}}';
30
31          $this->core =& $core;
32
33          # Transitional tags
34          $this->addValue('EntryTrackbackCount',array($this,'EntryPingCount'));
35          $this->addValue('EntryTrackbackData',array($this,'EntryPingData'));
36          $this->addValue('EntryTrackbackLink',array($this,'EntryPingLink'));
37
38          # l10n
39          $this->addValue('lang',array($this,'l10n'));
40
41          # Loops test tags
42          $this->addBlock('LoopPosition',array($this,'LoopPosition'));
43          $this->addValue('LoopIndex',array($this,'LoopIndex'));
44
45          # Archives
46          $this->addBlock('Archives',array($this,'Archives'));
47          $this->addBlock('ArchivesHeader',array($this,'ArchivesHeader'));
48          $this->addBlock('ArchivesFooter',array($this,'ArchivesFooter'));
49          $this->addBlock('ArchivesYearHeader',array($this,'ArchivesYearHeader'));
50          $this->addBlock('ArchivesYearFooter',array($this,'ArchivesYearFooter'));
51          $this->addValue('ArchiveDate',array($this,'ArchiveDate'));
52          $this->addBlock('ArchiveNext',array($this,'ArchiveNext'));
53          $this->addBlock('ArchivePrevious',array($this,'ArchivePrevious'));
54          $this->addValue('ArchiveEntriesCount',array($this,'ArchiveEntriesCount'));
55          $this->addValue('ArchiveURL',array($this,'ArchiveURL'));
56
57          # Blog
58          $this->addValue('BlogArchiveURL',array($this,'BlogArchiveURL'));
59          $this->addValue('BlogCopyrightNotice',array($this,'BlogCopyrightNotice'));
60          $this->addValue('BlogDescription',array($this,'BlogDescription'));
61          $this->addValue('BlogEditor',array($this,'BlogEditor'));
62          $this->addValue('BlogFeedID',array($this,'BlogFeedID'));
63          $this->addValue('BlogFeedURL',array($this,'BlogFeedURL'));
64          $this->addValue('BlogRSDURL',array($this,'BlogRSDURL'));
65          $this->addValue('BlogName',array($this,'BlogName'));
66          $this->addValue('BlogLanguage',array($this,'BlogLanguage'));
67          $this->addValue('BlogThemeURL',array($this,'BlogThemeURL'));
68        $this->addValue('BlogParentThemeURL',array($this,'BlogParentThemeURL'));
69          $this->addValue('BlogUpdateDate',array($this,'BlogUpdateDate'));
70          $this->addValue('BlogID',array($this,'BlogID'));
71          $this->addValue('BlogURL',array($this,'BlogURL'));
72          $this->addValue('BlogXMLRPCURL',array($this,'BlogXMLRPCURL'));
73          $this->addValue('BlogPublicURL',array($this,'BlogPublicURL'));
74          $this->addValue('BlogQmarkURL',array($this,'BlogQmarkURL'));
75          $this->addValue('BlogMetaRobots',array($this,'BlogMetaRobots'));
76          $this->addValue('BlogJsJQuery',array($this,'BlogJsJQuery'));
77
78          # Categories
79          $this->addBlock('Categories',array($this,'Categories'));
80          $this->addBlock('CategoriesHeader',array($this,'CategoriesHeader'));
81          $this->addBlock('CategoriesFooter',array($this,'CategoriesFooter'));
82          $this->addBlock('CategoryIf',array($this,'CategoryIf'));
83          $this->addBlock('CategoryFirstChildren',array($this,'CategoryFirstChildren'));
84          $this->addBlock('CategoryParents',array($this,'CategoryParents'));
85          $this->addValue('CategoryFeedURL',array($this,'CategoryFeedURL'));
86          $this->addValue('CategoryURL',array($this,'CategoryURL'));
87          $this->addValue('CategoryShortURL',array($this,'CategoryShortURL'));
88          $this->addValue('CategoryDescription',array($this,'CategoryDescription'));
89          $this->addValue('CategoryTitle',array($this,'CategoryTitle'));
90          $this->addValue('CategoryEntriesCount',array($this,'CategoryEntriesCount'));
91
92          # Comments
93          $this->addBlock('Comments',array($this,'Comments'));
94          $this->addValue('CommentAuthor',array($this,'CommentAuthor'));
95          $this->addValue('CommentAuthorDomain',array($this,'CommentAuthorDomain'));
96          $this->addValue('CommentAuthorLink',array($this,'CommentAuthorLink'));
97          $this->addValue('CommentAuthorMailMD5',array($this,'CommentAuthorMailMD5'));
98          $this->addValue('CommentAuthorURL',array($this,'CommentAuthorURL'));
99          $this->addValue('CommentContent',array($this,'CommentContent'));
100          $this->addValue('CommentDate',array($this,'CommentDate'));
101          $this->addValue('CommentTime',array($this,'CommentTime'));
102          $this->addValue('CommentEmail',array($this,'CommentEmail'));
103          $this->addValue('CommentEntryTitle',array($this,'CommentEntryTitle'));
104          $this->addValue('CommentFeedID',array($this,'CommentFeedID'));
105          $this->addValue('CommentID',array($this,'CommentID'));
106          $this->addBlock('CommentIf',array($this,'CommentIf'));
107          $this->addValue('CommentIfFirst',array($this,'CommentIfFirst'));
108          $this->addValue('CommentIfMe',array($this,'CommentIfMe'));
109          $this->addValue('CommentIfOdd',array($this,'CommentIfOdd'));
110          $this->addValue('CommentIP',array($this,'CommentIP'));
111          $this->addValue('CommentOrderNumber',array($this,'CommentOrderNumber'));
112          $this->addBlock('CommentsFooter',array($this,'CommentsFooter'));
113          $this->addBlock('CommentsHeader',array($this,'CommentsHeader'));
114          $this->addValue('CommentPostURL',array($this,'CommentPostURL'));
115          $this->addBlock('IfCommentAuthorEmail',array($this,'IfCommentAuthorEmail'));
116          $this->addValue('CommentHelp',array($this,'CommentHelp'));
117
118          # Comment preview
119          $this->addBlock('IfCommentPreview',array($this,'IfCommentPreview'));
120          $this->addBlock('IfCommentPreviewOptional',array($this,'IfCommentPreviewOptional'));
121          $this->addValue('CommentPreviewName',array($this,'CommentPreviewName'));
122          $this->addValue('CommentPreviewEmail',array($this,'CommentPreviewEmail'));
123          $this->addValue('CommentPreviewSite',array($this,'CommentPreviewSite'));
124          $this->addValue('CommentPreviewContent',array($this,'CommentPreviewContent'));
125          $this->addValue('CommentPreviewCheckRemember',array($this,'CommentPreviewCheckRemember'));
126
127          # Entries
128          $this->addBlock('DateFooter',array($this,'DateFooter'));
129          $this->addBlock('DateHeader',array($this,'DateHeader'));
130          $this->addBlock('Entries',array($this,'Entries'));
131          $this->addBlock('EntriesFooter',array($this,'EntriesFooter'));
132          $this->addBlock('EntriesHeader',array($this,'EntriesHeader'));
133          $this->addValue('EntryAuthorCommonName',array($this,'EntryAuthorCommonName'));
134          $this->addValue('EntryAuthorDisplayName',array($this,'EntryAuthorDisplayName'));
135          $this->addValue('EntryAuthorEmail',array($this,'EntryAuthorEmail'));
136          $this->addValue('EntryAuthorEmailMD5',array($this,'EntryAuthorEmailMD5'));
137          $this->addValue('EntryAuthorID',array($this,'EntryAuthorID'));
138          $this->addValue('EntryAuthorLink',array($this,'EntryAuthorLink'));
139          $this->addValue('EntryAuthorURL',array($this,'EntryAuthorURL'));
140          $this->addValue('EntryBasename',array($this,'EntryBasename'));
141          $this->addValue('EntryCategory',array($this,'EntryCategory'));
142          $this->addValue('EntryCategoryDescription',array($this,'EntryCategoryDescription'));
143          $this->addBlock('EntryCategoriesBreadcrumb',array($this,'EntryCategoriesBreadcrumb'));
144          $this->addValue('EntryCategoryID',array($this,'EntryCategoryID'));
145          $this->addValue('EntryCategoryURL',array($this,'EntryCategoryURL'));
146          $this->addValue('EntryCategoryShortURL',array($this,'EntryCategoryShortURL'));
147          $this->addValue('EntryCommentCount',array($this,'EntryCommentCount'));
148          $this->addValue('EntryContent',array($this,'EntryContent'));
149          $this->addValue('EntryDate',array($this,'EntryDate'));
150          $this->addValue('EntryExcerpt',array($this,'EntryExcerpt'));
151          $this->addValue('EntryFeedID',array($this,'EntryFeedID'));
152          $this->addValue('EntryFirstImage',array($this,'EntryFirstImage'));
153          $this->addValue('EntryID',array($this,'EntryID'));
154          $this->addBlock('EntryIf',array($this,'EntryIf'));
155          $this->addBlock('EntryIfContentCut',array($this,'EntryIfContentCut'));
156          $this->addValue('EntryIfFirst',array($this,'EntryIfFirst'));
157          $this->addValue('EntryIfOdd',array($this,'EntryIfOdd'));
158          $this->addValue('EntryIfSelected',array($this,'EntryIfSelected'));
159          $this->addValue('EntryLang',array($this,'EntryLang'));
160          $this->addBlock('EntryNext',array($this,'EntryNext'));
161          $this->addValue('EntryPingCount',array($this,'EntryPingCount'));
162          $this->addValue('EntryPingData',array($this,'EntryPingData'));
163          $this->addValue('EntryPingLink',array($this,'EntryPingLink'));
164          $this->addBlock('EntryPrevious',array($this,'EntryPrevious'));
165          $this->addValue('EntryTitle',array($this,'EntryTitle'));
166          $this->addValue('EntryTime',array($this,'EntryTime'));
167          $this->addValue('EntryURL',array($this,'EntryURL'));
168
169          # Languages
170          $this->addBlock('Languages',array($this,'Languages'));
171          $this->addBlock('LanguagesHeader',array($this,'LanguagesHeader'));
172          $this->addBlock('LanguagesFooter',array($this,'LanguagesFooter'));
173          $this->addValue('LanguageCode',array($this,'LanguageCode'));
174          $this->addBlock('LanguageIfCurrent',array($this,'LanguageIfCurrent'));
175          $this->addValue('LanguageURL',array($this,'LanguageURL'));
176
177          # Pagination
178          $this->addBlock('Pagination',array($this,'Pagination'));
179          $this->addValue('PaginationCounter',array($this,'PaginationCounter'));
180          $this->addValue('PaginationCurrent',array($this,'PaginationCurrent'));
181          $this->addBlock('PaginationIf',array($this,'PaginationIf'));
182          $this->addValue('PaginationURL',array($this,'PaginationURL'));
183
184          # Trackbacks
185          $this->addValue('PingBlogName',array($this,'PingBlogName'));
186          $this->addValue('PingContent',array($this,'PingContent'));
187          $this->addValue('PingDate',array($this,'PingDate'));
188          $this->addValue('PingEntryTitle',array($this,'PingEntryTitle'));
189          $this->addValue('PingFeedID',array($this,'PingFeedID'));
190          $this->addValue('PingID',array($this,'PingID'));
191          $this->addValue('PingIfFirst',array($this,'PingIfFirst'));
192          $this->addValue('PingIfOdd',array($this,'PingIfOdd'));
193          $this->addValue('PingIP',array($this,'PingIP'));
194          $this->addValue('PingNoFollow',array($this,'PingNoFollow'));
195          $this->addValue('PingOrderNumber',array($this,'PingOrderNumber'));
196          $this->addValue('PingPostURL',array($this,'PingPostURL'));
197          $this->addBlock('Pings',array($this,'Pings'));
198          $this->addBlock('PingsFooter',array($this,'PingsFooter'));
199          $this->addBlock('PingsHeader',array($this,'PingsHeader'));
200          $this->addValue('PingTime',array($this,'PingTime'));
201          $this->addValue('PingTitle',array($this,'PingTitle'));
202          $this->addValue('PingAuthorURL',array($this,'PingAuthorURL'));
203
204          # System
205          $this->addValue('SysBehavior',array($this,'SysBehavior'));
206          $this->addBlock('SysIf',array($this,'SysIf'));
207          $this->addBlock('SysIfCommentPublished',array($this,'SysIfCommentPublished'));
208          $this->addBlock('SysIfCommentPending',array($this,'SysIfCommentPending'));
209          $this->addBlock('SysIfFormError',array($this,'SysIfFormError'));
210          $this->addValue('SysFeedSubtitle',array($this,'SysFeedSubtitle'));
211          $this->addValue('SysFormError',array($this,'SysFormError'));
212          $this->addValue('SysPoweredBy',array($this,'SysPoweredBy'));
213          $this->addValue('SysSearchString',array($this,'SysSearchString'));
214          $this->addValue('SysSelfURI',array($this,'SysSelfURI'));
215
216          # Generic
217          $this->addValue('else',array($this,'GenericElse'));
218     }
219
220     public function getData($________)
221     {
222          # --BEHAVIOR-- tplBeforeData
223          if ($this->core->hasBehavior('tplBeforeData'))
224          {
225               self::$_r = $this->core->callBehavior('tplBeforeData',$this->core);
226               if (self::$_r) {
227                    return self::$_r;
228               }
229          }
230
231          parent::getData($________);
232
233          # --BEHAVIOR-- tplAfterData
234          if ($this->core->hasBehavior('tplAfterData')) {
235               $this->core->callBehavior('tplAfterData',$this->core,self::$_r);
236          }
237
238          return self::$_r;
239     }
240
241     public function compileBlockNode($tag,$attr,$content)
242     {
243          $this->current_tag = $tag;
244          $attr = new ArrayObject($attr);
245          # --BEHAVIOR-- templateBeforeBlock
246          $res = $this->core->callBehavior('templateBeforeBlock',$this->core,$this->current_tag,$attr);
247
248          # --BEHAVIOR-- templateInsideBlock
249          $this->core->callBehavior('templateInsideBlock',$this->core,$this->current_tag,$attr,array(&$content));
250
251          $res .= parent::compileBlockNode($this->current_tag,$attr,$content);
252
253          # --BEHAVIOR-- templateAfterBlock
254          $res .= $this->core->callBehavior('templateAfterBlock',$this->core,$this->current_tag,$attr);
255
256          return $res;
257     }
258
259     public function compileValueNode($tag,$attr,$str_attr)
260     {
261          $this->current_tag = $tag;
262
263          $attr = new ArrayObject($attr);
264          # --BEHAVIOR-- templateBeforeValue
265          $res = $this->core->callBehavior('templateBeforeValue',$this->core,$this->current_tag,$attr);
266
267          $res .= parent::compileValueNode($this->current_tag,$attr,$str_attr);
268
269          # --BEHAVIOR-- templateAfterValue
270          $res .= $this->core->callBehavior('templateAfterValue',$this->core,$this->current_tag,$attr);
271
272          return $res;
273     }
274
275     public function getFilters($attr,$default=array())
276     {
277          if (!is_array($attr) && !($attr instanceof arrayObject)) {
278               $attr = array();
279          }
280
281          $p = array_merge(
282               array(
283                    0 => null,
284                    'encode_xml' => 0,
285                    'encode_html' => 0,
286                    'cut_string' => 0,
287                    'lower_case' => 0,
288                    'upper_case' => 0,
289                    'encode_url' => 0,
290                    'remove_html' => 0,
291                    'capitalize' => 0,
292                    'strip_tags' => 0
293               ),
294               $default
295          );
296
297          foreach($attr as $k => $v) {
298               // attributes names must follow this rule
299               $k = preg_filter('/[a-zA-Z0-9_]/','$0',$k);
300               if ($k) {
301                    // addslashes protect var_export, str_replace protect sprintf;
302                    $p[$k] = str_replace('%','%%',addslashes($v));
303               }
304          }
305
306          return "context::global_filters(%s,".var_export($p,true).",'".addslashes($this->current_tag)."')";
307     }
308
309     public static function getOperator($op)
310     {
311          switch (strtolower($op))
312          {
313               case 'or':
314               case '||':
315                    return '||';
316               case 'and':
317               case '&&':
318               default:
319                    return '&&';
320          }
321     }
322
323     public function getSortByStr($attr,$table = null)
324     {
325          $res = array();
326
327          $default_order = 'desc';
328
329          $default_alias = array(
330               'post' => array(
331                    'title' => 'post_title',
332                    'selected' => 'post_selected',
333                    'author' => 'user_id',
334                    'date' => 'post_dt',
335                    'id' => 'post_id',
336                    'comment' => 'nb_comment',
337                    'trackback' => 'nb_trackback'
338               ),
339               'comment' => array(
340                    'author' => 'comment_author',
341                    'date' => 'comment_dt',
342                    'id' => 'comment_id'
343               )
344          );
345
346          $alias = new ArrayObject();
347
348          # --BEHAVIOR-- templateCustomSortByAlias
349          $this->core->callBehavior('templateCustomSortByAlias',$alias);
350
351          $alias = $alias->getArrayCopy();
352
353          if (is_array($alias)) {
354               foreach ($alias as $k => $v) {
355                    if (!is_array($v)) {
356                         $alias[$k] = array();
357                    }
358                    if (!isset($default_alias[$k]) || !is_array($default_alias[$k])) {
359                         $default_alias[$k] = array();
360                    }
361                    $default_alias[$k] = array_merge($default_alias[$k],$alias[$k]);
362               }
363          }
364
365          if (!array_key_exists($table,$default_alias)) {
366               return implode(', ',$res);
367          }
368
369          if (isset($attr['order']) && preg_match('/^(desc|asc)$/i',$attr['order'])) {
370               $default_order = $attr['order'];
371          }
372          if (isset($attr['sortby'])) {
373               $sorts = explode(',',$attr['sortby']);
374               foreach ($sorts as $k => $sort) {
375                    $order = $default_order;
376                    if (preg_match('/([a-z]*)\s*\?(desc|asc)$/i',$sort,$matches)) {
377                         $sort = $matches[1];
378                         $order = $matches[2];
379                    }
380                    if (array_key_exists($sort,$default_alias[$table])) {
381                         array_push($res,$default_alias[$table][$sort].' '.$order);
382                    }
383               }
384          }
385
386          if (count($res) === 0) {
387               array_push($res,$default_alias[$table]['date'].' '.$default_order);
388          }
389
390          return implode(', ',$res);
391     }
392
393     public static function getAge($attr)
394     {
395          if (isset($attr['age']) && preg_match('/^(\-[0-9]+|last).*$/i',$attr['age'])) {
396               if (($ts = strtotime($attr['age'])) !== false) {
397                    return dt::str('%Y-%m-%d %H:%m:%S',$ts);
398               }
399          }
400          return '';
401     }
402
403     public function displayCounter($variable,$values,$attr,$count_only_by_default=false) {
404          if (isset($attr['count_only'])) {
405               $count_only=($attr['count_only']==1);
406          } else {
407               $count_only = $count_only_by_default;
408          }
409          if ($count_only) {
410               return "<?php echo ".$variable."; ?>";
411          } else {
412               $v=$values;
413               if (isset($attr['none'])) {
414                    $v['none'] = addslashes($attr['none']);
415               }
416               if (isset($attr['one'])) {
417                    $v['one'] = addslashes($attr['one']);
418               }
419               if (isset($attr['more'])) {
420                    $v['more'] = addslashes($attr['more']);
421               }
422               return
423                    "<?php if (".$variable." == 0) {\n".
424                    "  printf(__('".$v['none']."'),".$variable.");\n".
425                    "} elseif (".$variable." == 1) {\n".
426                    "  printf(__('".$v['one']."'),".$variable.");\n".
427                    "} else {\n".
428                    "  printf(__('".$v['more']."'),".$variable.");\n".
429                    "} ?>";
430          }
431     }
432     /* TEMPLATE FUNCTIONS
433     ------------------------------------------------------- */
434
435     public function l10n($attr,$str_attr)
436     {
437          # Normalize content
438          $str_attr = preg_replace('/\s+/x',' ',$str_attr);
439
440          return "<?php echo __('".str_replace("'","\\'",$str_attr)."'); ?>";
441     }
442
443     public function LoopPosition($attr,$content)
444     {
445          $start = isset($attr['start']) ? (integer) $attr['start'] : '0';
446          $length = isset($attr['length']) ? (integer) $attr['length'] : 'null';
447          $even = isset($attr['even']) ? (integer) (boolean) $attr['even'] : 'null';
448          $modulo = isset($attr['modulo']) ? (integer) $attr['modulo'] : 'null';
449
450          if ($start > 0) {
451               $start--;
452          }
453
454          return
455          '<?php if ($_ctx->loopPosition('.$start.','.$length.','.$even.','.$modulo.')) : ?>'.
456          $content.
457          "<?php endif; ?>";
458     }
459
460     public function LoopIndex($attr)
461     {
462          $f = $this->getFilters($attr);
463          return '<?php echo '.sprintf($f,'(!$_ctx->cur_loop ? 0 : $_ctx->cur_loop->index() + 1)').'; ?>';
464     }
465
466
467     /* Archives ------------------------------------------- */
468     /*dtd
469     <!ELEMENT tpl:Archives - - -- Archives dates loop -->
470     <!ATTLIST tpl:Archives
471     type      (day|month|year)    #IMPLIED  -- Get days, months or years, default to month --
472     category  CDATA               #IMPLIED  -- Get dates of given category --
473     no_context (1|0)              #IMPLIED  -- Override context information
474     order     (asc|desc)          #IMPLIED  -- Sort asc or desc --
475     post_type CDATA               #IMPLIED  -- Get dates of given type of entries, default to post --
476     post_lang CDATA          #IMPLIED  -- Filter on the given language
477     >
478     */
479     public function Archives($attr,$content)
480     {
481          $p = "if (!isset(\$params)) \$params = array();\n";
482          $p .= "\$params['type'] = 'month';\n";
483          if (isset($attr['type'])) {
484               $p .= "\$params['type'] = '".addslashes($attr['type'])."';\n";
485          }
486
487          if (isset($attr['category'])) {
488               $p .= "\$params['cat_url'] = '".addslashes($attr['category'])."';\n";
489          }
490
491          if (isset($attr['post_type'])) {
492               $p .= "\$params['post_type'] = '".addslashes($attr['post_type'])."';\n";
493          }
494
495          if (isset($attr['post_lang'])) {
496               $p .= "\$params['post_lang'] = '".addslashes($attr['post_lang'])."';\n";
497          }
498
499          if (empty($attr['no_context']) && !isset($attr['category']))
500          {
501               $p .=
502               'if ($_ctx->exists("categories")) { '.
503                    "\$params['cat_id'] = \$_ctx->categories->cat_id; ".
504               "}\n";
505          }
506
507          $order = 'desc';
508          if (isset($attr['order']) && preg_match('/^(desc|asc)$/i',$attr['order'])) {
509               $p .= "\$params['order'] = '".$attr['order']."';\n ";
510          }
511
512          $res = "<?php\n";
513          $res .= $p;
514          $res .= $this->core->callBehavior("templatePrepareParams",
515               array("tag" => "Archives","method" => "blog::getDates"),
516               $attr,$content);
517          $res .= '$_ctx->archives = $core->blog->getDates($params); unset($params);'."\n";
518          $res .= "?>\n";
519
520          $res .=
521          '<?php while ($_ctx->archives->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->archives = null; ?>';
522
523          return $res;
524     }
525
526     /*dtd
527     <!ELEMENT tpl:ArchivesHeader - - -- First archives result container -->
528     */
529     public function ArchivesHeader($attr,$content)
530     {
531          return
532          "<?php if (\$_ctx->archives->isStart()) : ?>".
533          $content.
534          "<?php endif; ?>";
535     }
536
537     /*dtd
538     <!ELEMENT tpl:ArchivesFooter - - -- Last archives result container -->
539     */
540     public function ArchivesFooter($attr,$content)
541     {
542          return
543          "<?php if (\$_ctx->archives->isEnd()) : ?>".
544          $content.
545          "<?php endif; ?>";
546     }
547
548     /*dtd
549     <!ELEMENT tpl:ArchivesYearHeader - - -- First result of year in archives container -->
550     */
551     public function ArchivesYearHeader($attr,$content)
552     {
553          return
554          "<?php if (\$_ctx->archives->yearHeader()) : ?>".
555          $content.
556          "<?php endif; ?>";
557     }
558
559     /*dtd
560     <!ELEMENT tpl:ArchivesYearFooter - - -- Last result of year in archives container -->
561     */
562     public function ArchivesYearFooter($attr,$content)
563     {
564          return
565          "<?php if (\$_ctx->archives->yearFooter()) : ?>".
566          $content.
567          "<?php endif; ?>";
568     }
569
570     /*dtd
571     <!ELEMENT tpl:ArchiveDate - O -- Archive result date -->
572     <!ATTLIST tpl:ArchiveDate
573     format    CDATA     #IMPLIED  -- Date format (Default %B %Y) --
574     >
575     */
576     public function ArchiveDate($attr)
577     {
578          $format = '%B %Y';
579          if (!empty($attr['format'])) {
580               $format = addslashes($attr['format']);
581          }
582
583          $f = $this->getFilters($attr);
584          return '<?php echo '.sprintf($f,"dt::dt2str('".$format."',\$_ctx->archives->dt)").'; ?>';
585     }
586
587     /*dtd
588     <!ELEMENT tpl:ArchiveEntriesCount - O -- Current archive result number of entries -->
589     */
590     public function ArchiveEntriesCount($attr)
591     {
592          $f = $this->getFilters($attr);
593          return $this->displayCounter(
594               sprintf($f,'$_ctx->archives->nb_post'),
595               array(
596                    'none' => 'no archive',
597                    'one'  => 'one archive',
598                    'more' => '%d archives'
599               ),
600               $attr,
601               true
602          );
603     }
604
605     /*dtd
606     <!ELEMENT tpl:ArchiveNext - - -- Next archive result container -->
607     <!ATTLIST tpl:ArchiveNext
608     type      (day|month|year)    #IMPLIED  -- Get days, months or years, default to month --
609     post_type CDATA               #IMPLIED  -- Get dates of given type of entries, default to post --
610     post_lang CDATA          #IMPLIED  -- Filter on the given language
611     >
612     */
613     public function ArchiveNext($attr,$content)
614     {
615          $p = "if (!isset(\$params)) \$params = array();\n";
616          $p .= "\$params['type'] = 'month';\n";
617          if (isset($attr['type'])) {
618               $p .= "\$params['type'] = '".addslashes($attr['type'])."';\n";
619          }
620
621          if (isset($attr['post_type'])) {
622               $p .= "\$params['post_type'] = '".addslashes($attr['post_type'])."';\n";
623          }
624
625          if (isset($attr['post_lang'])) {
626               $p .= "\$params['post_lang'] = '".addslashes($attr['post_lang'])."';\n";
627          }
628
629          $p .= "\$params['next'] = \$_ctx->archives->dt;";
630
631          $res = "<?php\n";
632          $res .= $p;
633          $res .= $this->core->callBehavior("templatePrepareParams",
634               array("tag" => "ArchiveNext","method" => "blog::getDates"),
635               $attr, $content);
636          $res .= '$_ctx->archives = $core->blog->getDates($params); unset($params);'."\n";
637          $res .= "?>\n";
638
639          $res .=
640          '<?php while ($_ctx->archives->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->archives = null; ?>';
641
642          return $res;
643     }
644
645     /*dtd
646     <!ELEMENT tpl:ArchivePrevious - - -- Previous archive result container -->
647     <!ATTLIST tpl:ArchivePrevious
648     type      (day|month|year)    #IMPLIED  -- Get days, months or years, default to month --
649     post_type CDATA               #IMPLIED  -- Get dates of given type of entries, default to post --
650     post_lang CDATA          #IMPLIED  -- Filter on the given language
651     >
652     */
653     public function ArchivePrevious($attr,$content)
654     {
655          $p = 'if (!isset($params)) $params = array();';
656          $p .= "\$params['type'] = 'month';\n";
657          if (isset($attr['type'])) {
658               $p .= "\$params['type'] = '".addslashes($attr['type'])."';\n";
659          }
660
661          if (isset($attr['post_type'])) {
662               $p .= "\$params['post_type'] = '".addslashes($attr['post_type'])."';\n";
663          }
664
665          if (isset($attr['post_lang'])) {
666               $p .= "\$params['post_lang'] = '".addslashes($attr['post_lang'])."';\n";
667          }
668
669          $p .= "\$params['previous'] = \$_ctx->archives->dt;";
670
671          $res = "<?php\n";
672          $res .= $this->core->callBehavior("templatePrepareParams",
673               array("tag" => "ArchivePrevious","method" => "blog::getDates"),
674               $attr, $content);
675          $res .= $p;
676          $res .= '$_ctx->archives = $core->blog->getDates($params); unset($params);'."\n";
677          $res .= "?>\n";
678
679          $res .=
680          '<?php while ($_ctx->archives->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->archives = null; ?>';
681
682          return $res;
683     }
684
685     /*dtd
686     <!ELEMENT tpl:ArchiveURL - O -- Current archive result URL -->
687     */
688     public function ArchiveURL($attr)
689     {
690          $f = $this->getFilters($attr);
691          return '<?php echo '.sprintf($f,'$_ctx->archives->url($core)').'; ?>';
692     }
693
694
695     /* Blog ----------------------------------------------- */
696     /*dtd
697     <!ELEMENT tpl:BlogArchiveURL - O -- Blog Archives URL -->
698     */
699     public function BlogArchiveURL($attr)
700     {
701          $f = $this->getFilters($attr);
702          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor("archive")').'; ?>';
703     }
704
705     /*dtd
706     <!ELEMENT tpl:BlogCopyrightNotice - O -- Blog copyrght notices -->
707     */
708     public function BlogCopyrightNotice($attr)
709     {
710          $f = $this->getFilters($attr);
711          return '<?php echo '.sprintf($f,'$core->blog->settings->system->copyright_notice').'; ?>';
712     }
713
714     /*dtd
715     <!ELEMENT tpl:BlogDescription - O -- Blog Description -->
716     */
717     public function BlogDescription($attr)
718     {
719          $f = $this->getFilters($attr);
720          return '<?php echo '.sprintf($f,'$core->blog->desc').'; ?>';
721     }
722
723     /*dtd
724     <!ELEMENT tpl:BlogEditor - O -- Blog Editor -->
725     */
726     public function BlogEditor($attr)
727     {
728          $f = $this->getFilters($attr);
729          return '<?php echo '.sprintf($f,'$core->blog->settings->system->editor').'; ?>';
730     }
731
732     /*dtd
733     <!ELEMENT tpl:BlogFeedID - O -- Blog Feed ID -->
734     */
735     public function BlogFeedID($attr)
736     {
737          $f = $this->getFilters($attr);
738          return '<?php echo '.sprintf($f,'"urn:md5:".$core->blog->uid').'; ?>';
739     }
740
741     /*dtd
742     <!ELEMENT tpl:BlogFeedURL - O -- Blog Feed URL -->
743     <!ATTLIST tpl:BlogFeedURL
744     type (rss2|atom)    #IMPLIED  -- feed type (default : rss2)
745     >
746     */
747     public function BlogFeedURL($attr)
748     {
749          $type = !empty($attr['type']) ? $attr['type'] : 'atom';
750
751          if (!preg_match('#^(rss2|atom)$#',$type)) {
752               $type = 'atom';
753          }
754
755          $f = $this->getFilters($attr);
756          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor("feed","'.$type.'")').'; ?>';
757     }
758
759     /*dtd
760     <!ELEMENT tpl:BlogName - O -- Blog Name -->
761     */
762     public function BlogName($attr)
763     {
764          $f = $this->getFilters($attr);
765          return '<?php echo '.sprintf($f,'$core->blog->name').'; ?>';
766     }
767
768     /*dtd
769     <!ELEMENT tpl:BlogLanguage - O -- Blog Language -->
770     */
771     public function BlogLanguage($attr)
772     {
773          $f = $this->getFilters($attr);
774          return '<?php echo '.sprintf($f,'$core->blog->settings->system->lang').'; ?>';
775     }
776
777     /*dtd
778     <!ELEMENT tpl:BlogThemeURL - O -- Blog's current Theme URL -->
779     */
780     public function BlogThemeURL($attr)
781     {
782          $f = $this->getFilters($attr);
783          return '<?php echo '.sprintf($f,'$core->blog->settings->system->themes_url."/".$core->blog->settings->system->theme').'; ?>';
784     }
785
786     /*dtd
787     <!ELEMENT tpl:BlogParentThemeURL - O -- Blog's current Theme's parent URL -->
788     */
789     public function BlogParentThemeURL($attr)
790     {
791          $f = $this->getFilters($attr);
792          $parent = '$core->themes->moduleInfo($core->blog->settings->system->theme,\'parent\')';
793          return '<?php echo '.sprintf($f,'$core->blog->settings->system->themes_url."/".('."$parent".' ? '."$parent".' : $core->blog->settings->system->theme)').'; ?>';
794     }
795
796     /*dtd
797     <!ELEMENT tpl:BlogPublicURL - O -- Blog Public directory URL -->
798     */
799     public function BlogPublicURL($attr)
800     {
801          $f = $this->getFilters($attr);
802          return '<?php echo '.sprintf($f,'$core->blog->settings->system->public_url').'; ?>';
803     }
804
805     /*dtd
806     <!ELEMENT tpl:BlogUpdateDate - O -- Blog last update date -->
807     <!ATTLIST tpl:BlogUpdateDate
808     format    CDATA     #IMPLIED  -- date format (encoded in dc:str by default if iso8601 or rfc822 not specified)
809     iso8601   CDATA     #IMPLIED  -- if set, tells that date format is ISO 8601
810     rfc822    CDATA     #IMPLIED  -- if set, tells that date format is RFC 822
811     >
812     */
813     public function BlogUpdateDate($attr)
814     {
815          $format = '';
816          if (!empty($attr['format'])) {
817               $format = addslashes($attr['format']);
818          } else {
819               $format = '%Y-%m-%d %H:%M:%S';
820          }
821
822          $iso8601 = !empty($attr['iso8601']);
823          $rfc822 = !empty($attr['rfc822']);
824
825          $f = $this->getFilters($attr);
826
827          if ($rfc822) {
828               return '<?php echo '.sprintf($f,"dt::rfc822(\$core->blog->upddt,\$core->blog->settings->system->blog_timezone)").'; ?>';
829          } elseif ($iso8601) {
830               return '<?php echo '.sprintf($f,"dt::iso8601(\$core->blog->upddt,\$core->blog->settings->system->blog_timezone)").'; ?>';
831          } else {
832               return '<?php echo '.sprintf($f,"dt::str('".$format."',\$core->blog->upddt)").'; ?>';
833          }
834     }
835
836     /*dtd
837     <!ELEMENT tpl:BlogID - 0 -- Blog ID -->
838     */
839     public function BlogID($attr)
840     {
841          $f = $this->getFilters($attr);
842          return '<?php echo '.sprintf($f,'$core->blog->id').'; ?>';
843     }
844
845     /*dtd
846     <!ELEMENT tpl:BlogRSDURL - O -- Blog RSD URL -->
847     */
848     public function BlogRSDURL($attr)
849     {
850          $f = $this->getFilters($attr);
851          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor(\'rsd\')').'; ?>';
852     }
853
854     /*dtd
855     <!ELEMENT tpl:BlogXMLRPCURL - O -- Blog XML-RPC URL -->
856     */
857     public function BlogXMLRPCURL($attr)
858     {
859          $f = $this->getFilters($attr);
860          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor(\'xmlrpc\',$core->blog->id)').'; ?>';
861     }
862
863     /*dtd
864     <!ELEMENT tpl:BlogURL - O -- Blog URL -->
865     */
866     public function BlogURL($attr)
867     {
868          $f = $this->getFilters($attr);
869          return '<?php echo '.sprintf($f,'$core->blog->url').'; ?>';
870     }
871
872     /*dtd
873     <!ELEMENT tpl:BlogQmarkURL - O -- Blog URL, ending with a question mark -->
874     */
875     public function BlogQmarkURL($attr)
876     {
877          $f = $this->getFilters($attr);
878          return '<?php echo '.sprintf($f,'$core->blog->getQmarkURL()').'; ?>';
879     }
880
881     /*dtd
882     <!ELEMENT tpl:BlogMetaRobots - O -- Blog meta robots tag definition, overrides robots_policy setting -->
883     <!ATTLIST tpl:BlogMetaRobots
884     robots    CDATA     #IMPLIED  -- can be INDEX,FOLLOW,NOINDEX,NOFOLLOW,ARCHIVE,NOARCHIVE
885     >
886     */
887     public function BlogMetaRobots($attr)
888     {
889          $robots = isset($attr['robots']) ? addslashes($attr['robots']) : '';
890          return "<?php echo context::robotsPolicy(\$core->blog->settings->system->robots_policy,'".$robots."'); ?>";
891     }
892
893     /*dtd
894     <!ELEMENT gpl:BlogJsJQuery - 0 -- Blog Js jQuery version selected -->
895     */
896     public function BlogJsJQuery($attr)
897     {
898          $f = $this->getFilters($attr);
899          return '<?php echo '.sprintf($f,'$core->blog->getJsJQuery()').'; ?>';
900     }
901
902     /* Categories ----------------------------------------- */
903
904     /*dtd
905     <!ELEMENT tpl:Categories - - -- Categories loop -->
906     */
907     public function Categories($attr,$content)
908     {
909          $p = "if (!isset(\$params)) \$params = array();\n";
910
911          if (isset($attr['url'])) {
912               $p .= "\$params['cat_url'] = '".addslashes($attr['url'])."';\n";
913          }
914
915          if (!empty($attr['post_type'])) {
916               $p .= "\$params['post_type'] = '".addslashes($attr['post_type'])."';\n";
917          }
918
919          if (!empty($attr['level'])) {
920               $p .= "\$params['level'] = ".(integer) $attr['level'].";\n";
921          }
922
923          if (isset($attr['with_empty']) && ((boolean) $attr['with_empty'] == true)) {
924               $p .= '$params[\'without_empty\'] = false;';
925          }
926
927          $res = "<?php\n";
928          $res .= $p;
929          $res .= $this->core->callBehavior("templatePrepareParams",
930               array("tag" => "Categories","method" => "blog::getCategories"),
931               $attr,$content);
932          $res .= '$_ctx->categories = $core->blog->getCategories($params);'."\n";
933          $res .= "?>\n";
934          $res .= '<?php while ($_ctx->categories->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->categories = null; unset($params); ?>';
935
936          return $res;
937     }
938
939     /*dtd
940     <!ELEMENT tpl:CategoriesHeader - - -- First Categories result container -->
941     */
942     public function CategoriesHeader($attr,$content)
943     {
944          return
945          "<?php if (\$_ctx->categories->isStart()) : ?>".
946          $content.
947          "<?php endif; ?>";
948     }
949
950     /*dtd
951     <!ELEMENT tpl:CategoriesFooter - - -- Last Categories result container -->
952     */
953     public function CategoriesFooter($attr,$content)
954     {
955          return
956          "<?php if (\$_ctx->categories->isEnd()) : ?>".
957          $content.
958          "<?php endif; ?>";
959     }
960
961     /*dtd
962     <!ELEMENT tpl:CategoryIf - - -- tests on current entry -->
963     <!ATTLIST tpl:CategoryIf
964     url       CDATA     #IMPLIED  -- category has given url
965     urls CDATA     #IMPLIED  -- category has one of given urls
966     has_entries    (0|1)     #IMPLIED  -- post is the first post from list (value : 1) or not (value : 0)
967     has_description     (0|1)     #IMPLIED  -- category has description (value : 1) or not (value : 0)
968     >
969     */
970     public function CategoryIf($attr,$content)
971     {
972          $if = new ArrayObject();
973          $operator = isset($attr['operator']) ? $this->getOperator($attr['operator']) : '&&';
974
975          if (isset($attr['url'])) {
976               $url = addslashes(trim($attr['url']));
977               if (substr($url,0,1) == '!') {
978                    $url = substr($url,1);
979                    $if[] = '($_ctx->categories->cat_url != "'.$url.'")';
980               } else {
981                    $if[] = '($_ctx->categories->cat_url == "'.$url.'")';
982               }
983          }
984
985          if (isset($attr['urls'])) {
986               $urls = explode(',',addslashes(trim($attr['urls'])));
987               if (is_array($urls) && count($urls)) {
988                    foreach ($urls as $url) {
989                         if (substr($url,0,1) == '!') {
990                              $url = substr($url,1);
991                              $if[] = '($_ctx->categories->cat_url != "'.$url.'")';
992                         } else {
993                              $if[] = '($_ctx->categories->cat_url == "'.$url.'")';
994                         }
995                    }
996               }
997          }
998
999          if (isset($attr['has_entries'])) {
1000               $sign = (boolean) $attr['has_entries'] ? '>' : '==';
1001               $if[] = '$_ctx->categories->nb_post '.$sign.' 0';
1002          }
1003
1004          if (isset($attr['has_description'])) {
1005               $sign = (boolean) $attr['has_description'] ? '!=' : '==';
1006               $if[] = '$_ctx->categories->cat_desc '.$sign.' ""';
1007          }
1008
1009          $this->core->callBehavior('tplIfConditions','CategoryIf',$attr,$content,$if);
1010
1011          if (count($if) != 0) {
1012               return '<?php if('.implode(' '.$operator.' ', (array) $if).') : ?>'.$content.'<?php endif; ?>';
1013          } else {
1014               return $content;
1015          }
1016     }
1017
1018     /*dtd
1019     <!ELEMENT tpl:CategoryFirstChildren - - -- Current category first children loop -->
1020     */
1021     public function CategoryFirstChildren($attr,$content)
1022     {
1023          return
1024          "<?php\n".
1025          '$_ctx->categories = $core->blog->getCategoryFirstChildren($_ctx->categories->cat_id);'."\n".
1026          'while ($_ctx->categories->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->categories = null; ?>';
1027     }
1028
1029     /*dtd
1030     <!ELEMENT tpl:CategoryParents - - -- Current category parents loop -->
1031     */
1032     public function CategoryParents($attr,$content)
1033     {
1034          return
1035          "<?php\n".
1036          '$_ctx->categories = $core->blog->getCategoryParents($_ctx->categories->cat_id);'."\n".
1037          'while ($_ctx->categories->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->categories = null; ?>';
1038     }
1039
1040     /*dtd
1041     <!ELEMENT tpl:CategoryFeedURL - O -- Category feed URL -->
1042     <!ATTLIST tpl:CategoryFeedURL
1043     type (rss2|atom)    #IMPLIED  -- feed type (default : rss2)
1044     >
1045     */
1046     public function CategoryFeedURL($attr)
1047     {
1048          $type = !empty($attr['type']) ? $attr['type'] : 'atom';
1049
1050          if (!preg_match('#^(rss2|atom)$#',$type)) {
1051               $type = 'atom';
1052          }
1053
1054          $f = $this->getFilters($attr);
1055          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor("feed","category/".'.
1056          '$_ctx->categories->cat_url."/'.$type.'")').'; ?>';
1057     }
1058
1059     /*dtd
1060     <!ELEMENT tpl:CategoryURL - O -- Category URL (complete iabsolute URL, including blog URL) -->
1061     */
1062     public function CategoryURL($attr)
1063     {
1064          $f = $this->getFilters($attr);
1065          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor("category",'.
1066               '$_ctx->categories->cat_url)').'; ?>';
1067     }
1068
1069     /*dtd
1070     <!ELEMENT tpl:CategoryShortURL - O -- Category short URL (relative URL, from /category/) -->
1071     */
1072     public function CategoryShortURL($attr)
1073     {
1074          $f = $this->getFilters($attr);
1075          return '<?php echo '.sprintf($f,'$_ctx->categories->cat_url').'; ?>';
1076     }
1077
1078     /*dtd
1079     <!ELEMENT tpl:CategoryDescription - O -- Category description -->
1080     */
1081     public function CategoryDescription($attr)
1082     {
1083          $f = $this->getFilters($attr);
1084          return '<?php echo '.sprintf($f,'$_ctx->categories->cat_desc').'; ?>';
1085     }
1086
1087     /*dtd
1088     <!ELEMENT tpl:CategoryTitle - O -- Category title -->
1089     */
1090     public function CategoryTitle($attr)
1091     {
1092          $f = $this->getFilters($attr);
1093          return '<?php echo '.sprintf($f,'$_ctx->categories->cat_title').'; ?>';
1094     }
1095
1096     /*dtd
1097     <!ELEMENT tpl:CategoryEntriesCount - O -- Category number of entries -->
1098     */
1099     public function CategoryEntriesCount($attr)
1100     {
1101          $f = $this->getFilters($attr);
1102          return $this->displayCounter(
1103               sprintf($f,'$_ctx->categories->nb_post'),
1104               array(
1105                    'none' => 'No post',
1106                    'one'  => 'One post',
1107                    'more' => '%d posts'
1108               ),
1109               $attr,
1110               true
1111          );
1112     }
1113
1114     /* Entries -------------------------------------------- */
1115     /*dtd
1116     <!ELEMENT tpl:Entries - - -- Blog Entries loop -->
1117     <!ATTLIST tpl:Entries
1118     lastn     CDATA     #IMPLIED  -- limit number of results to specified value
1119     author    CDATA     #IMPLIED  -- get entries for a given user id
1120     category  CDATA     #IMPLIED  -- get entries for specific categories only (multiple comma-separated categories can be specified. Use "!" as prefix to exclude a category)
1121     no_category    CDATA     #IMPLIED  -- get entries without category
1122     with_category  CDATA     #IMPLIED  -- get entries with category
1123     no_context (1|0)    #IMPLIED  -- Override context information
1124     sortby    (title|selected|author|date|id)    #IMPLIED  -- specify entries sort criteria (default : date) (multiple comma-separated sortby can be specified. Use "?asc" or "?desc" as suffix to provide an order for each sorby)
1125     order     (desc|asc)     #IMPLIED  -- specify entries order (default : desc)
1126     no_content     (0|1)     #IMPLIED  -- do not retrieve entries content
1127     selected  (0|1)     #IMPLIED  -- retrieve posts marked as selected only (value: 1) or not selected only (value: 0)
1128     url       CDATA     #IMPLIED  -- retrieve post by its url
1129     type      CDATA     #IMPLIED  -- retrieve post with given post_type (there can be many ones separated by comma)
1130     age       CDATA     #IMPLIED  -- retrieve posts by maximum age (ex: -2 days, last month, last week)
1131     ignore_pagination   (0|1)     #IMPLIED  -- ignore page number provided in URL (useful when using multiple tpl:Entries on the same page)
1132     >
1133     */
1134     public function Entries($attr,$content)
1135     {
1136          $lastn = -1;
1137          if (isset($attr['lastn'])) {
1138               $lastn = abs((integer) $attr['lastn'])+0;
1139          }
1140
1141          $p = 'if (!isset($_page_number)) { $_page_number = 1; }'."\n";
1142
1143          if ($lastn != 0) {
1144               // Set limit (aka nb of entries needed)
1145               if ($lastn > 0) {
1146                    // nb of entries per page specified in template -> regular pagination
1147                    $p .= "\$params['limit'] = ".$lastn.";\n";
1148                    $p .= "\$nb_entry_first_page = \$nb_entry_per_page = ".$lastn.";\n";
1149               } else {
1150                    // nb of entries per page not specified -> use ctx settings
1151                    $p .= "\$nb_entry_first_page=\$_ctx->nb_entry_first_page; \$nb_entry_per_page = \$_ctx->nb_entry_per_page;\n";
1152                    $p .= "if ((\$core->url->type == 'default') || (\$core->url->type == 'default-page')) {\n";
1153                    $p .= "    \$params['limit'] = (\$_page_number == 1 ? \$nb_entry_first_page : \$nb_entry_per_page);\n";
1154                    $p .= "} else {\n";
1155                    $p .= "    \$params['limit'] = \$nb_entry_per_page;\n";
1156                    $p .= "}\n";
1157               }
1158               // Set offset (aka index of first entry)
1159               if (!isset($attr['ignore_pagination']) || $attr['ignore_pagination'] == "0") {
1160                    // standard pagination, set offset
1161                    $p .= "if ((\$core->url->type == 'default') || (\$core->url->type == 'default-page')) {\n";
1162                    $p .= "    \$params['limit'] = array((\$_page_number == 1 ? 0 : (\$_page_number - 2) * \$nb_entry_per_page + \$nb_entry_first_page),\$params['limit']);\n";
1163                    $p .= "} else {\n";
1164                    $p .= "    \$params['limit'] = array((\$_page_number - 1) * \$nb_entry_per_page,\$params['limit']);\n";
1165                    $p .= "}\n";
1166               } else {
1167                    // no pagination, get all posts from 0 to limit
1168                    $p .= "\$params['limit'] = array(0, \$params['limit']);\n";
1169               }
1170          }
1171
1172          if (isset($attr['author'])) {
1173               $p .= "\$params['user_id'] = '".addslashes($attr['author'])."';\n";
1174          }
1175
1176          if (isset($attr['category'])) {
1177               $p .= "\$params['cat_url'] = '".addslashes($attr['category'])."';\n";
1178               $p .= "context::categoryPostParam(\$params);\n";
1179          }
1180
1181          if (isset($attr['with_category']) && $attr['with_category']) {
1182               $p .= "@\$params['sql'] .= ' AND P.cat_id IS NOT NULL ';\n";
1183          }
1184
1185          if (isset($attr['no_category']) && $attr['no_category']) {
1186               $p .= "@\$params['sql'] .= ' AND P.cat_id IS NULL ';\n";
1187               $p .= "unset(\$params['cat_url']);\n";
1188          }
1189
1190          if (!empty($attr['type'])) {
1191               $p .= "\$params['post_type'] = preg_split('/\s*,\s*/','".addslashes($attr['type'])."',-1,PREG_SPLIT_NO_EMPTY);\n";
1192          }
1193
1194          if (!empty($attr['url'])) {
1195               $p .= "\$params['post_url'] = '".addslashes($attr['url'])."';\n";
1196          }
1197
1198          if (empty($attr['no_context']))
1199          {
1200               if (!isset($attr['author']))
1201               {
1202                    $p .=
1203                    'if ($_ctx->exists("users")) { '.
1204                         "\$params['user_id'] = \$_ctx->users->user_id; ".
1205                    "}\n";
1206               }
1207
1208               if (!isset($attr['category']) && (!isset($attr['no_category']) || !$attr['no_category']))
1209               {
1210                    $p .=
1211                    'if ($_ctx->exists("categories")) { '.
1212                         "\$params['cat_id'] = \$_ctx->categories->cat_id.(\$core->blog->settings->system->inc_subcats?' ?sub':'');".
1213                    "}\n";
1214               }
1215
1216               $p .=
1217               'if ($_ctx->exists("archives")) { '.
1218                    "\$params['post_year'] = \$_ctx->archives->year(); ".
1219                    "\$params['post_month'] = \$_ctx->archives->month(); ";
1220               if (!isset($attr['lastn'])) {
1221                    $p .= "unset(\$params['limit']); ";
1222               }
1223               $p .=
1224               "}\n";
1225
1226               $p .=
1227               'if ($_ctx->exists("langs")) { '.
1228                    "\$params['post_lang'] = \$_ctx->langs->post_lang; ".
1229               "}\n";
1230
1231               $p .=
1232               'if (isset($_search)) { '.
1233                    "\$params['search'] = \$_search; ".
1234               "}\n";
1235          }
1236
1237          $p .= "\$params['order'] = '".$this->getSortByStr($attr,'post')."';\n";
1238
1239          if (isset($attr['no_content']) && $attr['no_content']) {
1240               $p .= "\$params['no_content'] = true;\n";
1241          }
1242
1243          if (isset($attr['selected'])) {
1244               $p .= "\$params['post_selected'] = ".(integer) (boolean) $attr['selected'].";";
1245          }
1246
1247          if (isset($attr['age'])) {
1248               $age = $this->getAge($attr);
1249               $p .= !empty($age) ? "@\$params['sql'] .= ' AND P.post_dt > \'".$age."\'';\n" : '';
1250          }
1251
1252          $res = "<?php\n";
1253          $res .= $p;
1254          $res .= $this->core->callBehavior("templatePrepareParams",
1255               array("tag" => "Entries","method" => "blog::getPosts"),
1256               $attr,$content);
1257          $res .= '$_ctx->post_params = $params;'."\n";
1258          $res .= '$_ctx->posts = $core->blog->getPosts($params); unset($params);'."\n";
1259          $res .= "?>\n";
1260          $res .=
1261          '<?php while ($_ctx->posts->fetch()) : ?>'.$content.'<?php endwhile; '.
1262          '$_ctx->posts = null; $_ctx->post_params = null; ?>';
1263
1264          return $res;
1265     }
1266
1267     /*dtd
1268     <!ELEMENT tpl:DateHeader - O -- Displays date, if post is the first post of the given day -->
1269     */
1270     public function DateHeader($attr,$content)
1271     {
1272          return
1273          "<?php if (\$_ctx->posts->firstPostOfDay()) : ?>".
1274          $content.
1275          "<?php endif; ?>";
1276     }
1277
1278     /*dtd
1279     <!ELEMENT tpl:DateFooter - O -- Displays date,  if post is the last post of the given day -->
1280     */
1281     public function DateFooter($attr,$content)
1282     {
1283          return
1284          "<?php if (\$_ctx->posts->lastPostOfDay()) : ?>".
1285          $content.
1286          "<?php endif; ?>";
1287     }
1288
1289     /*dtd
1290     <!ELEMENT tpl:EntryIf - - -- tests on current entry -->
1291     <!ATTLIST tpl:EntryIf
1292     type CDATA     #IMPLIED  -- post has a given type (default: "post")
1293     category  CDATA     #IMPLIED  -- post has a given category
1294     categories     CDATA     #IMPLIED  -- post has a one of given categories
1295     first     (0|1)     #IMPLIED  -- post is the first post from list (value : 1) or not (value : 0)
1296     odd  (0|1)     #IMPLIED  -- post is in an odd position (value : 1) or not (value : 0)
1297     even (0|1)     #IMPLIED  -- post is in an even position (value : 1) or not (value : 0)
1298     extended  (0|1)     #IMPLIED  -- post has an excerpt (value : 1) or not (value : 0)
1299     selected  (0|1)     #IMPLIED  -- post is selected (value : 1) or not (value : 0)
1300     has_category   (0|1)     #IMPLIED  -- post has a category (value : 1) or not (value : 0)
1301     has_attachment (0|1)     #IMPLIED  -- post has attachments (value : 1) or not (value : 0) (see Attachment plugin for code)
1302     comments_active     (0|1)     #IMPLIED  -- comments are active for this post (value : 1) or not (value : 0)
1303     pings_active   (0|1)     #IMPLIED  -- trackbacks are active for this post (value : 1) or not (value : 0)
1304     show_comments  (0|1)     #IMPLIED  -- there are comments for this post (value : 1) or not (value : 0)
1305     show_pings     (0|1)     #IMPLIED  -- there are trackbacks for this post (value : 1) or not (value : 0)
1306     republished    (0|1)     #IMPLIED  -- post has been updated since publication (value : 1) or not (value : 0)
1307     operator  (and|or)  #IMPLIED  -- combination of conditions, if more than 1 specifiec (default: and)
1308     url       CDATA     #IMPLIED  -- post has given url
1309     >
1310     */
1311     public function EntryIf($attr,$content)
1312     {
1313          $if = new ArrayObject();
1314          $extended = null;
1315          $hascategory = null;
1316
1317          $operator = isset($attr['operator']) ? $this->getOperator($attr['operator']) : '&&';
1318
1319          if (isset($attr['type'])) {
1320               $type = trim($attr['type']);
1321               $type = !empty($type)?$type:'post';
1322               $if[] = '$_ctx->posts->post_type == "'.addslashes($type).'"';
1323          }
1324
1325          if (isset($attr['url'])) {
1326               $url = trim($attr['url']);
1327               if (substr($url,0,1) == '!') {
1328                    $url = substr($url,1);
1329                    $if[] = '$_ctx->posts->post_url != "'.addslashes($url).'"';
1330               } else {
1331                    $if[] = '$_ctx->posts->post_url == "'.addslashes($url).'"';
1332               }
1333          }
1334
1335          if (isset($attr['category'])) {
1336               $category = addslashes(trim($attr['category']));
1337               if (substr($category,0,1) == '!') {
1338                    $category = substr($category,1);
1339                    $if[] = '($_ctx->posts->cat_url != "'.$category.'")';
1340               } else {
1341                    $if[] = '($_ctx->posts->cat_url == "'.$category.'")';
1342               }
1343          }
1344
1345          if (isset($attr['categories'])) {
1346               $categories = explode(',',addslashes(trim($attr['categories'])));
1347               if (is_array($categories) && count($categories)) {
1348                    foreach ($categories as $category) {
1349                         if (substr($category,0,1) == '!') {
1350                              $category = substr($category,1);
1351                              $if[] = '($_ctx->posts->cat_url != "'.$category.'")';
1352                         } else {
1353                              $if[] = '($_ctx->posts->cat_url == "'.$category.'")';
1354                         }
1355                    }
1356               }
1357          }
1358
1359          if (isset($attr['first'])) {
1360               $sign = (boolean) $attr['first'] ? '=' : '!';
1361               $if[] = '$_ctx->posts->index() '.$sign.'= 0';
1362          }
1363
1364          if (isset($attr['odd'])) {
1365               $sign = (boolean) $attr['odd'] ? '=' : '!';
1366               $if[] = '($_ctx->posts->index()+1)%2 '.$sign.'= 1';
1367          }
1368
1369          if (isset($attr['extended'])) {
1370               $sign = (boolean) $attr['extended'] ? '' : '!';
1371               $if[] = $sign.'$_ctx->posts->isExtended()';
1372          }
1373
1374          if (isset($attr['selected'])) {
1375               $sign = (boolean) $attr['selected'] ? '' : '!';
1376               $if[] = $sign.'(boolean)$_ctx->posts->post_selected';
1377          }
1378
1379          if (isset($attr['has_category'])) {
1380               $sign = (boolean) $attr['has_category'] ? '' : '!';
1381               $if[] = $sign.'$_ctx->posts->cat_id';
1382          }
1383
1384          if (isset($attr['comments_active'])) {
1385               $sign = (boolean) $attr['comments_active'] ? '' : '!';
1386               $if[] = $sign.'$_ctx->posts->commentsActive()';
1387          }
1388
1389          if (isset($attr['pings_active'])) {
1390               $sign = (boolean) $attr['pings_active'] ? '' : '!';
1391               $if[] = $sign.'$_ctx->posts->trackbacksActive()';
1392          }
1393
1394          if (isset($attr['has_comment'])) {
1395               $sign = (boolean) $attr['has_comment'] ? '' : '!';
1396               $if[] = $sign.'$_ctx->posts->hasComments()';
1397          }
1398
1399          if (isset($attr['has_ping'])) {
1400               $sign = (boolean) $attr['has_ping'] ? '' : '!';
1401               $if[] = $sign.'$_ctx->posts->hasTrackbacks()';
1402          }
1403
1404          if (isset($attr['show_comments'])) {
1405               if ((boolean) $attr['show_comments']) {
1406                    $if[] = '($_ctx->posts->hasComments() || $_ctx->posts->commentsActive())';
1407               } else {
1408                    $if[] = '(!$_ctx->posts->hasComments() && !$_ctx->posts->commentsActive())';
1409               }
1410          }
1411
1412          if (isset($attr['show_pings'])) {
1413               if ((boolean) $attr['show_pings']) {
1414                    $if[] = '($_ctx->posts->hasTrackbacks() || $_ctx->posts->trackbacksActive())';
1415               } else {
1416                    $if[] = '(!$_ctx->posts->hasTrackbacks() && !$_ctx->posts->trackbacksActive())';
1417               }
1418          }
1419
1420          if (isset($attr['republished'])) {
1421               $sign = (boolean) $attr['republished'] ? '' : '!';
1422               $if[] = $sign.'(boolean)$_ctx->posts->isRepublished()';
1423          }
1424
1425          $this->core->callBehavior('tplIfConditions','EntryIf',$attr,$content,$if);
1426
1427          if (count($if) != 0) {
1428               return '<?php if('.implode(' '.$operator.' ', (array) $if).') : ?>'.$content.'<?php endif; ?>';
1429          } else {
1430               return $content;
1431          }
1432     }
1433
1434     /*dtd
1435     <!ELEMENT tpl:EntryIfFirst - O -- displays value if entry is the first one -->
1436     <!ATTLIST tpl:EntryIfFirst
1437     return    CDATA     #IMPLIED  -- value to display in case of success (default: first)
1438     >
1439     */
1440     public function EntryIfFirst($attr)
1441     {
1442          $ret = isset($attr['return']) ? $attr['return'] : 'first';
1443          $ret = html::escapeHTML($ret);
1444
1445          return
1446          '<?php if ($_ctx->posts->index() == 0) { '.
1447          "echo '".addslashes($ret)."'; } ?>";
1448     }
1449
1450     /*dtd
1451     <!ELEMENT tpl:EntryIfOdd - O -- displays value if entry is in an odd position -->
1452     <!ATTLIST tpl:EntryIfOdd
1453     return    CDATA     #IMPLIED  -- value to display in case of success (default: odd)
1454     >
1455     */
1456     public function EntryIfOdd($attr)
1457     {
1458          $ret = isset($attr['return']) ? $attr['return'] : 'odd';
1459          $ret = html::escapeHTML($ret);
1460
1461          return
1462          '<?php if (($_ctx->posts->index()+1)%2 == 1) { '.
1463          "echo '".addslashes($ret)."'; } ?>";
1464     }
1465
1466     /*dtd
1467     <!ELEMENT tpl:EntryIfSelected - O -- displays value if entry is selected -->
1468     <!ATTLIST tpl:EntryIfSelected
1469     return    CDATA     #IMPLIED  -- value to display in case of success (default: selected)
1470     >
1471     */
1472     public function EntryIfSelected($attr)
1473     {
1474          $ret = isset($attr['return']) ? $attr['return'] : 'selected';
1475          $ret = html::escapeHTML($ret);
1476
1477          return
1478          '<?php if ($_ctx->posts->post_selected) { '.
1479          "echo '".addslashes($ret)."'; } ?>";
1480     }
1481
1482     /*dtd
1483     <!ELEMENT tpl:EntryContent -  -- Entry content -->
1484     <!ATTLIST tpl:EntryContent
1485     absolute_urls  CDATA     #IMPLIED -- transforms local URLs to absolute one
1486     full           (1|0)     #IMPLIED -- returns full content with excerpt
1487     >
1488     */
1489     public function EntryContent($attr)
1490     {
1491          $urls = '0';
1492          if (!empty($attr['absolute_urls'])) {
1493               $urls = '1';
1494          }
1495
1496          $f = $this->getFilters($attr);
1497
1498          if (!empty($attr['full'])) {
1499               return '<?php echo '.sprintf($f,
1500                    '$_ctx->posts->getExcerpt('.$urls.')." ".$_ctx->posts->getContent('.$urls.')').'; ?>';
1501          } else {
1502               return '<?php echo '.sprintf($f,'$_ctx->posts->getContent('.$urls.')').'; ?>';
1503          }
1504     }
1505
1506     /*dtd
1507     <!ELEMENT tpl:EntryIfContentCut - - -- Test if Entry content has been cut -->
1508     <!ATTLIST tpl:EntryIfContentCut
1509     absolute_urls  CDATA     #IMPLIED -- transforms local URLs to absolute one
1510     full           (1|0)     #IMPLIED -- test with full content and excerpt
1511     >
1512     */
1513     public function EntryIfContentCut($attr,$content)
1514     {
1515          if (empty($attr['cut_string']) || !empty($attr['full'])) {
1516               return '';
1517          }
1518
1519          $urls = '0';
1520          if (!empty($attr['absolute_urls'])) {
1521               $urls = '1';
1522          }
1523
1524          $short = $this->getFilters($attr);
1525          $cut = $attr['cut_string'];
1526          $attr['cut_string'] = 0;
1527          $full = $this->getFilters($attr);
1528          $attr['cut_string'] = $cut;
1529
1530          return '<?php if (strlen('.sprintf($full,'$_ctx->posts->getContent('.$urls.')').') > '.
1531               'strlen('.sprintf($short,'$_ctx->posts->getContent('.$urls.')').')) : ?>'.
1532               $content.
1533               '<?php endif; ?>';
1534     }
1535
1536     /*dtd
1537     <!ELEMENT tpl:EntryExcerpt - O -- Entry excerpt -->
1538     <!ATTLIST tpl:EntryExcerpt
1539     absolute_urls  CDATA     #IMPLIED -- transforms local URLs to absolute one
1540     >
1541     */
1542     public function EntryExcerpt($attr)
1543     {
1544          $urls = '0';
1545          if (!empty($attr['absolute_urls'])) {
1546               $urls = '1';
1547          }
1548
1549          $f = $this->getFilters($attr);
1550          return '<?php echo '.sprintf($f,'$_ctx->posts->getExcerpt('.$urls.')').'; ?>';
1551     }
1552
1553
1554     /*dtd
1555     <!ELEMENT tpl:EntryAuthorCommonName - O -- Entry author common name -->
1556     */
1557     public function EntryAuthorCommonName($attr)
1558     {
1559          $f = $this->getFilters($attr);
1560          return '<?php echo '.sprintf($f,'$_ctx->posts->getAuthorCN()').'; ?>';
1561     }
1562
1563     /*dtd
1564     <!ELEMENT tpl:EntryAuthorDisplayName - O -- Entry author display name -->
1565     */
1566     public function EntryAuthorDisplayName($attr)
1567     {
1568          $f = $this->getFilters($attr);
1569          return '<?php echo '.sprintf($f,'$_ctx->posts->user_displayname').'; ?>';
1570     }
1571
1572     /*dtd
1573     <!ELEMENT tpl:EntryAuthorID - O -- Entry author ID -->
1574     */
1575     public function EntryAuthorID($attr)
1576     {
1577          $f = $this->getFilters($attr);
1578          return '<?php echo '.sprintf($f,'$_ctx->posts->user_id').'; ?>';
1579     }
1580
1581     /*dtd
1582     <!ELEMENT tpl:EntryAuthorEmail - O -- Entry author email -->
1583     <!ATTLIST tpl:EntryAuthorEmail
1584     spam_protected (0|1)     #IMPLIED  -- protect email from spam (default: 1)
1585     >
1586     */
1587     public function EntryAuthorEmail($attr)
1588     {
1589          $p = 'true';
1590          if (isset($attr['spam_protected']) && !$attr['spam_protected']) {
1591               $p = 'false';
1592          }
1593
1594          $f = $this->getFilters($attr);
1595          return '<?php echo '.sprintf($f,"\$_ctx->posts->getAuthorEmail(".$p.")").'; ?>';
1596     }
1597
1598     /*dtd
1599     <!ELEMENT tpl:EntryAuthorEmailMD5 - O -- Entry author email MD5 sum -->
1600     >
1601     */
1602     public function EntryAuthorEmailMD5($attr)
1603     {
1604          $f = $this->getFilters($attr);
1605          return '<?php echo '.sprintf($f,'md5($_ctx->posts->getAuthorEmail(false))').'; ?>';
1606     }
1607
1608     /*dtd
1609     <!ELEMENT tpl:EntryAuthorLink - O -- Entry author link -->
1610     */
1611     public function EntryAuthorLink($attr)
1612     {
1613          $f = $this->getFilters($attr);
1614          return '<?php echo '.sprintf($f,'$_ctx->posts->getAuthorLink()').'; ?>';
1615     }
1616
1617     /*dtd
1618     <!ELEMENT tpl:EntryAuthorURL - O -- Entry author URL -->
1619     */
1620     public function EntryAuthorURL($attr)
1621     {
1622          $f = $this->getFilters($attr);
1623          return '<?php echo '.sprintf($f,'$_ctx->posts->user_url').'; ?>';
1624     }
1625
1626     /*dtd
1627     <!ELEMENT tpl:EntryBasename - O -- Entry short URL (relative to /post) -->
1628     */
1629     public function EntryBasename($attr)
1630     {
1631          $f = $this->getFilters($attr);
1632          return '<?php echo '.sprintf($f,'$_ctx->posts->post_url').'; ?>';
1633     }
1634
1635     /*dtd
1636     <!ELEMENT tpl:EntryCategory - O -- Entry category (full name) -->
1637     */
1638     public function EntryCategory($attr)
1639     {
1640          $f = $this->getFilters($attr);
1641          return '<?php echo '.sprintf($f,'$_ctx->posts->cat_title').'; ?>';
1642     }
1643
1644     /*dtd
1645     <!ELEMENT tpl:EntryCategoryDescription - O -- Entry category description -->
1646     */
1647     public function EntryCategoryDescription($attr)
1648     {
1649          $f = $this->getFilters($attr);
1650          return '<?php echo '.sprintf($f,'$_ctx->posts->cat_desc').'; ?>';
1651     }
1652
1653     /*dtd
1654     <!ELEMENT tpl:EntryCategoriesBreadcrumb - - -- Current entry parents loop (without last one) -->
1655     */
1656     public function EntryCategoriesBreadcrumb($attr,$content)
1657     {
1658          return
1659          "<?php\n".
1660          '$_ctx->categories = $core->blog->getCategoryParents($_ctx->posts->cat_id);'."\n".
1661          'while ($_ctx->categories->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->categories = null; ?>';
1662     }
1663
1664     /*dtd
1665     <!ELEMENT tpl:EntryCategoryID - O -- Entry category ID -->
1666     */
1667     public function EntryCategoryID($attr)
1668     {
1669          $f = $this->getFilters($attr);
1670          return '<?php echo '.sprintf($f,'$_ctx->posts->cat_id').'; ?>';
1671     }
1672
1673     /*dtd
1674     <!ELEMENT tpl:EntryCategoryURL - O -- Entry category URL -->
1675     */
1676     public function EntryCategoryURL($attr)
1677     {
1678          $f = $this->getFilters($attr);
1679          return '<?php echo '.sprintf($f,'$_ctx->posts->getCategoryURL()').'; ?>';
1680     }
1681
1682     /*dtd
1683     <!ELEMENT tpl:EntryCategoryShortURL - O -- Entry category short URL (relative URL, from /category/) -->
1684     */
1685     public function EntryCategoryShortURL($attr)
1686     {
1687          $f = $this->getFilters($attr);
1688          return '<?php echo '.sprintf($f,'$_ctx->posts->cat_url').'; ?>';
1689     }
1690
1691
1692     /*dtd
1693     <!ELEMENT tpl:EntryFeedID - O -- Entry feed ID -->
1694     */
1695     public function EntryFeedID($attr)
1696     {
1697          $f = $this->getFilters($attr);
1698          return '<?php echo '.sprintf($f,'$_ctx->posts->getFeedID()').'; ?>';
1699     }
1700
1701     /*dtd
1702     <!ELEMENT tpl:EntryFirstImage - O -- Extracts entry first image if exists -->
1703     <!ATTLIST tpl:EntryAuthorEmail
1704     size           (sq|t|s|m|o)   #IMPLIED  -- Image size to extract
1705     class          CDATA          #IMPLIED  -- Class to add on image tag
1706     with_category  (1|0)          #IMPLIED  -- Search in entry category description if present (default 0)
1707     no_tag    (1|0)     #IMPLIED  -- Return image URL without HTML tag (default 0)
1708     content_only   (1|0)          #IMPLIED  -- Search in content entry only, not in excerpt (default 0)
1709     cat_only  (1|0)          #IMPLIED  -- Search in category description only (default 0)
1710     >
1711     */
1712     public function EntryFirstImage($attr)
1713     {
1714          $size = !empty($attr['size']) ? $attr['size'] : '';
1715          $class = !empty($attr['class']) ? $attr['class'] : '';
1716          $with_category = !empty($attr['with_category']) ? 1 : 0;
1717          $no_tag = !empty($attr['no_tag']) ? 1 : 0;
1718          $content_only = !empty($attr['content_only']) ? 1 : 0;
1719          $cat_only = !empty($attr['cat_only']) ? 1 : 0;
1720
1721          return "<?php echo context::EntryFirstImageHelper('".addslashes($size)."',".$with_category.",'".addslashes($class)."',".
1722               $no_tag.",".$content_only.",".$cat_only."); ?>";
1723     }
1724
1725     /*dtd
1726     <!ELEMENT tpl:EntryID - O -- Entry ID -->
1727     */
1728     public function EntryID($attr)
1729     {
1730          $f = $this->getFilters($attr);
1731          return '<?php echo '.sprintf($f,'$_ctx->posts->post_id').'; ?>';
1732     }
1733
1734     /*dtd
1735     <!ELEMENT tpl:EntryLang - O --  Entry language or blog lang if not defined -->
1736     */
1737     public function EntryLang($attr)
1738     {
1739          $f = $this->getFilters($attr);
1740          return
1741          '<?php if ($_ctx->posts->post_lang) { '.
1742               'echo '.sprintf($f,'$_ctx->posts->post_lang').'; '.
1743          '} else {'.
1744               'echo '.sprintf($f,'$core->blog->settings->system->lang').'; '.
1745          '} ?>';
1746     }
1747
1748     /*dtd
1749     <!ELEMENT tpl:EntryNext - - -- Next entry block -->
1750     <!ATTLIST tpl:EntryNext
1751     restrict_to_category     (0|1)     #IMPLIED  -- find next post in the same category (default: 0)
1752     restrict_to_lang         (0|1)     #IMPLIED  -- find next post in the same language (default: 0)
1753     >
1754     */
1755     public function EntryNext($attr,$content)
1756     {
1757          $restrict_to_category = !empty($attr['restrict_to_category']) ? '1' : '0';
1758          $restrict_to_lang = !empty($attr['restrict_to_lang']) ? '1' : '0';
1759
1760          return
1761          '<?php $next_post = $core->blog->getNextPost($_ctx->posts,1,'.$restrict_to_category.','.$restrict_to_lang.'); ?>'."\n".
1762          '<?php if ($next_post !== null) : ?>'.
1763
1764               '<?php $_ctx->posts = $next_post; unset($next_post);'."\n".
1765               'while ($_ctx->posts->fetch()) : ?>'.
1766               $content.
1767               '<?php endwhile; $_ctx->posts = null; ?>'.
1768          "<?php endif; ?>\n";
1769     }
1770
1771     /*dtd
1772     <!ELEMENT tpl:EntryPrevious - - -- Previous entry block -->
1773     <!ATTLIST tpl:EntryPrevious
1774     restrict_to_category     (0|1)     #IMPLIED  -- find previous post in the same category (default: 0)
1775     restrict_to_lang         (0|1)     #IMPLIED  -- find next post in the same language (default: 0)
1776     >
1777     */
1778     public function EntryPrevious($attr,$content)
1779     {
1780          $restrict_to_category = !empty($attr['restrict_to_category']) ? '1' : '0';
1781          $restrict_to_lang = !empty($attr['restrict_to_lang']) ? '1' : '0';
1782
1783          return
1784          '<?php $prev_post = $core->blog->getNextPost($_ctx->posts,-1,'.$restrict_to_category.','.$restrict_to_lang.'); ?>'."\n".
1785          '<?php if ($prev_post !== null) : ?>'.
1786
1787               '<?php $_ctx->posts = $prev_post; unset($prev_post);'."\n".
1788               'while ($_ctx->posts->fetch()) : ?>'.
1789               $content.
1790               '<?php endwhile; $_ctx->posts = null; ?>'.
1791          "<?php endif; ?>\n";
1792     }
1793
1794     /*dtd
1795     <!ELEMENT tpl:EntryTitle - O -- Entry title -->
1796     */
1797     public function EntryTitle($attr)
1798     {
1799          $f = $this->getFilters($attr);
1800          return '<?php echo '.sprintf($f,'$_ctx->posts->post_title').'; ?>';
1801     }
1802
1803     /*dtd
1804     <!ELEMENT tpl:EntryURL - O -- Entry URL -->
1805     */
1806     public function EntryURL($attr)
1807     {
1808          $f = $this->getFilters($attr);
1809          return '<?php echo '.sprintf($f,'$_ctx->posts->getURL()').'; ?>';
1810     }
1811
1812     /*dtd
1813     <!ELEMENT tpl:EntryDate - O -- Entry date -->
1814     <!ATTLIST tpl:EntryDate
1815     format    CDATA     #IMPLIED  -- date format (encoded in dc:str by default if iso8601 or rfc822 not specified)
1816     iso8601   CDATA     #IMPLIED  -- if set, tells that date format is ISO 8601
1817     rfc822    CDATA     #IMPLIED  -- if set, tells that date format is RFC 822
1818     upddt     CDATA     #IMPLIED  -- if set, uses the post update time
1819     creadt    CDATA     #IMPLIED  -- if set, uses the post creation time
1820     >
1821     */
1822     public function EntryDate($attr)
1823     {
1824          $format = '';
1825          if (!empty($attr['format'])) {
1826               $format = addslashes($attr['format']);
1827          }
1828
1829          $iso8601 = !empty($attr['iso8601']);
1830          $rfc822 = !empty($attr['rfc822']);
1831          $type = (!empty($attr['creadt']) ? 'creadt' : '');
1832          $type = (!empty($attr['upddt']) ? 'upddt' : $type);
1833
1834          $f = $this->getFilters($attr);
1835
1836          if ($rfc822) {
1837               return '<?php echo '.sprintf($f,"\$_ctx->posts->getRFC822Date('".$type."')").'; ?>';
1838          } elseif ($iso8601) {
1839               return '<?php echo '.sprintf($f,"\$_ctx->posts->getISO8601Date('".$type."')").'; ?>';
1840          } else {
1841               return '<?php echo '.sprintf($f,"\$_ctx->posts->getDate('".$format."','".$type."')").'; ?>';
1842          }
1843     }
1844
1845     /*dtd
1846     <!ELEMENT tpl:EntryTime - O -- Entry date -->
1847     <!ATTLIST tpl:EntryTime
1848     format    CDATA     #IMPLIED  -- time format
1849     upddt     CDATA     #IMPLIED  -- if set, uses the post update time
1850     creadt    CDATA     #IMPLIED  -- if set, uses the post creation time
1851     >
1852     */
1853     public function EntryTime($attr)
1854     {
1855          $format = '';
1856          if (!empty($attr['format'])) {
1857               $format = addslashes($attr['format']);
1858          }
1859
1860          $type = (!empty($attr['creadt']) ? 'creadt' : '');
1861          $type = (!empty($attr['upddt']) ? 'upddt' : $type);
1862
1863          $f = $this->getFilters($attr);
1864          return '<?php echo '.sprintf($f,"\$_ctx->posts->getTime('".$format."','".$type."')").'; ?>';
1865     }
1866
1867     /*dtd
1868     <!ELEMENT tpl:EntriesHeader - - -- First entries result container -->
1869     */
1870     public function EntriesHeader($attr,$content)
1871     {
1872          return
1873          "<?php if (\$_ctx->posts->isStart()) : ?>".
1874          $content.
1875          "<?php endif; ?>";
1876     }
1877
1878     /*dtd
1879     <!ELEMENT tpl:EntriesFooter - - -- Last entries result container -->
1880     */
1881     public function EntriesFooter($attr,$content)
1882     {
1883          return
1884          "<?php if (\$_ctx->posts->isEnd()) : ?>".
1885          $content.
1886          "<?php endif; ?>";
1887     }
1888
1889
1890
1891
1892     /*dtd
1893     <!ELEMENT tpl:EntryCommentCount - O -- Number of comments for entry -->
1894     <!ATTLIST tpl:EntryCommentCount
1895     none      CDATA     #IMPLIED  -- text to display for "no comments" (default: no comments)
1896     one       CDATA     #IMPLIED  -- text to display for "one comment" (default: one comment)
1897     more      CDATA     #IMPLIED  -- text to display for "more comments" (default: %s comments, %s is replaced by the number of comment)
1898     count_all CDATA     #IMPLIED  -- count comments and trackbacks
1899     >
1900     */
1901     public function EntryCommentCount($attr)
1902     {
1903          if (empty($attr['count_all'])) {
1904               $operation = '$_ctx->posts->nb_comment';
1905          } else {
1906               $operation = '($_ctx->posts->nb_comment + $_ctx->posts->nb_trackback)';
1907          }
1908
1909          return $this->displayCounter(
1910               $operation,
1911               array(
1912                    'none' => 'no comments',
1913                    'one'  => 'one comment',
1914                    'more' => '%d comments'
1915                    ),
1916               $attr,
1917               false
1918          );
1919     }
1920
1921     /*dtd
1922     <!ELEMENT tpl:EntryPingCount - O -- Number of trackbacks for entry -->
1923     <!ATTLIST tpl:EntryPingCount
1924     none CDATA     #IMPLIED  -- text to display for "no pings" (default: no pings)
1925     one  CDATA     #IMPLIED  -- text to display for "one ping" (default: one ping)
1926     more CDATA     #IMPLIED  -- text to display for "more pings" (default: %s trackbacks, %s is replaced by the number of pings)
1927     >
1928     */
1929     public function EntryPingCount($attr)
1930     {
1931          return $this->displayCounter(
1932               '$_ctx->posts->nb_trackback',
1933               array(
1934                    'none' => 'no trackbacks',
1935                    'one'  => 'one trackback',
1936                    'more' => '%d trackbacks'
1937                    ),
1938               $attr,
1939               false
1940          );
1941     }
1942
1943     /*dtd
1944     <!ELEMENT tpl:EntryPingData - O -- Display trackback RDF information -->
1945     */
1946     public function EntryPingData($attr)
1947     {
1948          $format = !empty($attr['format']) && $attr['format'] == 'xml' ? 'xml' : 'html';
1949          return "<?php if (\$_ctx->posts->trackbacksActive()) { echo \$_ctx->posts->getTrackbackData('".$format."'); } ?>\n";
1950     }
1951
1952     /*dtd
1953     <!ELEMENT tpl:EntryPingLink - O -- Entry trackback link -->
1954     */
1955     public function EntryPingLink($attr)
1956     {
1957          return "<?php if (\$_ctx->posts->trackbacksActive()) { echo \$_ctx->posts->getTrackbackLink(); } ?>\n";
1958     }
1959
1960     /* Languages -------------------------------------- */
1961     /*dtd
1962     <!ELEMENT tpl:Languages - - -- Languages loop -->
1963     <!ATTLIST tpl:Languages
1964     lang CDATA     #IMPLIED  -- restrict loop on given lang
1965     order     (desc|asc)     #IMPLIED  -- languages ordering (default: desc)
1966     >
1967     */
1968     public function Languages($attr,$content)
1969     {
1970          $p = "if (!isset(\$params)) \$params = array();\n";
1971
1972          if (isset($attr['lang'])) {
1973               $p = "\$params['lang'] = '".addslashes($attr['lang'])."';\n";
1974          }
1975
1976          $order = 'desc';
1977          if (isset($attr['order']) && preg_match('/^(desc|asc)$/i',$attr['order'])) {
1978               $p .= "\$params['order'] = '".$attr['order']."';\n ";
1979          }
1980
1981          $res = "<?php\n";
1982          $res .= $p;
1983          $res .= $this->core->callBehavior("templatePrepareParams",
1984               array("tag" => "Languages","method" => "blog::getLangs"),
1985               $attr,$content);
1986          $res .= '$_ctx->langs = $core->blog->getLangs($params); unset($params);'."\n";
1987          $res .= "?>\n";
1988
1989          $res .=
1990          '<?php if ($_ctx->langs->count() > 1) : '.
1991          'while ($_ctx->langs->fetch()) : ?>'.$content.
1992          '<?php endwhile; $_ctx->langs = null; endif; ?>';
1993
1994          return $res;
1995     }
1996
1997     /*dtd
1998     <!ELEMENT tpl:LanguagesHeader - - -- First languages result container -->
1999     */
2000     public function LanguagesHeader($attr,$content)
2001     {
2002          return
2003          "<?php if (\$_ctx->langs->isStart()) : ?>".
2004          $content.
2005          "<?php endif; ?>";
2006     }
2007
2008     /*dtd
2009     <!ELEMENT tpl:LanguagesFooter - - -- Last languages result container -->
2010     */
2011     public function LanguagesFooter($attr,$content)
2012     {
2013          return
2014          "<?php if (\$_ctx->langs->isEnd()) : ?>".
2015          $content.
2016          "<?php endif; ?>";
2017     }
2018
2019     /*dtd
2020     <!ELEMENT tpl:LanguageCode - O -- Language code -->
2021     */
2022     public function LanguageCode($attr)
2023     {
2024          $f = $this->getFilters($attr);
2025          return '<?php echo '.sprintf($f,'$_ctx->langs->post_lang').'; ?>';
2026     }
2027
2028     /*dtd
2029     <!ELEMENT tpl:LanguageIfCurrent - - -- tests if post language is current language -->
2030     */
2031     public function LanguageIfCurrent($attr,$content)
2032     {
2033          return
2034          "<?php if (\$_ctx->cur_lang == \$_ctx->langs->post_lang) : ?>".
2035          $content.
2036          "<?php endif; ?>";
2037     }
2038
2039     /*dtd
2040     <!ELEMENT tpl:LanguageURL - O -- Language URL -->
2041     */
2042     public function LanguageURL($attr)
2043     {
2044          $f = $this->getFilters($attr);
2045          return '<?php echo '.sprintf($f,'$core->blog->url.$core->url->getURLFor("lang",'.
2046               '$_ctx->langs->post_lang)').'; ?>';
2047     }
2048
2049     /* Pagination ------------------------------------- */
2050     /*dtd
2051     <!ELEMENT tpl:Pagination - - -- Pagination container -->
2052     <!ATTLIST tpl:Pagination
2053     no_context     (0|1)     #IMPLIED  -- override test on posts count vs number of posts per page
2054     >
2055     */
2056     public function Pagination($attr,$content)
2057     {
2058          $p = "<?php\n";
2059          $p .= '$params = $_ctx->post_params;'."\n";
2060          $p .= $this->core->callBehavior("templatePrepareParams",
2061               array("tag" => "Pagination","method" => "blog::getPosts"),
2062               $attr,$content);
2063          $p .= '$_ctx->pagination = $core->blog->getPosts($params,true); unset($params);'."\n";
2064          $p .= "?>\n";
2065
2066          if (isset($attr['no_context']) && $attr['no_context']) {
2067               return $p.$content;
2068          }
2069
2070          return
2071               $p.
2072               '<?php if ($_ctx->pagination->f(0) > $_ctx->posts->count()) : ?>'.
2073               $content.
2074               '<?php endif; ?>';
2075     }
2076
2077     /*dtd
2078     <!ELEMENT tpl:PaginationCounter - O -- Number of pages -->
2079     */
2080     public function PaginationCounter($attr)
2081     {
2082          $f = $this->getFilters($attr);
2083          return '<?php echo '.sprintf($f,"context::PaginationNbPages()").'; ?>';
2084     }
2085
2086     /*dtd
2087     <!ELEMENT tpl:PaginationCurrent - O -- current page -->
2088     */
2089     public function PaginationCurrent($attr)
2090     {
2091          $offset = 0;
2092          if (isset($attr['offset'])) {
2093               $offset = (integer) $attr['offset'];
2094          }
2095
2096          $f = $this->getFilters($attr);
2097          return '<?php echo '.sprintf($f,"context::PaginationPosition(".$offset.")").'; ?>';
2098     }
2099
2100     /*dtd
2101     <!ELEMENT tpl:PaginationIf - - -- pages tests -->
2102     <!ATTLIST tpl:PaginationIf
2103     start     (0|1)     #IMPLIED  -- test if we are at first page (value : 1) or not (value : 0)
2104     end  (0|1)     #IMPLIED  -- test if we are at last page (value : 1) or not (value : 0)
2105     >
2106     */
2107     public function PaginationIf($attr,$content)
2108     {
2109          $if = array();
2110
2111          if (isset($attr['start'])) {
2112               $sign = (boolean) $attr['start'] ? '' : '!';
2113               $if[] = $sign.'context::PaginationStart()';
2114          }
2115
2116          if (isset($attr['end'])) {
2117               $sign = (boolean) $attr['end'] ? '' : '!';
2118               $if[] = $sign.'context::PaginationEnd()';
2119          }
2120
2121          $this->core->callBehavior('tplIfConditions','PaginationIf',$attr,$content,$if);
2122
2123          if (count($if) != 0) {
2124               return '<?php if('.implode(' && ', (array) $if).') : ?>'.$content.'<?php endif; ?>';
2125          } else {
2126               return $content;
2127          }
2128     }
2129
2130     /*dtd
2131     <!ELEMENT tpl:PaginationURL - O -- link to previoux/next page -->
2132     <!ATTLIST tpl:PaginationURL
2133     offset    CDATA     #IMPLIED  -- page offset (negative for previous pages), default: 0
2134     >
2135     */
2136     public function PaginationURL($attr)
2137     {
2138          $offset = 0;
2139          if (isset($attr['offset'])) {
2140               $offset = (integer) $attr['offset'];
2141          }
2142
2143          $f = $this->getFilters($attr);
2144          return '<?php echo '.sprintf($f,"context::PaginationURL(".$offset.")").'; ?>';
2145     }
2146
2147     /* Comments --------------------------------------- */
2148     /*dtd
2149     <!ELEMENT tpl:Comments - - -- Comments container -->
2150     <!ATTLIST tpl:Comments
2151     with_pings     (0|1)     #IMPLIED  -- include trackbacks in request
2152     lastn     CDATA     #IMPLIED  -- restrict the number of entries
2153     no_context (1|0)         #IMPLIED  -- Override context information
2154     sortby    (title|selected|author|date|id)    #IMPLIED  -- specify comments sort criteria (default : date) (multiple comma-separated sortby can be specified. Use "?asc" or "?desc" as suffix to provide an order for each sorby)
2155     order     (desc|asc)     #IMPLIED  -- result ordering (default: asc)
2156     age       CDATA     #IMPLIED  -- retrieve comments by maximum age (ex: -2 days, last month, last week)
2157     >
2158     */
2159     public function Comments($attr,$content)
2160     {
2161          $p = "";
2162          if (empty($attr['with_pings'])) {
2163               $p .= "\$params['comment_trackback'] = false;\n";
2164          }
2165
2166          $lastn = 0;
2167          if (isset($attr['lastn'])) {
2168               $lastn = abs((integer) $attr['lastn'])+0;
2169          }
2170
2171          if ($lastn > 0) {
2172               $p .= "\$params['limit'] = ".$lastn.";\n";
2173          } else {
2174               $p .= "if (\$_ctx->nb_comment_per_page !== null) { \$params['limit'] = \$_ctx->nb_comment_per_page; }\n";
2175          }
2176
2177          if (empty($attr['no_context']))
2178          {
2179               $p .=
2180               "if (\$_ctx->posts !== null) { ".
2181                    "\$params['post_id'] = \$_ctx->posts->post_id; ".
2182                    "\$core->blog->withoutPassword(false);\n".
2183               "}\n";
2184               $p .=
2185               'if ($_ctx->exists("categories")) { '.
2186                    "\$params['cat_id'] = \$_ctx->categories->cat_id; ".
2187               "}\n";
2188
2189               $p .=
2190               'if ($_ctx->exists("langs")) { '.
2191                    "\$params['sql'] = \"AND P.post_lang = '\".\$core->blog->con->escape(\$_ctx->langs->post_lang).\"' \"; ".
2192               "}\n";
2193          }
2194
2195          if (!isset($attr['order'])) {
2196               $attr['order'] = 'asc';
2197          }
2198
2199          $p .= "\$params['order'] = '".$this->getSortByStr($attr,'comment')."';\n";
2200
2201          if (isset($attr['no_content']) && $attr['no_content']) {
2202               $p .= "\$params['no_content'] = true;\n";
2203          }
2204
2205          if (isset($attr['age'])) {
2206               $age = $this->getAge($attr);
2207               $p .= !empty($age) ? "@\$params['sql'] .= ' AND P.post_dt > \'".$age."\'';\n" : '';
2208          }
2209
2210          $res = "<?php\n";
2211          $res .= $this->core->callBehavior("templatePrepareParams",
2212               array("tag" => "Comments","method" => "blog::getComments"),
2213               $attr,$content);
2214          $res .= $p;
2215          $res .= '$_ctx->comments = $core->blog->getComments($params); unset($params);'."\n";
2216          $res .= "if (\$_ctx->posts !== null) { \$core->blog->withoutPassword(true);}\n";
2217
2218          if (!empty($attr['with_pings'])) {
2219               $res .= '$_ctx->pings = $_ctx->comments;'."\n";
2220          }
2221
2222          $res .= "?>\n";
2223
2224          $res .=
2225          '<?php while ($_ctx->comments->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->comments = null; ?>';
2226
2227          return $res;
2228     }
2229
2230     /*dtd
2231     <!ELEMENT tpl:CommentAuthor - O -- Comment author -->
2232     */
2233     public function CommentAuthor($attr)
2234     {
2235          $f = $this->getFilters($attr);
2236          return '<?php echo '.sprintf($f,"\$_ctx->comments->comment_author").'; ?>';
2237     }
2238
2239     /*dtd
2240     <!ELEMENT tpl:CommentAuthorDomain - O -- Comment author website domain -->
2241     */
2242     public function CommentAuthorDomain($attr)
2243     {
2244          return '<?php echo preg_replace("#^http(?:s?)://(.+?)/.*$#msu",\'$1\',$_ctx->comments->comment_site); ?>';
2245     }
2246
2247     /*dtd
2248     <!ELEMENT tpl:CommentAuthorLink - O -- Comment author link -->
2249     */
2250     public function CommentAuthorLink($attr)
2251     {
2252          $f = $this->getFilters($attr);
2253          return '<?php echo '.sprintf($f,'$_ctx->comments->getAuthorLink()').'; ?>';
2254     }
2255
2256     /*dtd
2257     <!ELEMENT tpl:CommentAuthorMailMD5 - O -- Comment author email MD5 sum -->
2258     */
2259     public function CommentAuthorMailMD5($attr)
2260     {
2261          return '<?php echo md5($_ctx->comments->comment_email) ; ?>';
2262     }
2263
2264     /*dtd
2265     <!ELEMENT tpl:CommentAuthorURL - O -- Comment author URL -->
2266     */
2267     public function CommentAuthorURL($attr)
2268     {
2269          $f = $this->getFilters($attr);
2270          return '<?php echo '.sprintf($f,'$_ctx->comments->getAuthorURL()').'; ?>';
2271     }
2272
2273     /*dtd
2274     <!ELEMENT tpl:CommentContent - O --  Comment content -->
2275     <!ATTLIST tpl:CommentContent
2276     absolute_urls  (0|1)     #IMPLIED  -- convert URLS to absolute urls
2277     >
2278     */
2279     public function CommentContent($attr)
2280     {
2281          $urls = '0';
2282          if (!empty($attr['absolute_urls'])) {
2283               $urls = '1';
2284          }
2285
2286          $f = $this->getFilters($attr);
2287          return '<?php echo '.sprintf($f,'$_ctx->comments->getContent('.$urls.')').'; ?>';
2288     }
2289
2290     /*dtd
2291     <!ELEMENT tpl:CommentDate - O -- Comment date -->
2292     <!ATTLIST tpl:CommentDate
2293     format    CDATA     #IMPLIED  -- date format (encoded in dc:str by default if iso8601 or rfc822 not specified)
2294     iso8601   CDATA     #IMPLIED  -- if set, tells that date format is ISO 8601
2295     rfc822    CDATA     #IMPLIED  -- if set, tells that date format is RFC 822
2296     upddt     CDATA     #IMPLIED  -- if set, uses the comment update time
2297     >
2298     */
2299     public function CommentDate($attr)
2300     {
2301          $format = '';
2302          if (!empty($attr['format'])) {
2303               $format = addslashes($attr['format']);
2304          }
2305
2306          $iso8601 = !empty($attr['iso8601']);
2307          $rfc822 = !empty($attr['rfc822']);
2308          $type = (!empty($attr['upddt']) ? 'upddt' : '');
2309
2310          $f = $this->getFilters($attr);
2311
2312          if ($rfc822) {
2313               return '<?php echo '.sprintf($f,"\$_ctx->comments->getRFC822Date('".$type."')").'; ?>';
2314          } elseif ($iso8601) {
2315               return '<?php echo '.sprintf($f,"\$_ctx->comments->getISO8601Date('".$type."')").'; ?>';
2316          } else {
2317               return '<?php echo '.sprintf($f,"\$_ctx->comments->getDate('".$format."','".$type."')").'; ?>';
2318          }
2319     }
2320
2321     /*dtd
2322     <!ELEMENT tpl:CommentTime - O -- Comment date -->
2323     <!ATTLIST tpl:CommentTime
2324     format    CDATA     #IMPLIED  -- time format
2325     upddt     CDATA     #IMPLIED  -- if set, uses the comment update time
2326     >
2327     */
2328     public function CommentTime($attr)
2329     {
2330          $format = '';
2331          if (!empty($attr['format'])) {
2332               $format = addslashes($attr['format']);
2333          }
2334          $type = (!empty($attr['upddt']) ? 'upddt' : '');
2335
2336          $f = $this->getFilters($attr);
2337          return '<?php echo '.sprintf($f,"\$_ctx->comments->getTime('".$format."','".$type."')").'; ?>';
2338     }
2339
2340     /*dtd
2341     <!ELEMENT tpl:CommentEmail - O -- Comment author email -->
2342     <!ATTLIST tpl:CommentEmail
2343     spam_protected (0|1)     #IMPLIED  -- protect email from spam (default: 1)
2344     >
2345     */
2346     public function CommentEmail($attr)
2347     {
2348          $p = 'true';
2349          if (isset($attr['spam_protected']) && !$attr['spam_protected']) {
2350               $p = 'false';
2351          }
2352
2353          $f = $this->getFilters($attr);
2354          return '<?php echo '.sprintf($f,"\$_ctx->comments->getEmail(".$p.")").'; ?>';
2355     }
2356
2357     /*dtd
2358     <!ELEMENT tpl:CommentEntryTitle - O -- Title of the comment entry -->
2359     */
2360     public function CommentEntryTitle($attr)
2361     {
2362          $f = $this->getFilters($attr);
2363          return '<?php echo '.sprintf($f,'$_ctx->comments->post_title').'; ?>';
2364     }
2365
2366     /*dtd
2367     <!ELEMENT tpl:CommentFeedID - O -- Comment feed ID -->
2368     */
2369     public function CommentFeedID($attr)
2370     {
2371          $f = $this->getFilters($attr);
2372          return '<?php echo '.sprintf($f,'$_ctx->comments->getFeedID()').'; ?>';
2373     }
2374
2375     /*dtd
2376     <!ELEMENT tpl:CommentID - O -- Comment ID -->
2377     */
2378     public function CommentID($attr)
2379     {
2380          return '<?php echo $_ctx->comments->comment_id; ?>';
2381     }
2382
2383     /*dtd
2384     <!ELEMENT tpl:CommentIf - - -- test container for comments -->
2385     <!ATTLIST tpl:CommentIf
2386     is_ping   (0|1)     #IMPLIED  -- test if comment is a trackback (value : 1) or not (value : 0)
2387     >
2388     */
2389     public function CommentIf($attr,$content)
2390     {
2391          $if = array();
2392          $is_ping = null;
2393
2394          if (isset($attr['is_ping'])) {
2395               $sign = (boolean) $attr['is_ping'] ? '' : '!';
2396               $if[] = $sign.'$_ctx->comments->comment_trackback';
2397          }
2398
2399          $this->core->callBehavior('tplIfConditions','CommentIf',$attr,$content,$if);
2400
2401          if (count($if) != 0) {
2402               return '<?php if('.implode(' && ', (array) $if).') : ?>'.$content.'<?php endif; ?>';
2403          } else {
2404               return $content;
2405          }
2406     }
2407
2408     /*dtd
2409     <!ELEMENT tpl:CommentIfFirst - O -- displays value if comment is the first one -->
2410     <!ATTLIST tpl:CommentIfFirst
2411     return    CDATA     #IMPLIED  -- value to display in case of success (default: first)
2412     >
2413     */
2414     public function CommentIfFirst($attr)
2415     {
2416          $ret = isset($attr['return']) ? $attr['return'] : 'first';
2417          $ret = html::escapeHTML($ret);
2418
2419          return
2420          '<?php if ($_ctx->comments->index() == 0) { '.
2421          "echo '".addslashes($ret)."'; } ?>";
2422     }
2423
2424     /*dtd
2425     <!ELEMENT tpl:CommentIfMe - O -- displays value if comment is the from the entry author -->
2426     <!ATTLIST tpl:CommentIfMe
2427     return    CDATA     #IMPLIED  -- value to display in case of success (default: me)
2428     >
2429     */
2430     public function CommentIfMe($attr)
2431     {
2432          $ret = isset($attr['return']) ? $attr['return'] : 'me';
2433          $ret = html::escapeHTML($ret);
2434
2435          return
2436          '<?php if ($_ctx->comments->isMe()) { '.
2437          "echo '".addslashes($ret)."'; } ?>";
2438     }
2439
2440     /*dtd
2441     <!ELEMENT tpl:CommentIfOdd - O -- displays value if comment is  at an odd position -->
2442     <!ATTLIST tpl:CommentIfOdd
2443     return    CDATA     #IMPLIED  -- value to display in case of success (default: odd)
2444     >
2445     */
2446     public function CommentIfOdd($attr)
2447     {
2448          $ret = isset($attr['return']) ? $attr['return'] : 'odd';
2449          $ret = html::escapeHTML($ret);
2450
2451          return
2452          '<?php if (($_ctx->comments->index()+1)%2) { '.
2453          "echo '".addslashes($ret)."'; } ?>";
2454     }
2455
2456     /*dtd
2457     <!ELEMENT tpl:CommentIP - O -- Comment author IP -->
2458     */
2459     public function CommentIP($attr)
2460     {
2461          return '<?php echo $_ctx->comments->comment_ip; ?>';
2462     }
2463
2464     /*dtd
2465     <!ELEMENT tpl:CommentOrderNumber - O -- Comment order in page -->
2466     */
2467     public function CommentOrderNumber($attr)
2468     {
2469          return '<?php echo $_ctx->comments->index()+1; ?>';
2470     }
2471
2472     /*dtd
2473     <!ELEMENT tpl:CommentsFooter - - -- Last comments result container -->
2474     */
2475     public function CommentsFooter($attr,$content)
2476     {
2477          return
2478          "<?php if (\$_ctx->comments->isEnd()) : ?>".
2479          $content.
2480          "<?php endif; ?>";
2481     }
2482
2483     /*dtd
2484     <!ELEMENT tpl:CommentsHeader - - -- First comments result container -->
2485     */
2486     public function CommentsHeader($attr,$content)
2487     {
2488          return
2489          "<?php if (\$_ctx->comments->isStart()) : ?>".
2490          $content.
2491          "<?php endif; ?>";
2492     }
2493
2494     /*dtd
2495     <!ELEMENT tpl:CommentPostURL - O -- Comment Entry URL -->
2496     */
2497     public function CommentPostURL($attr)
2498     {
2499          $f = $this->getFilters($attr);
2500          return '<?php echo '.sprintf($f,'$_ctx->comments->getPostURL()').'; ?>';
2501     }
2502
2503     /*dtd
2504     <!ELEMENT tpl:IfCommentAuthorEmail - - -- Container displayed if comment author email is set -->
2505     */
2506     public function IfCommentAuthorEmail($attr,$content)
2507     {
2508          return
2509          "<?php if (\$_ctx->comments->comment_email) : ?>".
2510          $content.
2511          "<?php endif; ?>";
2512     }
2513
2514     /*dtd
2515     <!ELEMENT tpl:CommentHelp - 0 -- Comment syntax mini help -->
2516     */
2517     public function CommentHelp($attr,$content)
2518     {
2519          return
2520          "<?php if (\$core->blog->settings->system->wiki_comments) {\n".
2521          "  echo __('Comments can be formatted using a simple wiki syntax.');\n".
2522          "} else {\n".
2523          "  echo __('HTML code is displayed as text and web addresses are automatically converted.');\n".
2524          "} ?>";
2525     }
2526
2527     /* Comment preview -------------------------------- */
2528     /*dtd
2529     <!ELEMENT tpl:IfCommentPreviewOptional - - -- Container displayed if comment preview is optional or currently previewed -->
2530     */
2531     public function IfCommentPreviewOptional($attr,$content)
2532     {
2533          return
2534          '<?php if ($core->blog->settings->system->comment_preview_optional || ($_ctx->comment_preview !== null && $_ctx->comment_preview["preview"])) : ?>'.
2535          $content.
2536          '<?php endif; ?>';
2537     }
2538
2539     /*dtd
2540     <!ELEMENT tpl:IfCommentPreview - - -- Container displayed if comment is being previewed -->
2541     */
2542     public function IfCommentPreview($attr,$content)
2543     {
2544          return
2545          '<?php if ($_ctx->comment_preview !== null && $_ctx->comment_preview["preview"]) : ?>'.
2546          $content.
2547          '<?php endif; ?>';
2548     }
2549
2550     /*dtd
2551     <!ELEMENT tpl:CommentPreviewName - O -- Author name for the previewed comment -->
2552     */
2553     public function CommentPreviewName($attr)
2554     {
2555          $f = $this->getFilters($attr);
2556          return '<?php echo '.sprintf($f,'$_ctx->comment_preview["name"]').'; ?>';
2557     }
2558
2559     /*dtd
2560     <!ELEMENT tpl:CommentPreviewEmail - O -- Author email for the previewed comment -->
2561     */
2562     public function CommentPreviewEmail($attr)
2563     {
2564          $f = $this->getFilters($attr);
2565          return '<?php echo '.sprintf($f,'$_ctx->comment_preview["mail"]').'; ?>';
2566     }
2567
2568     /*dtd
2569     <!ELEMENT tpl:CommentPreviewSite - O -- Author site for the previewed comment -->
2570     */
2571     public function CommentPreviewSite($attr)
2572     {
2573          $f = $this->getFilters($attr);
2574          return '<?php echo '.sprintf($f,'$_ctx->comment_preview["site"]').'; ?>';
2575     }
2576
2577     /*dtd
2578     <!ELEMENT tpl:CommentPreviewContent - O -- Content of the previewed comment -->
2579     <!ATTLIST tpl:CommentPreviewContent
2580     raw  (0|1)     #IMPLIED  -- display comment in raw content
2581     >
2582     */
2583     public function CommentPreviewContent($attr)
2584     {
2585          $f = $this->getFilters($attr);
2586
2587          if (!empty($attr['raw'])) {
2588               $co = '$_ctx->comment_preview["rawcontent"]';
2589          } else {
2590               $co = '$_ctx->comment_preview["content"]';
2591          }
2592
2593          return '<?php echo '.sprintf($f,$co).'; ?>';
2594     }
2595
2596     /*dtd
2597     <!ELEMENT tpl:CommentPreviewCheckRemember - O -- checkbox attribute for "remember me" (same value as before preview) -->
2598     */
2599     public function CommentPreviewCheckRemember($attr)
2600     {
2601          return
2602          "<?php if (\$_ctx->comment_preview['remember']) { echo ' checked=\"checked\"'; } ?>";
2603     }
2604
2605     /* Trackbacks ------------------------------------- */
2606     /*dtd
2607     <!ELEMENT tpl:PingBlogName - O -- Trackback blog name -->
2608     */
2609     public function PingBlogName($attr)
2610     {
2611          $f = $this->getFilters($attr);
2612          return '<?php echo '.sprintf($f,'$_ctx->pings->comment_author').'; ?>';
2613     }
2614
2615     /*dtd
2616     <!ELEMENT tpl:PingContent - O -- Trackback content -->
2617     */
2618     public function PingContent($attr)
2619     {
2620          $f = $this->getFilters($attr);
2621          return '<?php echo '.sprintf($f,'$_ctx->pings->getTrackbackContent()').'; ?>';
2622     }
2623
2624     /*dtd
2625     <!ELEMENT tpl:PingDate - O -- Trackback date -->
2626     <!ATTLIST tpl:PingDate
2627     format    CDATA     #IMPLIED  -- date format (encoded in dc:str by default if iso8601 or rfc822 not specified)
2628     iso8601   CDATA     #IMPLIED  -- if set, tells that date format is ISO 8601
2629     rfc822    CDATA     #IMPLIED  -- if set, tells that date format is RFC 822
2630     upddt     CDATA     #IMPLIED  -- if set, uses the comment update time
2631     >
2632     */
2633     public function PingDate($attr,$type='')
2634     {
2635          $format = '';
2636          if (!empty($attr['format'])) {
2637               $format = addslashes($attr['format']);
2638          }
2639
2640          $iso8601 = !empty($attr['iso8601']);
2641          $rfc822 = !empty($attr['rfc822']);
2642          $type = (!empty($attr['upddt']) ? 'upddt' : '');
2643
2644          $f = $this->getFilters($attr);
2645
2646          if ($rfc822) {
2647               return '<?php echo '.sprintf($f,"\$_ctx->pings->getRFC822Date('".$type."')").'; ?>';
2648          } elseif ($iso8601) {
2649               return '<?php echo '.sprintf($f,"\$_ctx->pings->getISO8601Date('".$type."')").'; ?>';
2650          } else {
2651               return '<?php echo '.sprintf($f,"\$_ctx->pings->getDate('".$format."','".$type."')").'; ?>';
2652          }
2653     }
2654
2655     /*dtd
2656     <!ELEMENT tpl:PingTime - O -- Trackback date -->
2657     <!ATTLIST tpl:PingTime
2658     format    CDATA     #IMPLIED  -- time format
2659     upddt     CDATA     #IMPLIED  -- if set, uses the comment update time
2660     >
2661     */
2662     public function PingTime($attr)
2663     {
2664          $format = '';
2665          if (!empty($attr['format'])) {
2666               $format = addslashes($attr['format']);
2667          }
2668          $type = (!empty($attr['upddt']) ? 'upddt' : '');
2669
2670          $f = $this->getFilters($attr);
2671          return '<?php echo '.sprintf($f,"\$_ctx->pings->getTime('".$format."','".$type."')").'; ?>';
2672     }
2673
2674     /*dtd
2675     <!ELEMENT tpl:PingEntryTitle - O -- Trackback entry title -->
2676     */
2677     public function PingEntryTitle($attr)
2678     {
2679          $f = $this->getFilters($attr);
2680          return '<?php echo '.sprintf($f,'$_ctx->pings->post_title').'; ?>';
2681     }
2682
2683     /*dtd
2684     <!ELEMENT tpl:PingFeedID - O -- Trackback feed ID -->
2685     */
2686     public function PingFeedID($attr)
2687     {
2688          $f = $this->getFilters($attr);
2689          return '<?php echo '.sprintf($f,'$_ctx->pings->getFeedID()').'; ?>';
2690     }
2691
2692     /*dtd
2693     <!ELEMENT tpl:PingID - O -- Trackback ID -->
2694     */
2695     public function PingID($attr)
2696     {
2697          return '<?php echo $_ctx->pings->comment_id; ?>';
2698     }
2699
2700     /*dtd
2701     <!ELEMENT tpl:PingIfFirst - O -- displays value if trackback is the first one -->
2702     <!ATTLIST tpl:PingIfFirst
2703     return    CDATA     #IMPLIED  -- value to display in case of success (default: first)
2704     >
2705     */
2706     public function PingIfFirst($attr)
2707     {
2708          $ret = isset($attr['return']) ? $attr['return'] : 'first';
2709          $ret = html::escapeHTML($ret);
2710
2711          return
2712          '<?php if ($_ctx->pings->index() == 0) { '.
2713          "echo '".addslashes($ret)."'; } ?>";
2714     }
2715
2716     /*dtd
2717     <!ELEMENT tpl:PingIfOdd - O -- displays value if trackback is  at an odd position -->
2718     <!ATTLIST tpl:PingIfOdd
2719     return    CDATA     #IMPLIED  -- value to display in case of success (default: odd)
2720     >
2721     */
2722     public function PingIfOdd($attr)
2723     {
2724          $ret = isset($attr['return']) ? $attr['return'] : 'odd';
2725          $ret = html::escapeHTML($ret);
2726
2727          return
2728          '<?php if (($_ctx->pings->index()+1)%2) { '.
2729          "echo '".addslashes($ret)."'; } ?>";
2730     }
2731
2732     /*dtd
2733     <!ELEMENT tpl:PingIP - O -- Trackback author IP -->
2734     */
2735     public function PingIP($attr)
2736     {
2737          return '<?php echo $_ctx->pings->comment_ip; ?>';
2738     }
2739
2740     /*dtd
2741     <!ELEMENT tpl:PingNoFollow - O -- displays 'rel="nofollow"' if set in blog -->
2742     */
2743     public function PingNoFollow($attr)
2744     {
2745          return
2746          '<?php if($core->blog->settings->system->comments_nofollow) { '.
2747          'echo \' rel="nofollow"\';'.
2748          '} ?>';
2749     }
2750
2751     /*dtd
2752     <!ELEMENT tpl:PingOrderNumber - O -- Trackback order in page -->
2753     */
2754     public function PingOrderNumber($attr)
2755     {
2756          return '<?php echo $_ctx->pings->index()+1; ?>';
2757     }
2758
2759     /*dtd
2760     <!ELEMENT tpl:PingPostURL - O -- Trackback Entry URL -->
2761     */
2762     public function PingPostURL($attr)
2763     {
2764          $f = $this->getFilters($attr);
2765          return '<?php echo '.sprintf($f,'$_ctx->pings->getPostURL()').'; ?>';
2766     }
2767
2768     /*dtd
2769     <!ELEMENT tpl:Pings - - -- Trackbacks container -->
2770     <!ATTLIST tpl:Pings
2771     with_pings     (0|1)     #IMPLIED  -- include trackbacks in request
2772     lastn     CDATA          #IMPLIED  -- restrict the number of entries
2773     no_context (1|0)         #IMPLIED  -- Override context information
2774     order     (desc|asc)     #IMPLIED  -- result ordering (default: asc)
2775     >
2776     */
2777     public function Pings($attr,$content)
2778     {
2779          $p =
2780          "if (\$_ctx->posts !== null) { ".
2781               "\$params['post_id'] = \$_ctx->posts->post_id; ".
2782               "\$core->blog->withoutPassword(false);\n".
2783          "}\n";
2784
2785          $p .= "\$params['comment_trackback'] = true;\n";
2786
2787          $lastn = 0;
2788          if (isset($attr['lastn'])) {
2789               $lastn = abs((integer) $attr['lastn'])+0;
2790          }
2791
2792          if ($lastn > 0) {
2793               $p .= "\$params['limit'] = ".$lastn.";\n";
2794          } else {
2795               $p .= "if (\$_ctx->nb_comment_per_page !== null) { \$params['limit'] = \$_ctx->nb_comment_per_page; }\n";
2796          }
2797
2798          if (empty($attr['no_context']))
2799          {
2800               $p .=
2801               'if ($_ctx->exists("categories")) { '.
2802                    "\$params['cat_id'] = \$_ctx->categories->cat_id; ".
2803               "}\n";
2804
2805               $p .=
2806               'if ($_ctx->exists("langs")) { '.
2807                    "\$params['sql'] = \"AND P.post_lang = '\".\$core->blog->con->escape(\$_ctx->langs->post_lang).\"' \"; ".
2808               "}\n";
2809          }
2810
2811          $order = 'asc';
2812          if (isset($attr['order']) && preg_match('/^(desc|asc)$/i',$attr['order'])) {
2813               $order = $attr['order'];
2814          }
2815
2816          $p .= "\$params['order'] = 'comment_dt ".$order."';\n";
2817
2818          if (isset($attr['no_content']) && $attr['no_content']) {
2819               $p .= "\$params['no_content'] = true;\n";
2820          }
2821
2822          $res = "<?php\n";
2823          $res .= $p;
2824          $res .= $this->core->callBehavior("templatePrepareParams",
2825               array("tag" => "Pings","method" => "blog::getComments"),
2826               $attr,$content);
2827          $res .= '$_ctx->pings = $core->blog->getComments($params); unset($params);'."\n";
2828          $res .= "if (\$_ctx->posts !== null) { \$core->blog->withoutPassword(true);}\n";
2829          $res .= "?>\n";
2830
2831          $res .=
2832          '<?php while ($_ctx->pings->fetch()) : ?>'.$content.'<?php endwhile; $_ctx->pings = null; ?>';
2833
2834          return $res;
2835     }
2836
2837     /*dtd
2838     <!ELEMENT tpl:PingsFooter - - -- Last trackbacks result container -->
2839     */
2840     public function PingsFooter($attr,$content)
2841     {
2842          return
2843          "<?php if (\$_ctx->pings->isEnd()) : ?>".
2844          $content.
2845          "<?php endif; ?>";
2846     }
2847
2848     /*dtd
2849     <!ELEMENT tpl:PingsHeader - - -- First trackbacks result container -->
2850     */
2851     public function PingsHeader($attr,$content)
2852     {
2853          return
2854          "<?php if (\$_ctx->pings->isStart()) : ?>".
2855          $content.
2856          "<?php endif; ?>";
2857     }
2858
2859     /*dtd
2860     <!ELEMENT tpl:PingTitle - O -- Trackback title -->
2861     */
2862     public function PingTitle($attr)
2863     {
2864          $f = $this->getFilters($attr);
2865          return '<?php echo '.sprintf($f,'$_ctx->pings->getTrackbackTitle()').'; ?>';
2866     }
2867
2868     /*dtd
2869     <!ELEMENT tpl:PingAuthorURL - O -- Trackback author URL -->
2870     */
2871     public function PingAuthorURL($attr)
2872     {
2873          $f = $this->getFilters($attr);
2874          return '<?php echo '.sprintf($f,'$_ctx->pings->getAuthorURL()').'; ?>';
2875     }
2876
2877     # System
2878     /*dtd
2879     <!ELEMENT tpl:SysBehavior - O -- Call a given behavior -->
2880     <!ATTLIST tpl:SysBehavior
2881     behavior  CDATA     #IMPLIED  -- behavior to call
2882     >
2883     */
2884     public function SysBehavior($attr,$raw)
2885     {
2886          if (!isset($attr['behavior'])) {
2887               return;
2888          }
2889
2890          $b = addslashes($attr['behavior']);
2891          return
2892          '<?php if ($core->hasBehavior(\''.$b.'\')) { '.
2893               '$core->callBehavior(\''.$b.'\',$core,$_ctx);'.
2894          '} ?>';
2895     }
2896
2897     /*dtd
2898     <!ELEMENT tpl:SysIf - - -- System settings tester container -->
2899     <!ATTLIST tpl:SysIf
2900     categories          (0|1)     #IMPLIED  -- test if categories are set in current context (value : 1) or not (value : 0)
2901     posts               (0|1)     #IMPLIED  -- test if posts are set in current context (value : 1) or not (value : 0)
2902     blog_lang           CDATA     #IMPLIED  -- tests if blog language is the one given in parameter
2903     current_tpl         CDATA     #IMPLIED  -- tests if current template is the one given in paramater
2904     current_mode        CDATA     #IMPLIED  -- tests if current URL mode is the one given in parameter
2905     has_tpl             CDATA     #IMPLIED  -- tests if a named template exists
2906     has_tag             CDATA     #IMPLIED  -- tests if a named template block or value exists
2907     blog_id             CDATA     #IMPLIED  -- tests if current blog ID is the one given in parameter
2908     comments_active     (0|1)     #IMPLIED  -- test if comments are enabled blog-wide
2909     pings_active        (0|1)     #IMPLIED  -- test if trackbacks are enabled blog-wide
2910     wiki_comments       (0|1)     #IMPLIED  -- test if wiki syntax is enabled for comments
2911     operator            (and|or)  #IMPLIED  -- combination of conditions, if more than 1 specifiec (default: and)
2912     >
2913     */
2914     public function SysIf($attr,$content)
2915     {
2916          $if = new ArrayObject();
2917          $is_ping = null;
2918
2919          $operator = isset($attr['operator']) ? $this->getOperator($attr['operator']) : '&&';
2920
2921          if (isset($attr['categories'])) {
2922               $sign = (boolean) $attr['categories'] ? '!' : '=';
2923               $if[] = '$_ctx->categories '.$sign.'== null';
2924          }
2925
2926          if (isset($attr['posts'])) {
2927               $sign = (boolean) $attr['posts'] ? '!' : '=';
2928               $if[] = '$_ctx->posts '.$sign.'== null';
2929          }
2930
2931          if (isset($attr['blog_lang'])) {
2932               $sign = (boolean) $attr['blog_lang'] ? '!' : '=';
2933               $if[] = "\$core->blog->settings->system->lang ".$sign."= '".addslashes($attr['blog_lang'])."'";
2934          }
2935
2936          if (isset($attr['current_tpl'])) {
2937               $sign = '=';
2938               if (substr($attr['current_tpl'],0,1) == '!') {
2939                    $sign = '!';
2940                    $attr['current_tpl'] = substr($attr['current_tpl'],1);
2941               }
2942               $if[] = "\$_ctx->current_tpl ".$sign."= '".addslashes($attr['current_tpl'])."'";
2943          }
2944
2945          if (isset($attr['current_mode'])) {
2946               $sign = '=';
2947               if (substr($attr['current_mode'],0,1) == '!') {
2948                    $sign = '!';
2949                    $attr['current_mode'] = substr($attr['current_mode'],1);
2950               }
2951               $if[] = "\$core->url->type ".$sign."= '".addslashes($attr['current_mode'])."'";
2952          }
2953
2954          if (isset($attr['has_tpl'])) {
2955               $sign = '';
2956               if (substr($attr['has_tpl'],0,1) == '!') {
2957                    $sign = '!';
2958                    $attr['has_tpl'] = substr($attr['has_tpl'],1);
2959               }
2960               $if[] = $sign."\$core->tpl->getFilePath('".addslashes($attr['has_tpl'])."') !== false";
2961          }
2962
2963          if (isset($attr['has_tag'])) {
2964               $sign = 'true';
2965               if (substr($attr['has_tag'],0,1) == '!') {
2966                    $sign = 'false';
2967                    $attr['has_tag'] = substr($attr['has_tag'],1);
2968               }
2969               $if[] =  "\$core->tpl->tagExists('".addslashes($attr['has_tag'])."') === ".$sign;
2970          }
2971
2972          if (isset($attr['blog_id'])) {
2973               $sign = '';
2974               if (substr($attr['blog_id'],0,1) == '!') {
2975                    $sign = '!';
2976                    $attr['blog_id'] = substr($attr['blog_id'],1);
2977               }
2978               $if[] = $sign."(\$core->blog->id == '".addslashes($attr['blog_id'])."')";
2979          }
2980
2981          if (isset($attr['comments_active'])) {
2982               $sign = (boolean) $attr['comments_active'] ? '' : '!';
2983               $if[] = $sign.'$core->blog->settings->system->allow_comments';
2984          }
2985
2986          if (isset($attr['pings_active'])) {
2987               $sign = (boolean) $attr['pings_active'] ? '' : '!';
2988               $if[] = $sign.'$core->blog->settings->system->allow_trackbacks';
2989          }
2990
2991          if (isset($attr['wiki_comments'])) {
2992               $sign = (boolean) $attr['wiki_comments'] ? '' : '!';
2993               $if[] = $sign.'$core->blog->settings->system->wiki_comments';
2994          }
2995
2996          if (isset($attr['search_count']) &&
2997               preg_match('/^((=|!|&gt;|&lt;)=|(&gt;|&lt;))\s*[0-9]+$/',trim($attr['search_count']))) {
2998               $if[] = '(isset($_search_count) && $_search_count '.html::decodeEntities($attr['search_count']).')';
2999          }
3000
3001          $this->core->callBehavior('tplIfConditions','SysIf',$attr,$content,$if);
3002
3003          if (count($if) != 0) {
3004               return '<?php if('.implode(' '.$operator.' ', (array) $if).') : ?>'.$content.'<?php endif; ?>';
3005          } else {
3006               return $content;
3007          }
3008     }
3009
3010     /*dtd
3011     <!ELEMENT tpl:SysIfCommentPublished - - -- Container displayed if comment has been published -->
3012     */
3013     public function SysIfCommentPublished($attr,$content)
3014     {
3015          return
3016          '<?php if (!empty($_GET[\'pub\'])) : ?>'.
3017          $content.
3018          '<?php endif; ?>';
3019     }
3020
3021     /*dtd
3022     <!ELEMENT tpl:SysIfCommentPending - - -- Container displayed if comment is pending after submission -->
3023     */
3024     public function SysIfCommentPending($attr,$content)
3025     {
3026          return
3027          '<?php if (isset($_GET[\'pub\']) && $_GET[\'pub\'] == 0) : ?>'.
3028          $content.
3029          '<?php endif; ?>';
3030     }
3031
3032     /*dtd
3033     <!ELEMENT tpl:SysFeedSubtitle - O -- Feed subtitle -->
3034     */
3035     public function SysFeedSubtitle($attr)
3036     {
3037          $f = $this->getFilters($attr);
3038          return '<?php if ($_ctx->feed_subtitle !== null) { echo '.sprintf($f,'$_ctx->feed_subtitle').';} ?>';
3039     }
3040
3041     /*dtd
3042     <!ELEMENT tpl:SysIfFormError - O -- Container displayed if an error has been detected after form submission -->
3043     */
3044     public function SysIfFormError($attr,$content)
3045     {
3046          return
3047          '<?php if ($_ctx->form_error !== null) : ?>'.
3048          $content.
3049          '<?php endif; ?>';
3050     }
3051
3052     /*dtd
3053     <!ELEMENT tpl:SysFormError - O -- Form error -->
3054     */
3055     public function SysFormError($attr)
3056     {
3057          return
3058          '<?php if ($_ctx->form_error !== null) { echo $_ctx->form_error; } ?>';
3059     }
3060
3061     public function SysPoweredBy($attr)
3062     {
3063          return
3064          '<?php printf(__("Powered by %s"),"<a href=\"http://dotclear.org/\">Dotclear</a>"); ?>';
3065     }
3066
3067     public function SysSearchString($attr)
3068     {
3069          $s = isset($attr['string']) ? $attr['string'] : '%1$s';
3070
3071          $f = $this->getFilters($attr);
3072          return '<?php if (isset($_search)) { echo sprintf(__(\''.$s.'\'),'.sprintf($f,'$_search').',$_search_count);} ?>';
3073     }
3074
3075     public function SysSelfURI($attr)
3076     {
3077          $f = $this->getFilters($attr);
3078          return '<?php echo '.sprintf($f,'http::getSelfURI()').'; ?>';
3079     }
3080
3081     /*dtd
3082     <!ELEMENT tpl:else - O -- else: statement -->
3083     */
3084     public function GenericElse($attr)
3085     {
3086          return '<?php else: ?>';
3087     }
3088}
Note: See TracBrowser for help on using the repository browser.

Sites map