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

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

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