PageRenderTime 28ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/joomla/application/component/controller.php

https://gitlab.com/endomorphosis/greenrenaissancejoomla
PHP | 721 lines | 308 code | 75 blank | 338 comment | 45 complexity | f45a04ee1cdb55df97b1a9e53d64aa5f MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: controller.php 10111 2008-03-07 11:56:46Z eddieajau $
  4. * @package Joomla.Framework
  5. * @subpackage Application
  6. * @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software. This version may have been modified pursuant
  9. * to the GNU General Public License, and as distributed it includes or
  10. * is derivative of works licensed under the GNU General Public License or
  11. * other free or open source software licenses.
  12. * See COPYRIGHT.php for copyright notices and details.
  13. */
  14. // Check to ensure this file is within the rest of the framework
  15. defined('JPATH_BASE') or die();
  16. /**
  17. * Base class for a Joomla Controller
  18. *
  19. * Controller (controllers are where you put all the actual code) Provides basic
  20. * functionality, such as rendering views (aka displaying templates).
  21. *
  22. * @abstract
  23. * @package Joomla.Framework
  24. * @subpackage Application
  25. * @since 1.5
  26. */
  27. class JController extends JObject
  28. {
  29. /**
  30. * The base path of the controller
  31. *
  32. * @var string
  33. * @access protected
  34. */
  35. var $_basePath = null;
  36. /**
  37. * The name of the controller
  38. *
  39. * @var array
  40. * @access protected
  41. */
  42. var $_name = null;
  43. /**
  44. * Array of class methods
  45. *
  46. * @var array
  47. * @access protected
  48. */
  49. var $_methods = null;
  50. /**
  51. * Array of class methods to call for a given task.
  52. *
  53. * @var array
  54. * @access protected
  55. */
  56. var $_taskMap = null;
  57. /**
  58. * Current or most recent task to be performed.
  59. *
  60. * @var string
  61. * @access protected
  62. */
  63. var $_task = null;
  64. /**
  65. * The mapped task that was performed.
  66. *
  67. * @var string
  68. * @access protected
  69. */
  70. var $_doTask = null;
  71. /**
  72. * The set of search directories for resources (views).
  73. *
  74. * @var array
  75. * @access protected
  76. */
  77. var $_path = array(
  78. 'view' => array()
  79. );
  80. /**
  81. * URL for redirection.
  82. *
  83. * @var string
  84. * @access protected
  85. */
  86. var $_redirect = null;
  87. /**
  88. * Redirect message.
  89. *
  90. * @var string
  91. * @access protected
  92. */
  93. var $_message = null;
  94. /**
  95. * Redirect message type.
  96. *
  97. * @var string
  98. * @access protected
  99. */
  100. var $_messageType = null;
  101. /**
  102. * ACO Section for the controller.
  103. *
  104. * @var string
  105. * @access protected
  106. */
  107. var $_acoSection = null;
  108. /**
  109. * Default ACO Section value for the controller.
  110. *
  111. * @var string
  112. * @access protected
  113. */
  114. var $_acoSectionValue = null;
  115. /**
  116. * Constructor.
  117. *
  118. * @access protected
  119. * @param array An optional associative array of configuration settings.
  120. * Recognized key values include 'name', 'default_task', 'model_path', and
  121. * 'view_path' (this list is not meant to be comprehensive).
  122. * @since 1.5
  123. */
  124. function __construct( $config = array() )
  125. {
  126. //Initialize private variables
  127. $this->_redirect = null;
  128. $this->_message = null;
  129. $this->_messageType = 'message';
  130. $this->_taskMap = array();
  131. $this->_methods = array();
  132. $this->_data = array();
  133. // Get the methods only for the final controller class
  134. $thisMethods = get_class_methods( get_class( $this ) );
  135. $baseMethods = get_class_methods( 'JController' );
  136. $methods = array_diff( $thisMethods, $baseMethods );
  137. // Add default display method
  138. $methods[] = 'display';
  139. // Iterate through methods and map tasks
  140. foreach ( $methods as $method )
  141. {
  142. if ( substr( $method, 0, 1 ) != '_' ) {
  143. $this->_methods[] = strtolower( $method );
  144. // auto register public methods as tasks
  145. $this->_taskMap[strtolower( $method )] = $method;
  146. }
  147. }
  148. //set the view name
  149. if (empty( $this->_name ))
  150. {
  151. if (array_key_exists('name', $config)) {
  152. $this->_name = $config['name'];
  153. } else {
  154. $this->_name = $this->getName();
  155. }
  156. }
  157. // Set a base path for use by the controller
  158. if (array_key_exists('base_path', $config)) {
  159. $this->_basePath = $config['base_path'];
  160. } else {
  161. $this->_basePath = JPATH_COMPONENT;
  162. }
  163. // If the default task is set, register it as such
  164. if ( array_key_exists( 'default_task', $config ) ) {
  165. $this->registerDefaultTask( $config['default_task'] );
  166. } else {
  167. $this->registerDefaultTask( 'display' );
  168. }
  169. // set the default model search path
  170. if ( array_key_exists( 'model_path', $config ) ) {
  171. // user-defined dirs
  172. $this->addModelPath($config['model_path']);
  173. } else {
  174. $this->addModelPath($this->_basePath.DS.'models');
  175. }
  176. // set the default view search path
  177. if ( array_key_exists( 'view_path', $config ) ) {
  178. // user-defined dirs
  179. $this->_setPath( 'view', $config['view_path'] );
  180. } else {
  181. $this->_setPath( 'view', $this->_basePath.DS.'views' );
  182. }
  183. }
  184. /**
  185. * Execute a task by triggering a method in the derived class.
  186. *
  187. * @access public
  188. * @param string The task to perform. If no matching task is found, the
  189. * '__default' task is executed, if defined.
  190. * @return mixed|false The value returned by the called method, false in
  191. * error case.
  192. * @since 1.5
  193. */
  194. function execute( $task )
  195. {
  196. $this->_task = $task;
  197. $task = strtolower( $task );
  198. if (isset( $this->_taskMap[$task] )) {
  199. $doTask = $this->_taskMap[$task];
  200. } elseif (isset( $this->_taskMap['__default'] )) {
  201. $doTask = $this->_taskMap['__default'];
  202. } else {
  203. return JError::raiseError( 404, JText::_('Task ['.$task.'] not found') );
  204. }
  205. // Record the actual task being fired
  206. $this->_doTask = $doTask;
  207. // Make sure we have access
  208. if ($this->authorize( $doTask ))
  209. {
  210. $retval = $this->$doTask();
  211. return $retval;
  212. }
  213. else
  214. {
  215. return JError::raiseError( 403, JText::_('Access Forbidden') );
  216. }
  217. }
  218. /**
  219. * Authorization check
  220. *
  221. * @access public
  222. * @param string $task The ACO Section Value to check access on
  223. * @return boolean True if authorized
  224. * @since 1.5
  225. */
  226. function authorize( $task )
  227. {
  228. // Only do access check if the aco section is set
  229. if ($this->_acoSection)
  230. {
  231. // If we have a section value set that trumps the passed task ???
  232. if ($this->_acoSectionValue) {
  233. // We have one, so set it and lets do the check
  234. $task = $this->_acoSectionValue;
  235. }
  236. // Get the JUser object for the current user and return the authorization boolean
  237. $user = & JFactory::getUser();
  238. return $user->authorize( $this->_acoSection, $task );
  239. }
  240. else
  241. {
  242. // Nothing set, nothing to check... so obviously its ok :)
  243. return true;
  244. }
  245. }
  246. /**
  247. * Typical view method for MVC based architecture
  248. *
  249. * This function is provide as a default implementation, in most cases
  250. * you will need to override it in your own controllers.
  251. *
  252. * @access public
  253. * @param string $cachable If true, the view output will be cached
  254. * @since 1.5
  255. */
  256. function display($cachable=false)
  257. {
  258. $document =& JFactory::getDocument();
  259. $viewType = $document->getType();
  260. $viewName = JRequest::getCmd( 'view', $this->getName() );
  261. $viewLayout = JRequest::getCmd( 'layout', 'default' );
  262. $view = & $this->getView( $viewName, $viewType, '', array( 'base_path'=>$this->_basePath));
  263. // Get/Create the model
  264. if ($model = & $this->getModel($viewName)) {
  265. // Push the model into the view (as default)
  266. $view->setModel($model, true);
  267. }
  268. // Set the layout
  269. $view->setLayout($viewLayout);
  270. // Display the view
  271. if ($cachable) {
  272. global $option;
  273. $cache =& JFactory::getCache($option, 'view');
  274. $cache->get($view, 'display');
  275. } else {
  276. $view->display();
  277. }
  278. }
  279. /**
  280. * Redirects the browser or returns false if no redirect is set.
  281. *
  282. * @access public
  283. * @return boolean False if no redirect exists.
  284. * @since 1.5
  285. */
  286. function redirect()
  287. {
  288. if ($this->_redirect) {
  289. global $mainframe;
  290. $mainframe->redirect( $this->_redirect, $this->_message, $this->_messageType );
  291. }
  292. return false;
  293. }
  294. /**
  295. * Method to get a model object, loading it if required.
  296. *
  297. * @access public
  298. * @param string The model name. Optional.
  299. * @param string The class prefix. Optional.
  300. * @param array Configuration array for model. Optional.
  301. * @return object The model.
  302. * @since 1.5
  303. */
  304. function &getModel( $name = '', $prefix = '', $config = array() )
  305. {
  306. if ( empty( $name ) ) {
  307. $name = $this->getName();
  308. }
  309. if ( empty( $prefix ) ) {
  310. $prefix = $this->getName() . 'Model';
  311. }
  312. if ( $model = & $this->_createModel( $name, $prefix, $config ) )
  313. {
  314. // task is a reserved state
  315. $model->setState( 'task', $this->_task );
  316. // Lets get the application object and set menu information if its available
  317. $app = &JFactory::getApplication();
  318. $menu = &$app->getMenu();
  319. if (is_object( $menu ))
  320. {
  321. if ($item = $menu->getActive())
  322. {
  323. $params =& $menu->getParams($item->id);
  324. // Set Default State Data
  325. $model->setState( 'parameters.menu', $params );
  326. }
  327. }
  328. }
  329. return $model;
  330. }
  331. /**
  332. * Adds to the stack of model paths in LIFO order.
  333. *
  334. * @static
  335. * @param string|array The directory (string), or list of directories
  336. * (array) to add.
  337. * @return void
  338. */
  339. function addModelPath( $path )
  340. {
  341. jimport('joomla.application.component.model');
  342. JModel::addIncludePath($path);
  343. }
  344. /**
  345. * Gets the available tasks in the controller.
  346. * @access public
  347. * @return array Array[i] of task names.
  348. * @since 1.5
  349. */
  350. function getTasks()
  351. {
  352. return $this->_methods;
  353. }
  354. /**
  355. * Get the last task that is or was to be performed.
  356. *
  357. * @access public
  358. * @return string The task that was or is being performed.
  359. * @since 1.5
  360. */
  361. function getTask()
  362. {
  363. return $this->_task;
  364. }
  365. /**
  366. * Method to get the controller name
  367. *
  368. * The dispatcher name by default parsed using the classname, or it can be set
  369. * by passing a $config['name'] in the class constructor
  370. *
  371. * @access public
  372. * @return string The name of the dispatcher
  373. * @since 1.5
  374. */
  375. function getName()
  376. {
  377. $name = $this->_name;
  378. if (empty( $name ))
  379. {
  380. $r = null;
  381. if ( !preg_match( '/(.*)Controller/i', get_class( $this ), $r ) ) {
  382. JError::raiseError(500, "JController::getName() : Cannot get or parse class name.");
  383. }
  384. $name = strtolower( $r[1] );
  385. }
  386. return $name;
  387. }
  388. /**
  389. * Method to get a reference to the current view and load it if necessary.
  390. *
  391. * @access public
  392. * @param string The view name. Optional, defaults to the controller
  393. * name.
  394. * @param string The view type. Optional.
  395. * @param string The class prefix. Optional.
  396. * @param array Configuration array for view. Optional.
  397. * @return object Reference to the view or an error.
  398. * @since 1.5
  399. */
  400. function &getView( $name = '', $type = '', $prefix = '', $config = array() )
  401. {
  402. static $views;
  403. if ( !isset( $views ) ) {
  404. $views = array();
  405. }
  406. if ( empty( $name ) ) {
  407. $name = $this->getName();
  408. }
  409. if ( empty( $prefix ) ) {
  410. $prefix = $this->getName() . 'View';
  411. }
  412. if ( empty( $views[$name] ) )
  413. {
  414. if ( $view = & $this->_createView( $name, $prefix, $type, $config ) ) {
  415. $views[$name] = & $view;
  416. } else {
  417. $result = JError::raiseError(
  418. 500, JText::_( 'View not found [name, type, prefix]:' )
  419. . ' ' . $name . ',' . $type . ',' . $prefix
  420. );
  421. return $result;
  422. }
  423. }
  424. return $views[$name];
  425. }
  426. /**
  427. * Add one or more view paths to the controller's stack, in LIFO order.
  428. *
  429. * @static
  430. * @param string|array The directory (string), or list of directories
  431. * (array) to add.
  432. * @return void
  433. */
  434. function addViewPath( $path )
  435. {
  436. $this->_addPath( 'view', $path );
  437. }
  438. /**
  439. * Register (map) a task to a method in the class.
  440. *
  441. * @access public
  442. * @param string The task.
  443. * @param string The name of the method in the derived class to perform
  444. * for this task.
  445. * @return void
  446. * @since 1.5
  447. */
  448. function registerTask( $task, $method )
  449. {
  450. if ( in_array( strtolower( $method ), $this->_methods ) ) {
  451. $this->_taskMap[strtolower( $task )] = $method;
  452. }
  453. }
  454. /**
  455. * Register the default task to perform if a mapping is not found.
  456. *
  457. * @access public
  458. * @param string The name of the method in the derived class to perform if
  459. * a named task is not found.
  460. * @return void
  461. * @since 1.5
  462. */
  463. function registerDefaultTask( $method )
  464. {
  465. $this->registerTask( '__default', $method );
  466. }
  467. /**
  468. * Sets the internal message that is passed with a redirect
  469. *
  470. * @access public
  471. * @param string The message
  472. * @return string Previous message
  473. * @since 1.5
  474. */
  475. function setMessage( $text )
  476. {
  477. $previous = $this->_message;
  478. $this->_message = $text;
  479. return $previous;
  480. }
  481. /**
  482. * Set a URL for browser redirection.
  483. *
  484. * @access public
  485. * @param string URL to redirect to.
  486. * @param string Message to display on redirect. Optional, defaults to
  487. * value set internally by controller, if any.
  488. * @param string Message type. Optional, defaults to 'message'.
  489. * @return void
  490. * @since 1.5
  491. */
  492. function setRedirect( $url, $msg = null, $type = 'message' )
  493. {
  494. $this->_redirect = $url;
  495. if ($msg !== null) {
  496. // controller may have set this directly
  497. $this->_message = $msg;
  498. }
  499. $this->_messageType = $type;
  500. }
  501. /**
  502. * Sets the access control levels.
  503. *
  504. * @access public
  505. * @param string The ACO section (eg, the component).
  506. * @param string The ACO section value (if using a constant value).
  507. * @return void
  508. * @since 1.5
  509. */
  510. function setAccessControl( $section, $value = null )
  511. {
  512. $this->_acoSection = $section;
  513. $this->_acoSectionValue = $value;
  514. }
  515. /**
  516. * Method to load and return a model object.
  517. *
  518. * @access private
  519. * @param string The name of the model.
  520. * @param string Optional model prefix.
  521. * @param array Configuration array for the model. Optional.
  522. * @return mixed Model object on success; otherwise null
  523. * failure.
  524. * @since 1.5
  525. */
  526. function &_createModel( $name, $prefix = '', $config = array())
  527. {
  528. $result = null;
  529. // Clean the model name
  530. $modelName = preg_replace( '/[^A-Z0-9_]/i', '', $name );
  531. $classPrefix = preg_replace( '/[^A-Z0-9_]/i', '', $prefix );
  532. $result =& JModel::getInstance($modelName, $classPrefix, $config);
  533. return $result;
  534. }
  535. /**
  536. * Method to load and return a view object. This method first looks in the
  537. * current template directory for a match, and failing that uses a default
  538. * set path to load the view class file.
  539. *
  540. * Note the "name, prefix, type" order of parameters, which differs from the
  541. * "name, type, prefix" order used in related public methods.
  542. *
  543. * @access private
  544. * @param string The name of the view.
  545. * @param string Optional prefix for the view class name.
  546. * @param string The type of view.
  547. * @param array Configuration array for the view. Optional.
  548. * @return mixed View object on success; null or error result on failure.
  549. * @since 1.5
  550. */
  551. function &_createView( $name, $prefix = '', $type = '', $config = array() )
  552. {
  553. $result = null;
  554. // Clean the view name
  555. $viewName = preg_replace( '/[^A-Z0-9_]/i', '', $name );
  556. $classPrefix = preg_replace( '/[^A-Z0-9_]/i', '', $prefix );
  557. $viewType = preg_replace( '/[^A-Z0-9_]/i', '', $type );
  558. // Build the view class name
  559. $viewClass = $classPrefix . $viewName;
  560. if ( !class_exists( $viewClass ) )
  561. {
  562. jimport( 'joomla.filesystem.path' );
  563. $path = JPath::find(
  564. $this->_path['view'],
  565. $this->_createFileName( 'view', array( 'name' => $viewName, 'type' => $viewType) )
  566. );
  567. if ($path) {
  568. require_once $path;
  569. if ( !class_exists( $viewClass ) ) {
  570. $result = JError::raiseError(
  571. 500, JText::_( 'View class not found [class, file]:' )
  572. . ' ' . $viewClass . ', ' . $path );
  573. return $result;
  574. }
  575. } else {
  576. return $result;
  577. }
  578. }
  579. $result = new $viewClass($config);
  580. return $result;
  581. }
  582. /**
  583. * Sets an entire array of search paths for resources.
  584. *
  585. * @access protected
  586. * @param string The type of path to set, typically 'view' or 'model'.
  587. * @param string|array The new set of search paths. If null or false,
  588. * resets to the current directory only.
  589. */
  590. function _setPath( $type, $path )
  591. {
  592. // clear out the prior search dirs
  593. $this->_path[$type] = array();
  594. // actually add the user-specified directories
  595. $this->_addPath( $type, $path );
  596. }
  597. /**
  598. * Adds to the search path for templates and resources.
  599. *
  600. * @access protected
  601. * @param string The path type (e.g. 'model', 'view'.
  602. * @param string|array The directory or stream to search.
  603. * @return void
  604. */
  605. function _addPath( $type, $path )
  606. {
  607. // just force path to array
  608. settype( $path, 'array' );
  609. // loop through the path directories
  610. foreach ( $path as $dir )
  611. {
  612. // no surrounding spaces allowed!
  613. $dir = trim( $dir );
  614. // add trailing separators as needed
  615. if ( substr( $dir, -1 ) != DIRECTORY_SEPARATOR ) {
  616. // directory
  617. $dir .= DIRECTORY_SEPARATOR;
  618. }
  619. // add to the top of the search dirs
  620. array_unshift( $this->_path[$type], $dir );
  621. }
  622. }
  623. /**
  624. * Create the filename for a resource.
  625. *
  626. * @access private
  627. * @param string The resource type to create the filename for.
  628. * @param array An associative array of filename information. Optional.
  629. * @return string The filename.
  630. * @since 1.5
  631. */
  632. function _createFileName( $type, $parts = array() )
  633. {
  634. $filename = '';
  635. switch ( $type )
  636. {
  637. case 'view':
  638. if ( !empty( $parts['type'] ) ) {
  639. $parts['type'] = '.'.$parts['type'];
  640. }
  641. $filename = strtolower($parts['name']).DS.'view'.$parts['type'].'.php';
  642. break;
  643. }
  644. return $filename;
  645. }
  646. }