PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/inc/public/class.dc.template.php

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