PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

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

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