Dotclear

source: inc/public/class.dc.template.php @ 2886:361a37518b41

Revision 2886:361a37518b41, 91.2 KB checked in by Dsls, 11 years ago (diff)

Removed $_ctx value stacking. Fixes #2035

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

Sites map