Dotclear

source: inc/public/class.dc.template.php @ 3064:a484a50c8c14

Revision 3064:a484a50c8c14, 89.6 KB checked in by Nicolas <nikrou77@…>, 10 years ago (diff)

dcTemplate::getSortByStr must allow new keys from foreign tables through templateCustomSortByAlias behavior.
Remove test for existing DC_RC_PATH constant.

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

Sites map