PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/Template.php

https://github.com/razorlegacy/pyrocms
PHP | 591 lines | 295 code | 94 blank | 202 comment | 40 complexity | 1d3edab75876036004c80da90b106b66 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 4.3.2 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author Rick Ellis
  9. * @copyright Copyright (c) 2006, EllisLab, Inc.
  10. * @license http://www.codeignitor.com/user_guide/license.html
  11. * @link http://www.codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * CodeIgniter Template Class
  18. *
  19. * Build your CodeIgniter pages much easier with partials, breadcrumbs, layouts and themes
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @category Libraries
  24. * @author Philip Sturgeon
  25. * @link
  26. */
  27. class Template
  28. {
  29. private $_module = '';
  30. private $_controller = '';
  31. private $_method = '';
  32. private $_theme = '';
  33. private $_layout = FALSE; // By default, dont wrap the view with anything
  34. private $_title = '';
  35. private $_metadata = array();
  36. private $_partials = array();
  37. private $_breadcrumbs = array();
  38. private $_title_separator = ' | ';
  39. private $_parser_enabled = TRUE;
  40. private $_parser_body_enabled = TRUE;
  41. private $_theme_locations = array();
  42. // Seconds that cache will be alive for
  43. private $cache_lifetime = 0;//7200;
  44. private $_ci;
  45. private $data = array();
  46. /**
  47. * Constructor - Sets Preferences
  48. *
  49. * The constructor can be passed an array of config values
  50. */
  51. function __construct($config = array())
  52. {
  53. $this->_ci =& get_instance();
  54. if (!empty($config))
  55. {
  56. $this->initialize($config);
  57. }
  58. log_message('debug', 'Template class Initialized');
  59. // Work out the controller and method
  60. if( method_exists( $this->_ci->router, 'fetch_module' ) )
  61. {
  62. $this->_module = $this->_ci->router->fetch_module();
  63. }
  64. $this->_controller = $this->_ci->router->fetch_class();
  65. $this->_method = $this->_ci->router->fetch_method();
  66. }
  67. // --------------------------------------------------------------------
  68. /**
  69. * Initialize preferences
  70. *
  71. * @access public
  72. * @param array
  73. * @return void
  74. */
  75. function initialize($config = array())
  76. {
  77. foreach ($config as $key => $val)
  78. {
  79. $this->{'_'.$key} = $val;
  80. }
  81. if(empty($this->_theme_locations))
  82. {
  83. $this->_theme_locations = array(APPPATH . 'themes/' => '../themes/');
  84. }
  85. if ($this->_parser_enabled === TRUE)
  86. {
  87. $this->_ci->load->library('parser');
  88. }
  89. }
  90. // --------------------------------------------------------------------
  91. /**
  92. * Set the mode of the creation
  93. *
  94. * @access public
  95. * @param string
  96. * @return void
  97. */
  98. public function build($view = '', $data = array(), $return = FALSE)
  99. {
  100. // Set whatever values are given. These will be available to all view files
  101. $this->data = is_object($data) ? (array) $data : $data;
  102. if(empty($this->_title))
  103. {
  104. $this->_title = $this->_guess_title();
  105. }
  106. // Output template variables to the template
  107. $template['title'] = $this->_title;
  108. $template['breadcrumbs'] = $this->_breadcrumbs;
  109. $template['metadata'] = implode("\n\t\t", $this->_metadata);
  110. $template['partials'] = array();
  111. // Assign by reference, as all loaded views will need access to partials
  112. $this->data['template'] =& $template;
  113. foreach( $this->_partials as $name => $partial )
  114. {
  115. // If its an array, use details to find it.
  116. if (isset($partial['view']))
  117. {
  118. $template['partials'][$name] = $this->_load_view($partial['view'], $partial['search']);
  119. }
  120. // Otherwise, jam that bloody string in!
  121. else
  122. {
  123. if($this->_parser_enabled === TRUE)
  124. {
  125. $partial['string'] = $this->_ci->parser->parse_string($partial['string'], $this->data + $partial['data'], TRUE, TRUE);
  126. }
  127. $template['partials'][$name] = $partial['string'];
  128. }
  129. }
  130. // Disable sodding IE7's constant cacheing!!
  131. $this->_ci->output->set_header('Expires: Sat, 01 Jan 2000 00:00:01 GMT');
  132. $this->_ci->output->set_header('Cache-Control: no-store, no-cache, must-revalidate');
  133. $this->_ci->output->set_header('Cache-Control: post-check=0, pre-check=0, max-age=0');
  134. $this->_ci->output->set_header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
  135. $this->_ci->output->set_header('Pragma: no-cache');
  136. // Let CI do the caching instead of the browser
  137. $this->_ci->output->cache( $this->cache_lifetime );
  138. // Test to see if this file
  139. $this->_body = $this->_load_view( $view, TRUE, $this->_parser_body_enabled );
  140. // Want this file wrapped with a layout file?
  141. if( $this->_layout )
  142. {
  143. $template['body'] = $this->_body;
  144. // If using a theme, use the layout in the theme
  145. foreach ($this->_theme_locations as $location => $offset)
  146. {
  147. if( $this->_theme && file_exists($location.$this->_theme.'/views/layouts/' . $this->_layout . self::_ext($this->_layout)))
  148. {
  149. // If directory is set, use it
  150. $this->data['theme_view_folder'] = $offset.$this->_theme.'/views/';
  151. $layout_view = $this->data['theme_view_folder'] . 'layouts/' . $this->_layout;
  152. break;
  153. }
  154. }
  155. // No theme layout file was found, lets use whatever they gave us
  156. isset($layout_view) || $layout_view = $this->_layout;
  157. // Parse if parser is enabled, or its a theme view
  158. if($this->_parser_enabled === TRUE || $this->_theme)
  159. {
  160. $this->_body = $this->_ci->parser->parse($layout_view, $this->data, TRUE, TRUE);
  161. }
  162. else
  163. {
  164. $this->_body = $this->_ci->load->view($layout_view, $this->data, TRUE);
  165. }
  166. }
  167. // Want it returned or output to browser?
  168. if(!$return)
  169. {
  170. // Send it to output
  171. $this->_ci->output->set_output($this->_body);
  172. }
  173. return $this->_body;
  174. }
  175. /**
  176. * Set the title of the page
  177. *
  178. * @access public
  179. * @param string
  180. * @return void
  181. */
  182. public function title()
  183. {
  184. // If we have some segments passed
  185. if($title_segments =& func_get_args())
  186. {
  187. $this->_title = implode($this->_title_separator, $title_segments);
  188. }
  189. return $this;
  190. }
  191. /**
  192. * Put extra javascipt, css, meta tags, etc before all other head data
  193. *
  194. * @access public
  195. * @param string $line The line being added to head
  196. * @return void
  197. */
  198. public function prepend_metadata($line)
  199. {
  200. array_unshift($this->_metadata, $line);
  201. return $this;
  202. }
  203. /**
  204. * Put extra javascipt, css, meta tags, etc after other head data
  205. *
  206. * @access public
  207. * @param string $line The line being added to head
  208. * @return void
  209. */
  210. public function append_metadata($line)
  211. {
  212. $this->_metadata[] = $line;
  213. return $this;
  214. }
  215. /**
  216. * Set metadata for output later
  217. *
  218. * @access public
  219. * @param string $name keywords, description, etc
  220. * @param string $content The content of meta data
  221. * @param string $type Meta-data comes in a few types, links for example
  222. * @return void
  223. */
  224. public function set_metadata($name, $content, $type = 'meta')
  225. {
  226. $name = htmlspecialchars(strip_tags($name));
  227. $content = htmlspecialchars(strip_tags($content));
  228. // Keywords with no comments? ARG! comment them
  229. if($name == 'keywords' && !strpos($content, ','))
  230. {
  231. $content = preg_replace('/[\s]+/', ', ', trim($content));
  232. }
  233. switch($type)
  234. {
  235. case 'meta':
  236. $this->_metadata[$name] = '<meta name="'.$name.'" content="'.$content.'" />';
  237. break;
  238. case 'link':
  239. $this->_metadata[$content] = '<link rel="'.$name.'" href="'.$content.'" />';
  240. break;
  241. }
  242. return $this;
  243. }
  244. /**
  245. * Which theme are we using here?
  246. *
  247. * @access public
  248. * @param string $theme Set a theme for the template library to use
  249. * @return void
  250. */
  251. public function set_theme($theme = '')
  252. {
  253. $this->_theme = $theme;
  254. return $this;
  255. }
  256. /**
  257. * Which theme layout should we using here?
  258. *
  259. * @access public
  260. * @param string $view
  261. * @return void
  262. */
  263. public function set_layout($view = '')
  264. {
  265. $this->_layout = $view;
  266. return $this;
  267. }
  268. /**
  269. * Set a view partial
  270. *
  271. * @access public
  272. * @param string
  273. * @param string
  274. * @param boolean
  275. * @return void
  276. */
  277. public function set_partial($name, $view, $search = TRUE)
  278. {
  279. $this->_partials[$name] = array('view' => $view, 'search' => $search);
  280. return $this;
  281. }
  282. /**
  283. * Set a view partial
  284. *
  285. * @access public
  286. * @param string
  287. * @param string
  288. * @param boolean
  289. * @return void
  290. */
  291. public function inject_partial($name, $string, $data = array())
  292. {
  293. $this->_partials[$name] = array('string' => $string, 'data' => $data);
  294. return $this;
  295. }
  296. /**
  297. * Helps build custom breadcrumb trails
  298. *
  299. * @access public
  300. * @param string $name What will appear as the link text
  301. * @param string $url_ref The URL segment
  302. * @return void
  303. */
  304. public function set_breadcrumb($name, $uri = '')
  305. {
  306. $this->_breadcrumbs[] = array('name' => $name, 'uri' => $uri );
  307. return $this;
  308. }
  309. /**
  310. * enable_parser
  311. * Should be parser be used or the view files just loaded normally?
  312. *
  313. * @access public
  314. * @param string $view
  315. * @return void
  316. */
  317. public function enable_parser($bool)
  318. {
  319. $this->_parser_enabled = $bool;
  320. return $this;
  321. }
  322. /**
  323. * enable_parser_body
  324. * Should be parser be used or the body view files just loaded normally?
  325. *
  326. * @access public
  327. * @param string $view
  328. * @return void
  329. */
  330. public function enable_parser_body($bool)
  331. {
  332. $this->_parser_body_enabled = $bool;
  333. return $this;
  334. }
  335. /**
  336. * theme_locations
  337. * List the locations where themes may be stored
  338. *
  339. * @access public
  340. * @param string $view
  341. * @return array
  342. */
  343. public function theme_locations()
  344. {
  345. return $this->_theme_locations;
  346. }
  347. /**
  348. * add_theme_location
  349. * Set another location for themes to be looked in
  350. *
  351. * @access public
  352. * @param string $view
  353. * @return array
  354. */
  355. public function add_theme_location($location, $offset)
  356. {
  357. $this->_theme_locations[$location] = $offset;
  358. }
  359. /**
  360. * theme_exists
  361. * Check if a theme exists
  362. *
  363. * @access public
  364. * @param string $view
  365. * @return array
  366. */
  367. public function theme_exists($theme = NULL)
  368. {
  369. $theme || $theme = $this->_theme;
  370. foreach ($this->_theme_locations as $location => $offset)
  371. {
  372. if( is_dir($location.$theme) )
  373. {
  374. return TRUE;
  375. }
  376. }
  377. return FALSE;
  378. }
  379. /**
  380. * layout_exists
  381. * Check if a theme layout exists
  382. *
  383. * @access public
  384. * @param string $view
  385. * @return array
  386. */
  387. public function theme_layout_exists($layout, $theme = NULL)
  388. {
  389. $theme || $theme = $this->_theme;
  390. foreach ($this->_theme_locations as $location => $offset)
  391. {
  392. if( is_dir($location.$theme) )
  393. {
  394. return file_exists($location.$theme . '/views/layouts/' . $layout . self::_ext($layout));
  395. }
  396. }
  397. return FALSE;
  398. }
  399. /**
  400. * layout_exists
  401. * Check if a theme layout exists
  402. *
  403. * @access public
  404. * @param string $view
  405. * @return array
  406. */
  407. public function get_theme_layouts($theme = NULL)
  408. {
  409. $theme || $theme = $this->_theme;
  410. $layouts = array();
  411. foreach ($this->_theme_locations as $location => $offset)
  412. {
  413. if( is_dir($location.$theme) )
  414. {
  415. foreach(glob($location.$theme . '/views/layouts/*.*') as $layout)
  416. {
  417. $layouts[] = pathinfo($layout, PATHINFO_BASENAME);
  418. }
  419. }
  420. }
  421. return $layouts;
  422. }
  423. // A module view file can be overriden in a theme
  424. private function _load_view($view = '', $search = TRUE, $parse_view = TRUE)
  425. {
  426. // Load exactly what we asked for, no f**king around!
  427. if($search !== TRUE)
  428. {
  429. if($this->_parser_enabled === TRUE && $parse_view === TRUE)
  430. {
  431. return $this->_ci->parser->parse( $view, $this->data, TRUE );
  432. }
  433. else
  434. {
  435. return $this->_ci->load->view( $view, $this->data, TRUE );
  436. }
  437. }
  438. // Only bother looking in themes if there is a theme
  439. if($this->_theme != '')
  440. {
  441. foreach ($this->_theme_locations as $location => $offset)
  442. {
  443. $theme_view = $this->_theme . '/views/modules/' . $this->_module . '/' . $view;
  444. if( file_exists( $location . $theme_view . self::_ext($theme_view) ))
  445. {
  446. if($this->_parser_enabled === TRUE && $parse_view === TRUE)
  447. {
  448. return $this->_ci->parser->parse( $offset.$theme_view, $this->data, TRUE );
  449. }
  450. else
  451. {
  452. return $this->_ci->load->view( $offset.$theme_view, $this->data, TRUE );
  453. }
  454. }
  455. }
  456. }
  457. // Not found it yet? Just load, its either in the module or root view
  458. if($this->_parser_enabled === TRUE && $parse_view === TRUE)
  459. {
  460. return $this->_ci->parser->parse( $this->_module.'/'.$view, $this->data, TRUE );
  461. }
  462. else
  463. {
  464. return $this->_ci->load->view( $this->_module.'/'.$view, $this->data, TRUE );
  465. }
  466. }
  467. private function _guess_title()
  468. {
  469. $this->_ci->load->helper('inflector');
  470. // Obviously no title, lets get making one
  471. $title_parts = array();
  472. // If the method is something other than index, use that
  473. if($this->_method != 'index')
  474. {
  475. $title_parts[] = $this->_method;
  476. }
  477. // Make sure controller name is not the same as the method name
  478. if(!in_array($this->_controller, $title_parts))
  479. {
  480. $title_parts[] = $this->_controller;
  481. }
  482. // Is there a module? Make sure it is not named the same as the method or controller
  483. if(!empty($this->_module) && !in_array($this->_module, $title_parts))
  484. {
  485. $title_parts[] = $this->_module;
  486. }
  487. // Glue the title pieces together using the title separator setting
  488. $title = humanize(implode($this->_title_separator, $title_parts));
  489. return $title;
  490. }
  491. private function _ext($file)
  492. {
  493. return pathinfo($file, PATHINFO_EXTENSION) ? '' : EXT;
  494. }
  495. }
  496. // END Template class