Dotclear

source: inc/public/class.dc.template.php @ 2574:b1eb712bc56f

Revision 2574:b1eb712bc56f, 88.5 KB checked in by Dsls, 12 years ago (diff)

Template engine backported to clearbricks, closes #1862

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

Sites map