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

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

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