PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/application/component/view.php

https://bitbucket.org/ankursaxena_2/joomla-platform
PHP | 704 lines | 306 code | 81 blank | 317 comment | 56 complexity | b5de476c1aeb59012ffd9a390d3f5317 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Application
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Base class for a Joomla View
  12. *
  13. * Class holding methods for displaying presentation data.
  14. *
  15. * @abstract
  16. * @package Joomla.Platform
  17. * @subpackage Application
  18. * @since 11.1
  19. */
  20. class JView extends JObject
  21. {
  22. /**
  23. * The name of the view
  24. *
  25. * @var array
  26. */
  27. protected $_name = null;
  28. /**
  29. * Registered models
  30. *
  31. * @var array
  32. */
  33. protected $_models = array();
  34. /**
  35. * The base path of the view
  36. *
  37. * @var string
  38. */
  39. protected $_basePath = null;
  40. /**
  41. * The default model
  42. *
  43. * @var string
  44. */
  45. protected $_defaultModel = null;
  46. /**
  47. * Layout name
  48. *
  49. * @var string
  50. */
  51. protected $_layout = 'default';
  52. /**
  53. * Layout extension
  54. *
  55. * @var string
  56. */
  57. protected $_layoutExt = 'php';
  58. /**
  59. * Layout template
  60. *
  61. * @var string
  62. */
  63. protected $_layoutTemplate = '_';
  64. /**
  65. * The set of search directories for resources (templates)
  66. *
  67. * @var array
  68. */
  69. protected $_path = array(
  70. 'template' => array(),
  71. 'helper' => array()
  72. );
  73. /**
  74. * The name of the default template source file.
  75. *
  76. * @var string
  77. */
  78. private $_template = null;
  79. /**
  80. * The output of the template script.
  81. *
  82. * @var string
  83. */
  84. private $_output = null;
  85. /**
  86. * Callback for escaping.
  87. *
  88. * @var string
  89. */
  90. private $_escape = 'htmlspecialchars';
  91. /**
  92. * Charset to use in escaping mechanisms; defaults to urf8 (UTF-8)
  93. *
  94. * @var string
  95. */
  96. private $_charset = 'UTF-8';
  97. /**
  98. * Constructor
  99. *
  100. */
  101. protected function __construct($config = array())
  102. {
  103. // Set the view name
  104. if (empty($this->_name))
  105. {
  106. if (array_key_exists('name', $config)) {
  107. $this->_name = $config['name'];
  108. } else {
  109. $this->_name = $this->getName();
  110. }
  111. }
  112. // Set the charset (used by the variable escaping functions)
  113. if (array_key_exists('charset', $config)) {
  114. $this->_charset = $config['charset'];
  115. }
  116. // User-defined escaping callback
  117. if (array_key_exists('escape', $config)) {
  118. $this->setEscape($config['escape']);
  119. }
  120. // Set a base path for use by the view
  121. if (array_key_exists('base_path', $config)) {
  122. $this->_basePath = $config['base_path'];
  123. } else {
  124. $this->_basePath = JPATH_COMPONENT;
  125. }
  126. // Set the default template search path
  127. if (array_key_exists('template_path', $config)) {
  128. // User-defined dirs
  129. $this->_setPath('template', $config['template_path']);
  130. } else {
  131. $this->_setPath('template', $this->_basePath.DS.'views'.DS.$this->getName().DS.'tmpl');
  132. }
  133. // Set the default helper search path
  134. if (array_key_exists('helper_path', $config)) {
  135. // User-defined dirs
  136. $this->_setPath('helper', $config['helper_path']);
  137. } else {
  138. $this->_setPath('helper', $this->_basePath.DS.'helpers');
  139. }
  140. // Set the layout
  141. if (array_key_exists('layout', $config)) {
  142. $this->setLayout($config['layout']);
  143. } else {
  144. $this->setLayout('default');
  145. }
  146. $this->baseurl = JURI::base(true);
  147. }
  148. /**
  149. * Execute and display a template script.
  150. *
  151. * @param string The name of the template file to parse;
  152. * automatically searches through the template paths.
  153. *
  154. * @throws object An JError object.
  155. * @see fetch()
  156. */
  157. function display($tpl = null)
  158. {
  159. $result = $this->loadTemplate($tpl);
  160. if (JError::isError($result)) {
  161. return $result;
  162. }
  163. echo $result;
  164. }
  165. /**
  166. * Assigns variables to the view script via differing strategies.
  167. *
  168. * This method is overloaded; you can assign all the properties of
  169. * an object, an associative array, or a single value by name.
  170. *
  171. * You are not allowed to set variables that begin with an underscore;
  172. * these are either private properties for JView or private variables
  173. * within the template script itself.
  174. *
  175. * <code>
  176. * $view = new JView();
  177. *
  178. * // Assign directly
  179. * $view->var1 = 'something';
  180. * $view->var2 = 'else';
  181. *
  182. * // Assign by name and value
  183. * $view->assign('var1', 'something');
  184. * $view->assign('var2', 'else');
  185. *
  186. * // Assign by assoc-array
  187. * $ary = array('var1' => 'something', 'var2' => 'else');
  188. * $view->assign($obj);
  189. *
  190. * // Assign by object
  191. * $obj = new stdClass;
  192. * $obj->var1 = 'something';
  193. * $obj->var2 = 'else';
  194. * $view->assign($obj);
  195. *
  196. * </code>
  197. *
  198. * @return bool True on success, false on failure.
  199. */
  200. public function assign()
  201. {
  202. // Get the arguments; there may be 1 or 2.
  203. $arg0 = @func_get_arg(0);
  204. $arg1 = @func_get_arg(1);
  205. // Assign by object
  206. if (is_object($arg0))
  207. {
  208. // Assign public properties
  209. foreach (get_object_vars($arg0) as $key => $val)
  210. {
  211. if (substr($key, 0, 1) != '_') {
  212. $this->$key = $val;
  213. }
  214. }
  215. return true;
  216. }
  217. // Assign by associative array
  218. if (is_array($arg0))
  219. {
  220. foreach ($arg0 as $key => $val)
  221. {
  222. if (substr($key, 0, 1) != '_') {
  223. $this->$key = $val;
  224. }
  225. }
  226. return true;
  227. }
  228. // Assign by string name and mixed value.
  229. // We use array_key_exists() instead of isset() becuase isset()
  230. // fails if the value is set to null.
  231. if (is_string($arg0) && substr($arg0, 0, 1) != '_' && func_num_args() > 1)
  232. {
  233. $this->$arg0 = $arg1;
  234. return true;
  235. }
  236. // $arg0 was not object, array, or string.
  237. return false;
  238. }
  239. /**
  240. * Assign variable for the view (by reference).
  241. *
  242. * You are not allowed to set variables that begin with an underscore;
  243. * these are either private properties for JView or private variables
  244. * within the template script itself.
  245. *
  246. * <code>
  247. * $view = new JView();
  248. *
  249. * // Assign by name and value
  250. * $view->assignRef('var1', $ref);
  251. *
  252. * // Assign directly
  253. * $view->ref = &$var1;
  254. * </code>
  255. *
  256. *
  257. * @param string The name for the reference in the view.
  258. * @param mixed The referenced variable.
  259. *
  260. * @return bool True on success, false on failure.
  261. */
  262. public function assignRef($key, &$val)
  263. {
  264. if (is_string($key) && substr($key, 0, 1) != '_')
  265. {
  266. $this->$key = &$val;
  267. return true;
  268. }
  269. return false;
  270. }
  271. /**
  272. * Escapes a value for output in a view script.
  273. *
  274. * If escaping mechanism is either htmlspecialchars or htmlentities, uses
  275. * {@link $_encoding} setting.
  276. *
  277. * @param mixed The output to escape.
  278. * @return mixed The escaped value.
  279. */
  280. function escape($var)
  281. {
  282. if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) {
  283. return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_charset);
  284. }
  285. return call_user_func($this->_escape, $var);
  286. }
  287. /**
  288. * Method to get data from a registered model or a property of the view
  289. *
  290. * @param string The name of the method to call on the model or the property to get
  291. * @param string The name of the model to reference or the default value [optional]
  292. * @return mixed The return value of the method
  293. */
  294. public function get($property, $default = null)
  295. {
  296. // If $model is null we use the default model
  297. if (is_null($default)) {
  298. $model = $this->_defaultModel;
  299. } else {
  300. $model = strtolower($default);
  301. }
  302. // First check to make sure the model requested exists
  303. if (isset($this->_models[$model]))
  304. {
  305. // Model exists, let's build the method name
  306. $method = 'get'.ucfirst($property);
  307. // Does the method exist?
  308. if (method_exists($this->_models[$model], $method))
  309. {
  310. // The method exists, let's call it and return what we get
  311. $result = $this->_models[$model]->$method();
  312. return $result;
  313. }
  314. }
  315. // Degrade to JObject::get
  316. $result = parent::get($property, $default);
  317. return $result;
  318. }
  319. /**
  320. * Method to get the model object
  321. *
  322. * @param string The name of the model (optional)
  323. * @return mixed JModel object
  324. */
  325. public function getModel($name = null)
  326. {
  327. if ($name === null) {
  328. $name = $this->_defaultModel;
  329. }
  330. return $this->_models[strtolower($name)];
  331. }
  332. /**
  333. * Get the layout.
  334. *
  335. * @return string The layout name
  336. */
  337. public function getLayout()
  338. {
  339. return $this->_layout;
  340. }
  341. /**
  342. * Get the layout template.
  343. *
  344. * @return string The layout template name
  345. */
  346. public function getLayoutTemplate()
  347. {
  348. return $this->_layoutTemplate;
  349. }
  350. /**
  351. * Method to get the view name
  352. *
  353. * The model name by default parsed using the classname, or it can be set
  354. * by passing a $config['name'] in the class constructor
  355. *
  356. * @return string The name of the model
  357. * @since 11.1
  358. */
  359. public function getName()
  360. {
  361. $name = $this->_name;
  362. if (empty($name))
  363. {
  364. $r = null;
  365. if (!preg_match('/View((view)*(.*(view)?.*))$/i', get_class($this), $r)) {
  366. JError::raiseError (500, JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME'));
  367. }
  368. if (strpos($r[3], "view"))
  369. {
  370. JError::raiseWarning('SOME_ERROR_CODE',JText::_('JLIB_APPLICATION_ERROR_VIEW_GET_NAME_SUBSTRING'));
  371. }
  372. $name = strtolower($r[3]);
  373. }
  374. return $name;
  375. }
  376. /**
  377. * Method to add a model to the view. We support a multiple model single
  378. * view system by which models are referenced by classname. A caveat to the
  379. * classname referencing is that any classname prepended by JModel will be
  380. * referenced by the name without JModel, eg. JModelCategory is just
  381. * Category.
  382. *
  383. * @param object The model to add to the view.
  384. * @param boolean Is this the default model?
  385. * @return object The added model
  386. */
  387. public function setModel(&$model, $default = false)
  388. {
  389. $name = strtolower($model->getName());
  390. $this->_models[$name] = &$model;
  391. if ($default) {
  392. $this->_defaultModel = $name;
  393. }
  394. return $model;
  395. }
  396. /**
  397. * Sets the layout name to use
  398. *
  399. * @param string The layout name or a string in format <template>:<layout file>
  400. * @return string Previous value
  401. * @since 11.1
  402. */
  403. public function setLayout($layout)
  404. {
  405. $previous = $this->_layout;
  406. if (strpos($layout, ':') === false )
  407. {
  408. $this->_layout = $layout;
  409. }
  410. else
  411. {
  412. // Convert parameter to array based on :
  413. $temp = explode(':', $layout);
  414. $this->_layout = $temp[1];
  415. // Set layout template
  416. $this->_layoutTemplate = $temp[0];
  417. }
  418. return $previous;
  419. }
  420. /**
  421. * Allows a different extension for the layout files to be used
  422. *
  423. * @param string The extension
  424. * @return string Previous value
  425. * @since 11.1
  426. */
  427. public function setLayoutExt($value)
  428. {
  429. $previous = $this->_layoutExt;
  430. if ($value = preg_replace('#[^A-Za-z0-9]#', '', trim($value))) {
  431. $this->_layoutExt = $value;
  432. }
  433. return $previous;
  434. }
  435. /**
  436. * Sets the _escape() callback.
  437. *
  438. * @param mixed The callback for _escape() to use.
  439. */
  440. function setEscape($spec)
  441. {
  442. $this->_escape = $spec;
  443. }
  444. /**
  445. * Adds to the stack of view script paths in LIFO order.
  446. *
  447. * @param string|array The directory (-ies) to add.
  448. * @return void
  449. */
  450. function addTemplatePath($path)
  451. {
  452. $this->_addPath('template', $path);
  453. }
  454. /**
  455. * Adds to the stack of helper script paths in LIFO order.
  456. *
  457. * @param string|array The directory (-ies) to add.
  458. * @return void
  459. */
  460. function addHelperPath($path)
  461. {
  462. $this->_addPath('helper', $path);
  463. }
  464. /**
  465. * Load a template file -- first look in the templates folder for an override
  466. *
  467. * @param string The name of the template source file ...
  468. * automatically searches the template paths and compiles as needed.
  469. * @return string The output of the the template script.
  470. */
  471. public function loadTemplate($tpl = null)
  472. {
  473. // clear prior output
  474. $this->_output = null;
  475. $template = JFactory::getApplication()->getTemplate();
  476. $layout = $this->getLayout();
  477. $layoutTemplate = $this->getLayoutTemplate();
  478. // Create the template file name based on the layout
  479. $file = isset($tpl) ? $layout.'_'.$tpl : $layout;
  480. // Clean the file name
  481. $file = preg_replace('/[^A-Z0-9_\.-]/i', '', $file);
  482. $tpl = isset($tpl)? preg_replace('/[^A-Z0-9_\.-]/i', '', $tpl) : $tpl;
  483. // Load the language file for the template
  484. $lang = JFactory::getLanguage();
  485. $lang->load('tpl_'.$template, JPATH_BASE, null, false, false)
  486. || $lang->load('tpl_'.$template, JPATH_THEMES."/$template", null, false, false)
  487. || $lang->load('tpl_'.$template, JPATH_BASE, $lang->getDefault(), false, false)
  488. || $lang->load('tpl_'.$template, JPATH_THEMES."/$template", $lang->getDefault(), false, false);
  489. // Change the template folder if alternative layout is in different template
  490. if (isset($layoutTemplate) && $layoutTemplate != '_' && $layoutTemplate != $template)
  491. {
  492. $this->_path['template'] = str_replace($template, $layoutTemplate, $this->_path['template']);
  493. }
  494. // Load the template script
  495. jimport('joomla.filesystem.path');
  496. $filetofind = $this->_createFileName('template', array('name' => $file));
  497. $this->_template = JPath::find($this->_path['template'], $filetofind);
  498. // If alternate layout can't be found, fall back to default layout
  499. if ($this->_template == false)
  500. {
  501. $filetofind = $this->_createFileName('', array('name' => 'default' . (isset($tpl) ? '_' . $tpl : $tpl)));
  502. $this->_template = JPath::find($this->_path['template'], $filetofind);
  503. }
  504. if ($this->_template != false)
  505. {
  506. // Unset so as not to introduce into template scope
  507. unset($tpl);
  508. unset($file);
  509. // Never allow a 'this' property
  510. if (isset($this->this)) {
  511. unset($this->this);
  512. }
  513. // Start capturing output into a buffer
  514. ob_start();
  515. // Include the requested template filename in the local scope
  516. // (this will execute the view logic).
  517. include $this->_template;
  518. // Done with the requested template; get the buffer and
  519. // clear it.
  520. $this->_output = ob_get_contents();
  521. ob_end_clean();
  522. return $this->_output;
  523. }
  524. else {
  525. return JError::raiseError(500, JText::sprintf('JLIB_APPLICATION_ERROR_LAYOUTFILE_NOT_FOUND', $file));
  526. }
  527. }
  528. /**
  529. * Load a helper file
  530. *
  531. * @param string The name of the helper source file ...
  532. * automatically searches the helper paths and compiles as needed.
  533. * @return boolean Returns true if the file was loaded
  534. */
  535. public function loadHelper($hlp = null)
  536. {
  537. // clean the file name
  538. $file = preg_replace('/[^A-Z0-9_\.-]/i', '', $hlp);
  539. // load the template script
  540. jimport('joomla.filesystem.path');
  541. $helper = JPath::find($this->_path['helper'], $this->_createFileName('helper', array('name' => $file)));
  542. if ($helper != false)
  543. {
  544. // Include the requested template filename in the local scope
  545. include_once $helper;
  546. }
  547. }
  548. /**
  549. * Sets an entire array of search paths for templates or resources.
  550. *
  551. * @param string The type of path to set, typically 'template'.
  552. * @param string|array The new set of search paths. If null or false, resets to the current directory only.
  553. */
  554. protected function _setPath($type, $path)
  555. {
  556. jimport('joomla.application.helper');
  557. $component = JApplicationHelper::getComponentName();
  558. $app = JFactory::getApplication();
  559. // Clear out the prior search dirs
  560. $this->_path[$type] = array();
  561. // Actually add the user-specified directories
  562. $this->_addPath($type, $path);
  563. // Always add the fallback directories as last resort
  564. switch (strtolower($type))
  565. {
  566. case 'template':
  567. // Set the alternative template search dir
  568. if (isset($app))
  569. {
  570. $component = preg_replace('/[^A-Z0-9_\.-]/i', '', $component);
  571. $fallback = JPATH_THEMES.DS.$app->getTemplate().DS.'html'.DS.$component.DS.$this->getName();
  572. $this->_addPath('template', $fallback);
  573. }
  574. break;
  575. }
  576. }
  577. /**
  578. * Adds to the search path for templates and resources.
  579. *
  580. * @param string|array The directory or stream to search.
  581. */
  582. protected function _addPath($type, $path)
  583. {
  584. // just force to array
  585. settype($path, 'array');
  586. // loop through the path directories
  587. foreach ($path as $dir)
  588. {
  589. // no surrounding spaces allowed!
  590. $dir = trim($dir);
  591. // add trailing separators as needed
  592. if (substr($dir, -1) != DIRECTORY_SEPARATOR) {
  593. // directory
  594. $dir .= DIRECTORY_SEPARATOR;
  595. }
  596. // Add to the top of the search dirs
  597. array_unshift($this->_path[$type], $dir);
  598. }
  599. }
  600. /**
  601. * Create the filename for a resource
  602. *
  603. * @param string The resource type to create the filename for
  604. * @param array An associative array of filename information
  605. *
  606. * @return string The filename
  607. * @since 11.1
  608. */
  609. private function _createFileName($type, $parts = array())
  610. {
  611. $filename = '';
  612. switch($type)
  613. {
  614. case 'template' :
  615. $filename = strtolower($parts['name']).'.'.$this->_layoutExt;
  616. break;
  617. default :
  618. $filename = strtolower($parts['name']).'.php';
  619. break;
  620. }
  621. return $filename;
  622. }
  623. }