PageRenderTime 50ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/theme.class.php

http://litepublisher.googlecode.com/
PHP | 639 lines | 534 code | 95 blank | 10 comment | 119 complexity | bfd0205cd270dfb05d05ee48cefef70f MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0
  1. <?php
  2. /**
  3. * Lite Publisher
  4. * Copyright (C) 2010 - 2013 Vladimir Yushko http://litepublisher.ru/ http://litepublisher.com/
  5. * Dual licensed under the MIT (mit.txt)
  6. * and GPL (gpl.txt) licenses.
  7. **/
  8. class ttheme extends tevents {
  9. public static $instances = array();
  10. public static $vars = array();
  11. public static $defaultargs;
  12. public static $inifiles;
  13. public $name;
  14. public $parsing;
  15. public $templates;
  16. public $extratml;
  17. private $themeprops;
  18. public static function exists($name) {
  19. return file_exists(litepublisher::$paths->data . 'themes'. DIRECTORY_SEPARATOR . $name . '.php') ||
  20. file_exists(litepublisher::$paths->themes . $name . DIRECTORY_SEPARATOR . 'about.ini');
  21. }
  22. public static function i() {
  23. return getinstance(__class__);
  24. }
  25. public static function getinstance($name) {
  26. if (isset(self::$instances[$name])) return self::$instances[$name];
  27. $result = getinstance(__class__);
  28. if ($result->name != '') $result = litepublisher::$classes->newinstance(__class__);
  29. $result->name = $name;
  30. $result->load();
  31. return $result;
  32. }
  33. public static function getwidgetnames() {
  34. return array('submenu', 'categories', 'tags', 'archives', 'links', 'posts', 'comments', 'friends', 'meta') ;
  35. }
  36. protected function create() {
  37. parent::create();
  38. $this->name = '';
  39. $this->parsing = array();
  40. $this->data['type'] = 'litepublisher';
  41. $this->data['parent'] = '';
  42. $this->addmap('templates', array());
  43. $this->templates = array(
  44. 'index' => '',
  45. 'title' => '',
  46. 'menu' => '',
  47. 'content' => '',
  48. 'sidebars' => array(),
  49. 'custom' => array(),
  50. 'customadmin' => array()
  51. );
  52. $this->themeprops = new tthemeprops($this);
  53. if (!isset(self::$defaultargs)) self::set_defaultargs();
  54. $this->extratml = '';
  55. }
  56. public static function set_defaultargs() {
  57. self::$defaultargs = array(
  58. '$site.url' => litepublisher::$site->url,
  59. '$site.files' => litepublisher::$site->files,
  60. '{$site.q}' => litepublisher::$site->q,
  61. '$site.q' => litepublisher::$site->q
  62. );
  63. }
  64. public function __destruct() {
  65. unset($this->themeprops, self::$instances[$this->name], $this->templates);
  66. parent::__destruct();
  67. }
  68. public function getbasename() {
  69. return 'themes' . DIRECTORY_SEPARATOR . $this->name;
  70. }
  71. public function load() {
  72. if ($this->name == '') return false;
  73. if (parent::load()) {
  74. self::$instances[$this->name] = $this;
  75. return true;
  76. }
  77. return $this->parsetheme();
  78. }
  79. public function parsetheme() {
  80. if (!file_exists(litepublisher::$paths->themes . $this->name . DIRECTORY_SEPARATOR . 'about.ini')) {
  81. $this->error(sprintf('The %s theme not exists', $this->name));
  82. }
  83. $parser = tthemeparser::i();
  84. if ($parser->parse($this)) {
  85. self::$instances[$this->name] = $this;
  86. $this->save();
  87. }else {
  88. $this->error(sprintf('Theme file %s not exists', $filename));
  89. }
  90. }
  91. public function __tostring() {
  92. return $this->templates['index'];
  93. }
  94. public function __get($name) {
  95. if (array_key_exists($name, $this->templates)) return $this->themeprops->setpath($name);
  96. if ($name == 'comment') return $this->themeprops->setpath('content.post.templatecomments.comments.comment');
  97. if ($name == 'sidebar') return $this->themeprops->setroot($this->templates['sidebars'][0]);
  98. if (preg_match('/^sidebar(\d)$/', $name, $m)) return $this->themeprops->setroot($this->templates['sidebars'][$m[1]]);
  99. return parent::__get($name);
  100. }
  101. public function __set($name, $value) {
  102. if (array_key_exists($name, $this->templates)) {
  103. $this->templates[$name] = $value;
  104. return;
  105. }
  106. return parent::__set($name, $value);
  107. }
  108. public function gettag($path) {
  109. if (!array_key_exists($path, $this->templates)) $this->error(sprintf('Path "%s" not found', $path));
  110. $this->themeprops->setpath($path);
  111. $this->themeprops->tostring = true;
  112. return $this->themeprops;
  113. }
  114. public function reg($exp) {
  115. if (!strpos($exp, '\.')) $exp = str_replace('.', '\.', $exp);
  116. $result = array();
  117. foreach ($this->templates as $name => $val) {
  118. if (preg_match($exp, $name)) $result[$name] = $val;
  119. }
  120. return $result;
  121. }
  122. public function getsidebarscount() {
  123. return count($this->templates['sidebars']);
  124. }
  125. private function get_author() {
  126. $context = isset(litepublisher::$urlmap->context) ? litepublisher::$urlmap->context : ttemplate::i()->context;
  127. if (!is_object($context)) {
  128. if (!isset(self::$vars['post'])) return new emptyclass();
  129. $context = self::$vars['post'];
  130. }
  131. if ($context instanceof tuserpages) return $context;
  132. $iduser = 0;
  133. foreach (array('author', 'idauthor', 'user', 'iduser') as $propname) {
  134. if (isset($context->$propname)) {
  135. $iduser = $context->$propname;
  136. break;
  137. }
  138. }
  139. if (!$iduser) return new emptyclass();
  140. $pages = tuserpages::i();
  141. if (!$pages->itemexists($iduser)) return new emptyclass();
  142. $pages->request($iduser);
  143. return $pages;
  144. }
  145. private function getvar($name) {
  146. switch ($name) {
  147. case 'site':
  148. return litepublisher::$site;
  149. case 'lang':
  150. return tlocal::i();
  151. case 'post':
  152. $context = isset(litepublisher::$urlmap->context) ? litepublisher::$urlmap->context : ttemplate::i()->context;
  153. if ($context instanceof tpost) return $context;
  154. break;
  155. case 'author':
  156. return self::get_author();
  157. case 'metapost':
  158. return isset(self::$vars['post']) ? self::$vars['post']->meta : new emptyclass();
  159. } //switch
  160. if (isset($GLOBALS[$name])) {
  161. $var = $GLOBALS[$name];
  162. } else {
  163. $classes = litepublisher::$classes;
  164. $var = $classes->gettemplatevar($name);
  165. if (!$var) {
  166. if (isset($classes->classes[$name])) {
  167. $var = $classes->getinstance($classes->classes[$name]);
  168. } elseif (isset($classes->items[$name])) {
  169. $var = $classes->getinstance($name);
  170. } else {
  171. $class = 't' . $name;
  172. if (isset($classes->items[$class])) $var = $classes->getinstance($class);
  173. }
  174. }
  175. }
  176. if (!is_object($var)) {
  177. litepublisher::$options->trace(sprintf('Object "%s" not found in %s', $name, $this->parsing[count($this->parsing) -1]));
  178. return false;
  179. }
  180. return $var;
  181. }
  182. public function parsecallback($names) {
  183. $name = $names[1];
  184. $prop = $names[2];
  185. if (isset(self::$vars[$name])) {
  186. $var = self::$vars[$name];
  187. } elseif ($name == 'custom') {
  188. return $this->parse($this->templates['custom'][$prop]);
  189. } elseif ($var = $this->getvar($name)) {
  190. self::$vars[$name] = $var;
  191. } elseif (($name == 'metapost') && isset(self::$vars['post'])) {
  192. $var = self::$vars['post']->meta;
  193. } else {
  194. return '';
  195. }
  196. try {
  197. return $var->{$prop};
  198. } catch (Exception $e) {
  199. litepublisher::$options->handexception($e);
  200. }
  201. return '';
  202. }
  203. public function parse($s) {
  204. if (!$s) return '';
  205. $s = strtr((string) $s, self::$defaultargs);
  206. if (isset($this->templates['content.admin.tableclass'])) $s = str_replace('$tableclass', $this->templates['content.admin.tableclass'], $s);
  207. array_push($this->parsing, $s);
  208. try {
  209. $s = preg_replace('/%%([a-zA-Z0-9]*+)_(\w\w*+)%%/', '\$$1.$2', $s);
  210. $result = preg_replace_callback('/\$([a-zA-Z]\w*+)\.(\w\w*+)/', array($this, 'parsecallback'), $s);
  211. } catch (Exception $e) {
  212. $result = '';
  213. litepublisher::$options->handexception($e);
  214. }
  215. array_pop($this->parsing);
  216. return $result;
  217. }
  218. public function parsearg($s, targs $args) {
  219. $s = $this->parse($s);
  220. return strtr ($s, $args->data);
  221. }
  222. public function replacelang($s, $lang) {
  223. $s = preg_replace('/%%([a-zA-Z0-9]*+)_(\w\w*+)%%/', '\$$1.$2', (string) $s);
  224. self::$vars['lang'] = isset($lang) ? $lang : tlocal::i('default');
  225. $s = strtr($s, self::$defaultargs);
  226. if (preg_match_all('/\$lang\.(\w\w*+)/', $s, $m, PREG_SET_ORDER)) {
  227. foreach ($m as $item) {
  228. $name = $item[1];
  229. if ($v = $lang->{$name}) {
  230. $s = str_replace($item[0], $v, $s);
  231. }
  232. }
  233. }
  234. return $s;
  235. }
  236. public static function parsevar($name, $var, $s) {
  237. self::$vars[$name] = $var;
  238. return self::i()->parse($s);
  239. }
  240. public function gethtml($context) {
  241. self::$vars['context'] = $context;
  242. if (isset($context->index_tml) && ($tml = $context->index_tml)) return $this->parse($tml);
  243. return $this->parse($this->templates['index']);
  244. }
  245. public function getnotfount() {
  246. return $this->parse($this->templates['content.notfound']);
  247. }
  248. public function getpages($url, $page, $count, $params = '') {
  249. if (!(($count > 1) && ($page >=1) && ($page <= $count))) return '';
  250. $args = new targs();
  251. $args->count = $count;
  252. $from = 1;
  253. $to = $count;
  254. $perpage = litepublisher::$options->perpage;
  255. $args->perpage = $perpage;
  256. $items = array();
  257. if ($count > $perpage * 2) {
  258. //$page is midle of the bar
  259. $from = (int) max(1, $page - ceil($perpage / 2));
  260. $to = (int) min($count, $from + $perpage);
  261. }
  262. if ($from == 1) {
  263. $items = range($from, $to);
  264. } else {
  265. $items[0] = 1;
  266. if ($from > $perpage) {
  267. if ($from - $perpage - 1 < $perpage) {
  268. $items[] = $perpage;
  269. } else {
  270. array_splice($items, count($items), 0, range($perpage, $from - 1, $perpage));
  271. }
  272. }
  273. array_splice($items, count($items), 0, range($from, $to));
  274. }
  275. if ($to < $count) {
  276. $from2 = (int) ($perpage * ceil(($to+1) / $perpage));
  277. if ($from2 + $perpage >= $count) {
  278. if ($from2 < $count) $items[] = $from2;
  279. } else {
  280. array_splice($items, count($items), 0, range($from2, $count, $perpage));
  281. }
  282. if ($items[count($items) -1] != $count) $items[] = $count;
  283. }
  284. $currenttml=$this->templates['content.navi.current'];
  285. $tml =$this->templates['content.navi.link'];
  286. if (!strbegin($url, 'http')) $url = litepublisher::$site->url . $url;
  287. $pageurl = rtrim($url, '/') . '/page/';
  288. if ($params) $params = litepublisher::$site->q . $params;
  289. $a = array();
  290. foreach ($items as $i) {
  291. $args->page = $i;
  292. $link = $i == 1 ? $url : $pageurl .$i . '/';
  293. if ($params) $link .= $params;
  294. $args->link = $link;
  295. $a[] = $this->parsearg(($i == $page ? $currenttml : $tml), $args);
  296. }
  297. $args->link =$url;
  298. $args->pageurl = $pageurl;
  299. $args->page = $page;
  300. $args->items = implode($this->templates['content.navi.divider'], $a);
  301. return $this->parsearg($this->templates['content.navi'], $args);
  302. }
  303. public function getposts(array $items, $lite) {
  304. if (count($items) == 0) return '';
  305. if (dbversion) tposts::i()->loaditems($items);
  306. $result = '';
  307. self::$vars['lang'] = tlocal::i('default');
  308. //$tml = $lite ? $this->templates['content.excerpts.lite.excerpt'] : $this->templates['content.excerpts.excerpt'];
  309. foreach($items as $id) {
  310. $post = tpost::i($id);
  311. $result .= $post->getcontexcerpt($lite);
  312. // has $author.* tags in tml
  313. if (isset(self::$vars['author'])) unset(self::$vars['author']);
  314. }
  315. $tml = $lite ? $this->templates['content.excerpts.lite'] : $this->templates['content.excerpts'];
  316. if ($tml != '') $result = str_replace('$excerpt', $result, $this->parse($tml));
  317. unset(self::$vars['post']);
  318. return $result;
  319. }
  320. public function getpostsnavi(array $items, $lite, $url, $count, $liteperpage = 1000) {
  321. $result = $this->getposts($items, $lite);
  322. $perpage = $lite ? $liteperpage : litepublisher::$options->perpage;
  323. $result .= $this->getpages($url, litepublisher::$urlmap->page, ceil($count / $perpage));
  324. return $result;
  325. }
  326. public function getpostswidgetcontent(array $items, $sidebar, $tml) {
  327. if (count($items) == 0) return '';
  328. $result = '';
  329. if ($tml == '') $tml = $this->getwidgetitem('posts', $sidebar);
  330. foreach ($items as $id) {
  331. self::$vars['post'] = tpost::i($id);
  332. $result .= $this->parse($tml);
  333. }
  334. unset(self::$vars['post']);
  335. return str_replace('$item', $result, $this->getwidgetitems('posts', $sidebar));
  336. }
  337. public function getwidgetcontent($items, $name, $sidebar) {
  338. return str_replace('$item', $items, $this->getwidgetitems($name, $sidebar));
  339. }
  340. public function getwidget($title, $content, $template, $sidebar) {
  341. $args = new targs();
  342. $args->title = $title;
  343. $args->items = $content;
  344. $args->sidebar = $sidebar;
  345. return $this->parsearg($this->getwidgettml($sidebar, $template, ''), $args);
  346. }
  347. public function getidwidget($id, $title, $content, $template, $sidebar) {
  348. $args = new targs();
  349. $args->id = $id;
  350. $args->title = $title;
  351. $args->items = $content;
  352. $args->sidebar = $sidebar;
  353. return $this->parsearg($this->getwidgettml($sidebar, $template, ''), $args);
  354. }
  355. public function getwidgetitem($name, $index) {
  356. return $this->getwidgettml($index, $name, 'item');
  357. }
  358. public function getwidgetitems($name, $index) {
  359. return $this->getwidgettml($index, $name, 'items');
  360. }
  361. public function getwidgettml($index, $name, $tml) {
  362. $count = count($this->templates['sidebars']);
  363. if ($index >= $count) $index = $count - 1;
  364. $widgets = &$this->templates['sidebars'][$index];
  365. if (($tml != '') && ($tml [0] != '.')) $tml = '.' . $tml;
  366. if (isset($widgets[$name . $tml])) return $widgets[$name . $tml];
  367. if (isset($widgets['widget' . $tml])) return $widgets['widget' . $tml];
  368. $this->error("Unknown widget '$name' and template '$tml' in $index sidebar");
  369. }
  370. public function getajaxtitle($id, $title, $sidebar, $tml) {
  371. $args = new targs();
  372. $args->title = $title;
  373. $args->id = $id;
  374. $args->sidebar = $sidebar;
  375. return $this->parsearg($this->templates[$tml], $args);
  376. }
  377. public function simple($content) {
  378. return str_replace('$content', $content, $this->templates['content.simple']);
  379. }
  380. public function getbutton($title) {
  381. return strtr($this->templates['content.admin.button'], array(
  382. '$lang.$name' => $title,
  383. 'name="$name"' => '',
  384. 'id="submitbutton-$name"' => ''
  385. ));
  386. }
  387. public function getsubmit($title) {
  388. return strtr($this->templates['content.admin.button'], array(
  389. '$lang.$name', '$title',
  390. 'name="$name"' => '',
  391. 'id="submitbutton-$name"' => ''
  392. ));
  393. }
  394. public static function clearcache() {
  395. tfiler::delete(litepublisher::$paths->data . 'themes', false, false);
  396. litepublisher::$urlmap->clearcache();
  397. }
  398. public static function cacheini($filename) {
  399. if (isset(self::$inifiles[$filename])) return self::$inifiles[$filename];
  400. $datafile = tlocal::getcachedir() . sprintf('cacheini.%s.php', md5($filename));
  401. if (!tfilestorage::loadvar($datafile, $ini) || !is_array($ini)) {
  402. if (file_exists($filename)) {
  403. $ini = parse_ini_file($filename, true);
  404. tfilestorage::savevar($datafile, $ini);
  405. } else {
  406. $ini = array();
  407. }
  408. }
  409. if (!isset(self::$inifiles)) self::$inifiles = array();
  410. self::$inifiles[$filename] = $ini;
  411. return $ini;
  412. }
  413. public static function inifile($class, $filename) {
  414. $dir = litepublisher::$classes->getresourcedir($class);
  415. return self::cacheini($dir . $filename);
  416. }
  417. public static function getwidgetpath($path) {
  418. if ($path === '') return '';
  419. switch ($path) {
  420. case '.items':
  421. return '.items';
  422. case '.items.item':
  423. case '.item':
  424. return '.item';
  425. case '.items.item.subcount':
  426. case '.item.subcount':
  427. case '.subcount':
  428. return '.subcount';
  429. case '.items.item.subitems':
  430. case '.item.subitems':
  431. case '.subitems':
  432. return '.subitems';
  433. case '.classes':
  434. case '.items.classes':
  435. return '.classes';
  436. }
  437. return false;
  438. }
  439. }//class
  440. class tthemeprops {
  441. public $path;
  442. public $tostring;
  443. private $root;
  444. private $theme;
  445. public function __construct(ttheme $theme) {
  446. $this->theme = $theme;
  447. $this->root = &$theme->templates;
  448. $this->path = '';
  449. $this->tostring = false;
  450. }
  451. public function __destruct() {
  452. unset($this->theme, $this->root);
  453. }
  454. public function error($path) {
  455. litepublisher::$options->trace(sprintf('Path "%s" not found', $path));
  456. litepublisher::$options->showerrors();
  457. }
  458. public function getpath($name) {
  459. return $this->path == '' ? $name : $this->path . '.' . $name;
  460. }
  461. public function setpath($path) {
  462. $this->root = &$this->theme->templates;
  463. $this->path = $path;
  464. $this->tostring = false;
  465. return $this;
  466. }
  467. public function setroot(array &$root) {
  468. $this->setpath('');
  469. $this->root = &$root;
  470. return $this;
  471. }
  472. public function __get($name) {
  473. //echo "$name get tml<br>";
  474. $path = $this->getpath($name);
  475. if (!array_key_exists($path, $this->root)) $this->error($path);
  476. if ($this->tostring) return $this->root[$path];
  477. $this->path = $path;
  478. return $this;
  479. }
  480. public function __set($name, $value) {
  481. $this->root[$this->getpath($name)] = $value;
  482. }
  483. public function __call($name, $params) {
  484. if (isset($params[0]) && is_object($params[0]) && ($params[0] instanceof targs)) {
  485. return $this->theme->parsearg( (string) $this->$name, $params[0]);
  486. } else {
  487. return $this->theme->parse((string) $this->$name);
  488. }
  489. }
  490. public function __tostring() {
  491. if (array_key_exists($this->path, $this->root)) {
  492. return $this->root[$this->path];
  493. } else {
  494. $this->error($this->path);
  495. }
  496. }
  497. public function __isset($name) {
  498. return array_key_exists($this->getpath($name), $this->root);
  499. }
  500. }//class
  501. class targs {
  502. public $data;
  503. public static function i() {
  504. return litepublisher::$classes->newinstance(__class__);
  505. }
  506. public function __construct($thisthis = null) {
  507. if (!isset(ttheme::$defaultargs)) ttheme::set_defaultargs();
  508. $this->data = ttheme::$defaultargs;
  509. if (isset($thisthis)) $this->data['$this'] = $thisthis;
  510. }
  511. public function __get($name) {
  512. if (($name == 'link') && !isset($this->data['$link']) && isset($this->data['$url'])) {
  513. return litepublisher::$site->url . $this->data['$url'];
  514. }
  515. return $this->data['$' . $name];
  516. }
  517. public function __set($name, $value) {
  518. if (!is_string($name)) return;
  519. if ($name == '') return;
  520. if (is_bool($value)) {
  521. $value = $value ? 'checked="checked"' : '';
  522. }
  523. $this->data['$'.$name] = $value;
  524. $this->data["%%$name%%"] = $value;
  525. if (($name == 'url') && !isset($this->data['$link'])) {
  526. $this->data['$link'] = litepublisher::$site->url . $value;
  527. $this->data['%%link%%'] = litepublisher::$site->url . $value;
  528. }
  529. }
  530. public function add(array $a) {
  531. foreach ($a as $key => $value) {
  532. $this->__set($key, $value);
  533. if ($key == 'url') {
  534. $this->data['$link'] = litepublisher::$site->url . $value;
  535. $this->data['%%link%%'] = litepublisher::$site->url . $value;
  536. }
  537. }
  538. if (isset($a['title']) && !isset($a['text'])) $this->__set('text', $a['title']);
  539. if (isset($a['text']) && !isset($a['title'])) $this->__set('title', $a['text']);
  540. }
  541. }//class
  542. class emptyclass{
  543. public function __get($name) { return ''; }
  544. }