PageRenderTime 75ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/fof/controller/controller.php

https://github.com/J2MTecnologia/joomla-3.x
PHP | 3313 lines | 1931 code | 559 blank | 823 comment | 279 complexity | cb04c4cccc0789bf47b854ecaf834974 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * @package FrameworkOnFramework
  4. * @subpackage controller
  5. * @copyright Copyright (C) 2010 - 2014 Akeeba Ltd. All rights reserved.
  6. * @license GNU General Public License version 2 or later; see LICENSE.txt
  7. */
  8. // Protect from unauthorized access
  9. defined('FOF_INCLUDED') or die;
  10. /**
  11. * FrameworkOnFramework controller class. FOF is based on the thin controller
  12. * paradigm, where the controller is mainly used to set up the model state and
  13. * spawn the view.
  14. *
  15. * @package FrameworkOnFramework
  16. * @since 1.0
  17. */
  18. class FOFController extends FOFUtilsObject
  19. {
  20. /**
  21. * @var int Bit mask to enable Routing on redirects.
  22. * 0 = never
  23. * 1 = frontend only
  24. * 2 = backend only
  25. * 3 = always
  26. */
  27. protected $autoRouting = 0;
  28. /**
  29. * The current component's name without the com_ prefix
  30. *
  31. * @var string
  32. */
  33. protected $bareComponent = 'foobar';
  34. /**
  35. * The base path of the controller
  36. *
  37. * @var string
  38. */
  39. protected $basePath;
  40. /**
  41. * The tasks for which caching should be enabled by default
  42. *
  43. * @var array
  44. */
  45. protected $cacheableTasks = array('browse', 'read');
  46. /**
  47. * The current component's name; you can override it in the configuration
  48. *
  49. * @var string
  50. */
  51. protected $component = 'com_foobar';
  52. /**
  53. * A cached copy of the class configuration parameter passed during initialisation
  54. *
  55. * @var array
  56. */
  57. protected $config = array();
  58. /**
  59. * An instance of FOFConfigProvider to provision configuration overrides
  60. *
  61. * @var FOFConfigProvider
  62. */
  63. protected $configProvider = null;
  64. /**
  65. * Set to true to enable CSRF protection on selected tasks. The possible
  66. * values are:
  67. * 0 Disabled; no token checks are performed
  68. * 1 Enabled; token checks are always performed
  69. * 2 Only on HTML requests and backend; token checks are always performed in the back-end and in the front-end only when format is 'html'
  70. * 3 Only on back-end; token checks are performer only in the back-end
  71. *
  72. * @var integer
  73. */
  74. protected $csrfProtection = 2;
  75. /**
  76. * The default view for the display method.
  77. *
  78. * @var string
  79. */
  80. protected $default_view;
  81. /**
  82. * The mapped task that was performed.
  83. *
  84. * @var string
  85. */
  86. protected $doTask;
  87. /**
  88. * The input object for this MVC triad; you can override it in the configuration
  89. *
  90. * @var FOFInput
  91. */
  92. protected $input = array();
  93. /**
  94. * Redirect message.
  95. *
  96. * @var string
  97. */
  98. protected $message;
  99. /**
  100. * Redirect message type.
  101. *
  102. * @var string
  103. */
  104. protected $messageType;
  105. /**
  106. * The current layout; you can override it in the configuration
  107. *
  108. * @var string
  109. */
  110. protected $layout = null;
  111. /**
  112. * Array of class methods
  113. *
  114. * @var array
  115. */
  116. protected $methods;
  117. /**
  118. * The prefix of the models
  119. *
  120. * @var string
  121. */
  122. protected $model_prefix;
  123. /**
  124. * Overrides the name of the view's default model
  125. *
  126. * @var string
  127. */
  128. protected $modelName = null;
  129. /**
  130. * The set of search directories for resources (views).
  131. *
  132. * @var array
  133. */
  134. protected $paths;
  135. /**
  136. * URL for redirection.
  137. *
  138. * @var string
  139. */
  140. protected $redirect;
  141. /**
  142. * Current or most recently performed task.
  143. *
  144. * @var string
  145. */
  146. protected $task;
  147. /**
  148. * Array of class methods to call for a given task.
  149. *
  150. * @var array
  151. */
  152. protected $taskMap;
  153. /**
  154. * The name of the controller
  155. *
  156. * @var array
  157. */
  158. protected $name;
  159. /**
  160. * The current view name; you can override it in the configuration
  161. *
  162. * @var string
  163. */
  164. protected $view = '';
  165. /**
  166. * Overrides the name of the view's default view
  167. *
  168. * @var string
  169. */
  170. protected $viewName = null;
  171. /**
  172. * A copy of the FOFView object used in this triad
  173. *
  174. * @var FOFView
  175. */
  176. private $_viewObject = null;
  177. /**
  178. * A cache for the view item objects created in this controller
  179. *
  180. * @var array
  181. */
  182. protected $viewsCache = array();
  183. /**
  184. * A copy of the FOFModel object used in this triad
  185. *
  186. * @var FOFModel
  187. */
  188. private $_modelObject = null;
  189. /**
  190. * Does this tried have a FOFForm which will be used to render it?
  191. *
  192. * @var boolean
  193. */
  194. protected $hasForm = false;
  195. /**
  196. * Gets a static (Singleton) instance of a controller class. It loads the
  197. * relevant controller file from the component's directory or, if it doesn't
  198. * exist, creates a new controller object out of thin air.
  199. *
  200. * @param string $option Component name, e.g. com_foobar
  201. * @param string $view The view name, also used for the controller name
  202. * @param array $config Configuration parameters
  203. *
  204. * @return FOFController
  205. */
  206. public static function &getAnInstance($option = null, $view = null, $config = array())
  207. {
  208. static $instances = array();
  209. // Make sure $config is an array
  210. if (is_object($config))
  211. {
  212. $config = (array) $config;
  213. }
  214. elseif (!is_array($config))
  215. {
  216. $config = array();
  217. }
  218. $hash = $option . $view;
  219. if (!array_key_exists($hash, $instances))
  220. {
  221. $instances[$hash] = self::getTmpInstance($option, $view, $config);
  222. }
  223. return $instances[$hash];
  224. }
  225. /**
  226. * Gets a temporary instance of a controller object. A temporary instance is
  227. * not a Singleton and can be disposed off after use.
  228. *
  229. * @param string $option The component name, e.g. com_foobar
  230. * @param string $view The view name, e.g. cpanel
  231. * @param array $config Configuration parameters
  232. *
  233. * @return \FOFController A disposable class instance
  234. */
  235. public static function &getTmpInstance($option = null, $view = null, $config = array())
  236. {
  237. // Make sure $config is an array
  238. if (is_object($config))
  239. {
  240. $config = (array) $config;
  241. }
  242. elseif (!is_array($config))
  243. {
  244. $config = array();
  245. }
  246. // Get an input object
  247. if (array_key_exists('input', $config))
  248. {
  249. $input = $config['input'];
  250. }
  251. else
  252. {
  253. $input = null;
  254. }
  255. if (array_key_exists('input_options', $config))
  256. {
  257. $input_options = $config['input_options'];
  258. }
  259. else
  260. {
  261. $input_options = array();
  262. }
  263. if (!($input instanceof FOFInput))
  264. {
  265. $input = new FOFInput($input, $input_options);
  266. }
  267. // Determine the option (component name) and view
  268. $config['option'] = !is_null($option) ? $option : $input->getCmd('option', 'com_foobar');
  269. $config['view'] = !is_null($view) ? $view : $input->getCmd('view', 'cpanel');
  270. // Get the class base name, e.g. FoobarController
  271. $classBaseName = ucfirst(str_replace('com_', '', $config['option'])) . 'Controller';
  272. // Get the class name suffixes, in the order to be searched for: plural, singular, 'default'
  273. $classSuffixes = array(
  274. FOFInflector::pluralize($config['view']),
  275. FOFInflector::singularize($config['view']),
  276. 'default'
  277. );
  278. // Get the path names for the component
  279. $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($config['option']);
  280. $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
  281. // Look for the best classname match
  282. foreach ($classSuffixes as $suffix)
  283. {
  284. $className = $classBaseName . ucfirst($suffix);
  285. if (class_exists($className))
  286. {
  287. // The class is already loaded. We have a match!
  288. break;
  289. }
  290. // The class is not already loaded. Try to find and load it.
  291. $searchPaths = array(
  292. $componentPaths['main'] . '/controllers',
  293. $componentPaths['admin'] . '/controllers'
  294. );
  295. // If we have a searchpath in the configuration please search it first
  296. if (array_key_exists('searchpath', $config))
  297. {
  298. array_unshift($searchPaths, $config['searchpath']);
  299. }
  300. else
  301. {
  302. $configProvider = new FOFConfigProvider;
  303. $searchPath = $configProvider->get($config['option'] . '.views.' . FOFInflector::singularize($config['view']) . '.config.searchpath', null);
  304. if ($searchPath)
  305. {
  306. array_unshift($searchPaths, $componentPaths['admin'] . '/' . $searchPath);
  307. array_unshift($searchPaths, $componentPaths['main'] . '/' . $searchPath);
  308. }
  309. }
  310. /**
  311. * Try to find the path to this file. First try to find the
  312. * format-specific controller file, e.g. foobar.json.php for
  313. * format=json, then the regular one-size-fits-all controller
  314. */
  315. $format = $input->getCmd('format', 'html');
  316. $path = null;
  317. if (!empty($format))
  318. {
  319. $path = $filesystem->pathFind(
  320. $searchPaths, strtolower($suffix) . '.' . strtolower($format) . '.php'
  321. );
  322. }
  323. if (!$path)
  324. {
  325. $path = $filesystem->pathFind(
  326. $searchPaths, strtolower($suffix) . '.php'
  327. );
  328. }
  329. // The path is found. Load the file and make sure the expected class name exists.
  330. if ($path)
  331. {
  332. require_once $path;
  333. if (class_exists($className))
  334. {
  335. // The class was loaded successfully. We have a match!
  336. break;
  337. }
  338. }
  339. }
  340. if (!class_exists($className))
  341. {
  342. // If no specialised class is found, instantiate the generic FOFController
  343. $className = 'FOFController';
  344. }
  345. $instance = new $className($config);
  346. return $instance;
  347. }
  348. /**
  349. * Public constructor of the Controller class
  350. *
  351. * @param array $config Optional configuration parameters
  352. */
  353. public function __construct($config = array())
  354. {
  355. // Make sure $config is an array
  356. if (is_object($config))
  357. {
  358. $config = (array) $config;
  359. }
  360. elseif (!is_array($config))
  361. {
  362. $config = array();
  363. }
  364. $this->methods = array();
  365. $this->message = null;
  366. $this->messageType = 'message';
  367. $this->paths = array();
  368. $this->redirect = null;
  369. $this->taskMap = array();
  370. // Cache the config
  371. $this->config = $config;
  372. // Get the input for this MVC triad
  373. if (array_key_exists('input', $config))
  374. {
  375. $input = $config['input'];
  376. }
  377. else
  378. {
  379. $input = null;
  380. }
  381. if (array_key_exists('input_options', $config))
  382. {
  383. $input_options = $config['input_options'];
  384. }
  385. else
  386. {
  387. $input_options = array();
  388. }
  389. if ($input instanceof FOFInput)
  390. {
  391. $this->input = $input;
  392. }
  393. else
  394. {
  395. $this->input = new FOFInput($input, $input_options);
  396. }
  397. // Load the configuration provider
  398. $this->configProvider = new FOFConfigProvider;
  399. // Determine the methods to exclude from the base class.
  400. $xMethods = get_class_methods('FOFController');
  401. // Some methods must always be considered valid tasks
  402. $iMethods = array('accesspublic', 'accessregistered', 'accessspecial',
  403. 'add', 'apply', 'browse', 'cancel', 'copy', 'edit', 'orderdown',
  404. 'orderup', 'publish', 'read', 'remove', 'save', 'savenew',
  405. 'saveorder', 'unpublish', 'display', 'archive', 'trash');
  406. // Get the public methods in this class using reflection.
  407. $r = new ReflectionClass($this);
  408. $rMethods = $r->getMethods(ReflectionMethod::IS_PUBLIC);
  409. foreach ($rMethods as $rMethod)
  410. {
  411. $mName = $rMethod->getName();
  412. // Add default display method if not explicitly declared.
  413. if (!in_array($mName, $xMethods) || in_array($mName, $iMethods))
  414. {
  415. $this->methods[] = strtolower($mName);
  416. // Auto register the methods as tasks.
  417. $this->taskMap[strtolower($mName)] = $mName;
  418. }
  419. }
  420. // Get the default values for the component and view names
  421. $classNameParts = FOFInflector::explode(get_class($this));
  422. if (count($classNameParts) == 3)
  423. {
  424. $defComponent = "com_" . $classNameParts[0];
  425. $defView = $classNameParts[2];
  426. }
  427. else
  428. {
  429. $defComponent = 'com_foobar';
  430. $defView = 'cpanel';
  431. }
  432. $this->component = $this->input->get('option', $defComponent, 'cmd');
  433. $this->view = $this->input->get('view', $defView, 'cmd');
  434. $this->layout = $this->input->get('layout', null, 'cmd');
  435. // Overrides from the config
  436. if (array_key_exists('option', $config))
  437. {
  438. $this->component = $config['option'];
  439. }
  440. if (array_key_exists('view', $config))
  441. {
  442. $this->view = $config['view'];
  443. }
  444. if (array_key_exists('layout', $config))
  445. {
  446. $this->layout = $config['layout'];
  447. }
  448. $this->layout = $this->configProvider->get($this->component . '.views.' . FOFInflector::singularize($this->view) . '.config.layout', $this->layout);
  449. $this->input->set('option', $this->component);
  450. // Set the bareComponent variable
  451. $this->bareComponent = str_replace('com_', '', strtolower($this->component));
  452. // Set the $name variable
  453. $this->name = $this->bareComponent;
  454. // Set the basePath variable
  455. $componentPaths = FOFPlatform::getInstance()->getComponentBaseDirs($this->component);
  456. $basePath = $componentPaths['main'];
  457. if (array_key_exists('base_path', $config))
  458. {
  459. $basePath = $config['base_path'];
  460. }
  461. $altBasePath = $this->configProvider->get(
  462. $this->component . '.views.' .
  463. FOFInflector::singularize($this->view) . '.config.base_path', null
  464. );
  465. if (!is_null($altBasePath))
  466. {
  467. $platformDirs = FOFPlatform::getInstance()->getPlatformBaseDirs();
  468. $basePath = $platformDirs['public'] . '/' . $altBasePath;
  469. }
  470. $this->basePath = $basePath;
  471. // If the default task is set, register it as such
  472. $defaultTask = $this->configProvider->get(
  473. $this->component . '.views.' .
  474. FOFInflector::singularize($this->view) . '.config.default_task', 'display'
  475. );
  476. if (array_key_exists('default_task', $config))
  477. {
  478. $this->registerDefaultTask($config['default_task']);
  479. }
  480. else
  481. {
  482. $this->registerDefaultTask($defaultTask);
  483. }
  484. // Set the models prefix
  485. if (empty($this->model_prefix))
  486. {
  487. if (array_key_exists('model_prefix', $config))
  488. {
  489. // User-defined prefix
  490. $this->model_prefix = $config['model_prefix'];
  491. }
  492. else
  493. {
  494. $this->model_prefix = $this->name . 'Model';
  495. $this->model_prefix = $this->configProvider->get(
  496. $this->component . '.views.' .
  497. FOFInflector::singularize($this->view) . '.config.model_prefix', $this->model_prefix
  498. );
  499. }
  500. }
  501. // Set the default model search path
  502. if (array_key_exists('model_path', $config))
  503. {
  504. // User-defined dirs
  505. $this->addModelPath($config['model_path'], $this->model_prefix);
  506. }
  507. else
  508. {
  509. $modelPath = $this->basePath . '/models';
  510. $altModelPath = $this->configProvider->get(
  511. $this->component . '.views.' .
  512. FOFInflector::singularize($this->view) . '.config.model_path', null
  513. );
  514. if (!is_null($altModelPath))
  515. {
  516. $modelPath = $this->basePath . '/' . $altModelPath;
  517. }
  518. $this->addModelPath($modelPath, $this->model_prefix);
  519. }
  520. // Set the default view search path
  521. if (array_key_exists('view_path', $config))
  522. {
  523. // User-defined dirs
  524. $this->setPath('view', $config['view_path']);
  525. }
  526. else
  527. {
  528. $viewPath = $this->basePath . '/views';
  529. $altViewPath = $this->configProvider->get(
  530. $this->component . '.views.' .
  531. FOFInflector::singularize($this->view) . '.config.view_path', null
  532. );
  533. if (!is_null($altViewPath))
  534. {
  535. $viewPath = $this->basePath . '/' . $altViewPath;
  536. }
  537. $this->setPath('view', $viewPath);
  538. }
  539. // Set the default view.
  540. if (array_key_exists('default_view', $config))
  541. {
  542. $this->default_view = $config['default_view'];
  543. }
  544. else
  545. {
  546. if (empty($this->default_view))
  547. {
  548. $this->default_view = $this->getName();
  549. }
  550. $this->default_view = $this->configProvider->get(
  551. $this->component . '.views.' .
  552. FOFInflector::singularize($this->view) . '.config.default_view', $this->default_view
  553. );
  554. }
  555. // Set the CSRF protection
  556. if (array_key_exists('csrf_protection', $config))
  557. {
  558. $this->csrfProtection = $config['csrf_protection'];
  559. }
  560. $this->csrfProtection = $this->configProvider->get(
  561. $this->component . '.views.' .
  562. FOFInflector::singularize($this->view) . '.config.csrf_protection', $this->csrfProtection
  563. );
  564. // Set any model/view name overrides
  565. if (array_key_exists('viewName', $config))
  566. {
  567. $this->setThisViewName($config['viewName']);
  568. }
  569. else
  570. {
  571. $overrideViewName = $this->configProvider->get(
  572. $this->component . '.views.' .
  573. FOFInflector::singularize($this->view) . '.config.viewName', null
  574. );
  575. if ($overrideViewName)
  576. {
  577. $this->setThisViewName($overrideViewName);
  578. }
  579. }
  580. if (array_key_exists('modelName', $config))
  581. {
  582. $this->setThisModelName($config['modelName']);
  583. }
  584. else
  585. {
  586. $overrideModelName = $this->configProvider->get(
  587. $this->component . '.views.' .
  588. FOFInflector::singularize($this->view) . '.config.modelName', null
  589. );
  590. if ($overrideModelName)
  591. {
  592. $this->setThisModelName($overrideModelName);
  593. }
  594. }
  595. // Caching
  596. if (array_key_exists('cacheableTasks', $config))
  597. {
  598. if (is_array($config['cacheableTasks']))
  599. {
  600. $this->cacheableTasks = $config['cacheableTasks'];
  601. }
  602. }
  603. else
  604. {
  605. $cacheableTasks = $this->configProvider->get(
  606. $this->component . '.views.' .
  607. FOFInflector::singularize($this->view) . '.config.cacheableTasks', null
  608. );
  609. if ($cacheableTasks)
  610. {
  611. $cacheableTasks = explode(',', $cacheableTasks);
  612. if (count($cacheableTasks))
  613. {
  614. $temp = array();
  615. foreach ($cacheableTasks as $t)
  616. {
  617. $temp[] = trim($t);
  618. }
  619. $temp = array_unique($temp);
  620. $this->cacheableTasks = $temp;
  621. }
  622. }
  623. }
  624. // Bit mask for auto routing on setRedirect
  625. $this->autoRouting = $this->configProvider->get(
  626. $this->component . '.views.' .
  627. FOFInflector::singularize($this->view) . '.config.autoRouting', $this->autoRouting
  628. );
  629. if (array_key_exists('autoRouting', $config))
  630. {
  631. $this->autoRouting = $config['autoRouting'];
  632. }
  633. // Apply task map
  634. $taskmap = $this->configProvider->get(
  635. $this->component . '.views.' .
  636. FOFInflector::singularize($this->view) . '.taskmap'
  637. );
  638. if (is_array($taskmap) && !empty($taskmap))
  639. {
  640. foreach ($taskmap as $aliasedtask => $realmethod)
  641. {
  642. $this->registerTask($aliasedtask, $realmethod);
  643. }
  644. }
  645. }
  646. /**
  647. * Adds to the stack of model paths in LIFO order.
  648. *
  649. * @param mixed $path The directory (string) , or list of directories (array) to add.
  650. * @param string $prefix A prefix for models
  651. *
  652. * @return void
  653. */
  654. public static function addModelPath($path, $prefix = '')
  655. {
  656. FOFModel::addIncludePath($path, $prefix);
  657. }
  658. /**
  659. * Adds to the search path for templates and resources.
  660. *
  661. * @param string $type The path type (e.g. 'model', 'view').
  662. * @param mixed $path The directory string or stream array to search.
  663. *
  664. * @return FOFController A FOFController object to support chaining.
  665. */
  666. protected function addPath($type, $path)
  667. {
  668. // Just force path to array
  669. settype($path, 'array');
  670. $filesystem = FOFPlatform::getInstance()->getIntegrationObject('filesystem');
  671. if (!isset($this->paths[$type]))
  672. {
  673. $this->paths[$type] = array();
  674. }
  675. // Loop through the path directories
  676. foreach ($path as $dir)
  677. {
  678. // No surrounding spaces allowed!
  679. $dir = rtrim($filesystem->pathCheck($dir, '/'), '/') . '/';
  680. // Add to the top of the search dirs
  681. array_unshift($this->paths[$type], $dir);
  682. }
  683. return $this;
  684. }
  685. /**
  686. * Add one or more view paths to the controller's stack, in LIFO order.
  687. *
  688. * @param mixed $path The directory (string) or list of directories (array) to add.
  689. *
  690. * @return FOFController This object to support chaining.
  691. */
  692. public function addViewPath($path)
  693. {
  694. $this->addPath('view', $path);
  695. return $this;
  696. }
  697. /**
  698. * Authorisation check
  699. *
  700. * @param string $task The ACO Section Value to check access on.
  701. *
  702. * @return boolean True if authorised
  703. *
  704. * @deprecated 2.0 Use JAccess instead.
  705. */
  706. public function authorise($task)
  707. {
  708. FOFPlatform::getInstance()->logDeprecated(__CLASS__ . '::' .__METHOD__ . ' is deprecated. Use checkACL() instead.');
  709. return true;
  710. }
  711. /**
  712. * Create the filename for a resource.
  713. *
  714. * @param string $type The resource type to create the filename for.
  715. * @param array $parts An associative array of filename information. Optional.
  716. *
  717. * @return string The filename.
  718. */
  719. protected static function createFileName($type, $parts = array())
  720. {
  721. $filename = '';
  722. switch ($type)
  723. {
  724. case 'controller':
  725. if (!empty($parts['format']))
  726. {
  727. if ($parts['format'] == 'html')
  728. {
  729. $parts['format'] = '';
  730. }
  731. else
  732. {
  733. $parts['format'] = '.' . $parts['format'];
  734. }
  735. }
  736. else
  737. {
  738. $parts['format'] = '';
  739. }
  740. $filename = strtolower($parts['name'] . $parts['format'] . '.php');
  741. break;
  742. case 'view':
  743. if (!empty($parts['type']))
  744. {
  745. $parts['type'] = '.' . $parts['type'];
  746. }
  747. else
  748. {
  749. $parts['type'] = '';
  750. }
  751. $filename = strtolower($parts['name'] . '/view' . $parts['type'] . '.php');
  752. break;
  753. }
  754. return $filename;
  755. }
  756. /**
  757. * Executes a given controller task. The onBefore<task> and onAfter<task>
  758. * methods are called automatically if they exist.
  759. *
  760. * @param string $task The task to execute, e.g. "browse"
  761. *
  762. * @throws Exception Exception thrown if the onBefore<task> returns false
  763. *
  764. * @return null|bool False on execution failure
  765. */
  766. public function execute($task)
  767. {
  768. $this->task = $task;
  769. $method_name = 'onBefore' . ucfirst($task);
  770. if (!method_exists($this, $method_name))
  771. {
  772. $result = $this->onBeforeGenericTask($task);
  773. }
  774. elseif (method_exists($this, $method_name))
  775. {
  776. $result = $this->$method_name();
  777. }
  778. else
  779. {
  780. $result = true;
  781. }
  782. if ($result)
  783. {
  784. $plugin_event = FOFInflector::camelize('on before ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task);
  785. $plugin_result = FOFPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input));
  786. if (in_array(false, $plugin_result, true))
  787. {
  788. $result = false;
  789. }
  790. }
  791. if (!$result)
  792. {
  793. throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
  794. }
  795. // Do not allow the display task to be directly called
  796. $task = strtolower($task);
  797. if (isset($this->taskMap[$task]))
  798. {
  799. $doTask = $this->taskMap[$task];
  800. }
  801. elseif (isset($this->taskMap['__default']))
  802. {
  803. $doTask = $this->taskMap['__default'];
  804. }
  805. else
  806. {
  807. $doTask = null;
  808. }
  809. if ($doTask == 'display')
  810. {
  811. FOFPlatform::getInstance()->setHeader('Status', '400 Bad Request', true);
  812. throw new Exception('Bad Request', 400);
  813. }
  814. $this->doTask = $doTask;
  815. $ret = $this->$doTask();
  816. $method_name = 'onAfter' . ucfirst($task);
  817. if (method_exists($this, $method_name))
  818. {
  819. $result = $this->$method_name();
  820. }
  821. else
  822. {
  823. $result = true;
  824. }
  825. if ($result)
  826. {
  827. $plugin_event = FOFInflector::camelize('on after ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task);
  828. $plugin_result = FOFPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input, &$ret));
  829. if (in_array(false, $plugin_result, true))
  830. {
  831. $result = false;
  832. }
  833. }
  834. if (!$result)
  835. {
  836. throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403);
  837. }
  838. return $ret;
  839. }
  840. /**
  841. * Default task. Assigns a model to the view and asks the view to render
  842. * itself.
  843. *
  844. * YOU MUST NOT USETHIS TASK DIRECTLY IN A URL. It is supposed to be
  845. * used ONLY inside your code. In the URL, use task=browse instead.
  846. *
  847. * @param bool $cachable Is this view cacheable?
  848. * @param bool $urlparams Add your safe URL parameters (see further down in the code)
  849. *
  850. * @return bool
  851. */
  852. public function display($cachable = false, $urlparams = false)
  853. {
  854. $document = FOFPlatform::getInstance()->getDocument();
  855. if ($document instanceof JDocument)
  856. {
  857. $viewType = $document->getType();
  858. }
  859. else
  860. {
  861. $viewType = $this->input->getCmd('format', 'html');
  862. }
  863. $view = $this->getThisView();
  864. // Get/Create the model
  865. if ($model = $this->getThisModel())
  866. {
  867. // Push the model into the view (as default)
  868. $view->setModel($model, true);
  869. }
  870. // Set the layout
  871. $view->setLayout(is_null($this->layout) ? 'default' : $this->layout);
  872. // Display the view
  873. $conf = FOFPlatform::getInstance()->getConfig();
  874. if (FOFPlatform::getInstance()->isFrontend() && $cachable && ($viewType != 'feed') && $conf->get('caching') >= 1)
  875. {
  876. // Get a JCache object
  877. $option = $this->input->get('option', 'com_foobar', 'cmd');
  878. $cache = JFactory::getCache($option, 'view');
  879. // Set up a cache ID based on component, view, task and user group assignment
  880. $user = FOFPlatform::getInstance()->getUser();
  881. if ($user->guest)
  882. {
  883. $groups = array();
  884. }
  885. else
  886. {
  887. $groups = $user->groups;
  888. }
  889. // Set up safe URL parameters
  890. if (!is_array($urlparams))
  891. {
  892. $urlparams = array(
  893. 'option' => 'CMD',
  894. 'view' => 'CMD',
  895. 'task' => 'CMD',
  896. 'format' => 'CMD',
  897. 'layout' => 'CMD',
  898. 'id' => 'INT',
  899. );
  900. }
  901. if (is_array($urlparams))
  902. {
  903. $app = JFactory::getApplication();
  904. $registeredurlparams = null;
  905. if (version_compare(JVERSION, '3.0', 'ge'))
  906. {
  907. if (property_exists($app, 'registeredurlparams'))
  908. {
  909. $registeredurlparams = $app->registeredurlparams;
  910. }
  911. }
  912. else
  913. {
  914. $registeredurlparams = $app->get('registeredurlparams');
  915. }
  916. if (empty($registeredurlparams))
  917. {
  918. $registeredurlparams = new stdClass;
  919. }
  920. foreach ($urlparams AS $key => $value)
  921. {
  922. // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}.
  923. $registeredurlparams->$key = $value;
  924. }
  925. if (version_compare(JVERSION, '3.0', 'ge'))
  926. {
  927. $app->registeredurlparams = $registeredurlparams;
  928. }
  929. else
  930. {
  931. $app->set('registeredurlparams', $registeredurlparams);
  932. }
  933. }
  934. // Create the cache ID after setting the registered URL params, as they are used to generate the ID
  935. $cacheId = md5(serialize(array(JCache::makeId(), $view->getName(), $this->doTask, $groups)));
  936. // Get the cached view or cache the current view
  937. $cache->get($view, 'display', $cacheId);
  938. }
  939. else
  940. {
  941. // Display without caching
  942. $view->display();
  943. }
  944. return true;
  945. }
  946. /**
  947. * Implements a default browse task, i.e. read a bunch of records and send
  948. * them to the browser.
  949. *
  950. * @return boolean
  951. */
  952. public function browse()
  953. {
  954. if ($this->input->get('savestate', -999, 'int') == -999)
  955. {
  956. $this->input->set('savestate', true);
  957. }
  958. // Do I have a form?
  959. $model = $this->getThisModel();
  960. if (empty($this->layout))
  961. {
  962. $formname = 'form.default';
  963. }
  964. else
  965. {
  966. $formname = 'form.' . $this->layout;
  967. }
  968. $model->setState('form_name', $formname);
  969. $form = $model->getForm();
  970. if ($form !== false)
  971. {
  972. $this->hasForm = true;
  973. }
  974. $this->display(in_array('browse', $this->cacheableTasks));
  975. return true;
  976. }
  977. /**
  978. * Single record read. The id set in the request is passed to the model and
  979. * then the item layout is used to render the result.
  980. *
  981. * @return bool
  982. */
  983. public function read()
  984. {
  985. // Load the model
  986. $model = $this->getThisModel();
  987. if (!$model->getId())
  988. {
  989. $model->setIDsFromRequest();
  990. }
  991. // Set the layout to item, if it's not set in the URL
  992. if (is_null($this->layout))
  993. {
  994. $this->layout = 'item';
  995. }
  996. // Do I have a form?
  997. $model->setState('form_name', 'form.' . $this->layout);
  998. $item = $model->getItem();
  999. if (!($item instanceof FOFTable))
  1000. {
  1001. return false;
  1002. }
  1003. $itemKey = $item->getKeyName();
  1004. if ($item->$itemKey != $model->getId())
  1005. {
  1006. return false;
  1007. }
  1008. $formData = is_object($item) ? $item->getData() : array();
  1009. $form = $model->getForm($formData);
  1010. if ($form !== false)
  1011. {
  1012. $this->hasForm = true;
  1013. }
  1014. // Display
  1015. $this->display(in_array('read', $this->cacheableTasks));
  1016. return true;
  1017. }
  1018. /**
  1019. * Single record add. The form layout is used to present a blank page.
  1020. *
  1021. * @return false|void
  1022. */
  1023. public function add()
  1024. {
  1025. // Load and reset the model
  1026. $model = $this->getThisModel();
  1027. $model->reset();
  1028. // Set the layout to form, if it's not set in the URL
  1029. if (is_null($this->layout))
  1030. {
  1031. $this->layout = 'form';
  1032. }
  1033. // Do I have a form?
  1034. $model->setState('form_name', 'form.' . $this->layout);
  1035. $item = $model->getItem();
  1036. if (!($item instanceof FOFTable))
  1037. {
  1038. return false;
  1039. }
  1040. $formData = is_object($item) ? $item->getData() : array();
  1041. $form = $model->getForm($formData);
  1042. if ($form !== false)
  1043. {
  1044. $this->hasForm = true;
  1045. }
  1046. // Display
  1047. $this->display(in_array('add', $this->cacheableTasks));
  1048. }
  1049. /**
  1050. * Single record edit. The ID set in the request is passed to the model,
  1051. * then the form layout is used to edit the result.
  1052. *
  1053. * @return bool
  1054. */
  1055. public function edit()
  1056. {
  1057. // Load the model
  1058. $model = $this->getThisModel();
  1059. if (!$model->getId())
  1060. {
  1061. $model->setIDsFromRequest();
  1062. }
  1063. $status = $model->checkout();
  1064. if (!$status)
  1065. {
  1066. // Redirect on error
  1067. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1068. {
  1069. $customURL = base64_decode($customURL);
  1070. }
  1071. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1072. $this->setRedirect($url, $model->getError(), 'error');
  1073. return false;
  1074. }
  1075. // Set the layout to form, if it's not set in the URL
  1076. if (is_null($this->layout))
  1077. {
  1078. $this->layout = 'form';
  1079. }
  1080. // Do I have a form?
  1081. $model->setState('form_name', 'form.' . $this->layout);
  1082. $item = $model->getItem();
  1083. if (!($item instanceof FOFTable))
  1084. {
  1085. return false;
  1086. }
  1087. $itemKey = $item->getKeyName();
  1088. if ($item->$itemKey != $model->getId())
  1089. {
  1090. return false;
  1091. }
  1092. $formData = is_object($item) ? $item->getData() : array();
  1093. $form = $model->getForm($formData);
  1094. if ($form !== false)
  1095. {
  1096. $this->hasForm = true;
  1097. }
  1098. // Display
  1099. $this->display(in_array('edit', $this->cacheableTasks));
  1100. return true;
  1101. }
  1102. /**
  1103. * Save the incoming data and then return to the Edit task
  1104. *
  1105. * @return bool
  1106. */
  1107. public function apply()
  1108. {
  1109. // CSRF prevention
  1110. if ($this->csrfProtection)
  1111. {
  1112. $this->_csrfProtection();
  1113. }
  1114. $model = $this->getThisModel();
  1115. $result = $this->applySave();
  1116. // Redirect to the edit task
  1117. if ($result)
  1118. {
  1119. $id = $this->input->get('id', 0, 'int');
  1120. $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
  1121. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1122. {
  1123. $customURL = base64_decode($customURL);
  1124. }
  1125. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix();
  1126. $this->setRedirect($url, JText::_($textkey));
  1127. }
  1128. return $result;
  1129. }
  1130. /**
  1131. * Duplicates selected items
  1132. *
  1133. * @return bool
  1134. */
  1135. public function copy()
  1136. {
  1137. // CSRF prevention
  1138. if ($this->csrfProtection)
  1139. {
  1140. $this->_csrfProtection();
  1141. }
  1142. $model = $this->getThisModel();
  1143. if (!$model->getId())
  1144. {
  1145. $model->setIDsFromRequest();
  1146. }
  1147. $status = $model->copy();
  1148. // Redirect
  1149. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1150. {
  1151. $customURL = base64_decode($customURL);
  1152. }
  1153. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1154. if (!$status)
  1155. {
  1156. $this->setRedirect($url, $model->getError(), 'error');
  1157. return false;
  1158. }
  1159. else
  1160. {
  1161. FOFPlatform::getInstance()->setHeader('Status', '201 Created', true);
  1162. $this->setRedirect($url);
  1163. return true;
  1164. }
  1165. }
  1166. /**
  1167. * Save the incoming data and then return to the Browse task
  1168. *
  1169. * @return bool
  1170. */
  1171. public function save()
  1172. {
  1173. // CSRF prevention
  1174. if ($this->csrfProtection)
  1175. {
  1176. $this->_csrfProtection();
  1177. }
  1178. $result = $this->applySave();
  1179. // Redirect to the display task
  1180. if ($result)
  1181. {
  1182. $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
  1183. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1184. {
  1185. $customURL = base64_decode($customURL);
  1186. }
  1187. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1188. $this->setRedirect($url, JText::_($textkey));
  1189. }
  1190. return $result;
  1191. }
  1192. /**
  1193. * Save the incoming data and then return to the Add task
  1194. *
  1195. * @return bool
  1196. */
  1197. public function savenew()
  1198. {
  1199. // CSRF prevention
  1200. if ($this->csrfProtection)
  1201. {
  1202. $this->_csrfProtection();
  1203. }
  1204. $result = $this->applySave();
  1205. // Redirect to the display task
  1206. if ($result)
  1207. {
  1208. $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED';
  1209. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1210. {
  1211. $customURL = base64_decode($customURL);
  1212. }
  1213. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix();
  1214. $this->setRedirect($url, JText::_($textkey));
  1215. }
  1216. return $result;
  1217. }
  1218. /**
  1219. * Cancel the edit, check in the record and return to the Browse task
  1220. *
  1221. * @return bool
  1222. */
  1223. public function cancel()
  1224. {
  1225. $model = $this->getThisModel();
  1226. if (!$model->getId())
  1227. {
  1228. $model->setIDsFromRequest();
  1229. }
  1230. $model->checkin();
  1231. // Remove any saved data
  1232. JFactory::getSession()->set($model->getHash() . 'savedata', null);
  1233. // Redirect to the display task
  1234. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1235. {
  1236. $customURL = base64_decode($customURL);
  1237. }
  1238. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1239. $this->setRedirect($url);
  1240. return true;
  1241. }
  1242. /**
  1243. * Sets the access to public. Joomla! 1.5 compatibility.
  1244. *
  1245. * @return bool
  1246. *
  1247. * @deprecated since 2.0
  1248. */
  1249. public function accesspublic()
  1250. {
  1251. // CSRF prevention
  1252. if ($this->csrfProtection)
  1253. {
  1254. $this->_csrfProtection();
  1255. }
  1256. return $this->setaccess(0);
  1257. }
  1258. /**
  1259. * Sets the access to registered. Joomla! 1.5 compatibility.
  1260. *
  1261. * @return bool
  1262. *
  1263. * @deprecated since 2.0
  1264. */
  1265. public function accessregistered()
  1266. {
  1267. // CSRF prevention
  1268. if ($this->csrfProtection)
  1269. {
  1270. $this->_csrfProtection();
  1271. }
  1272. return $this->setaccess(1);
  1273. }
  1274. /**
  1275. * Sets the access to special. Joomla! 1.5 compatibility.
  1276. *
  1277. * @return bool
  1278. *
  1279. * @deprecated since 2.0
  1280. */
  1281. public function accessspecial()
  1282. {
  1283. // CSRF prevention
  1284. if ($this->csrfProtection)
  1285. {
  1286. $this->_csrfProtection();
  1287. }
  1288. return $this->setaccess(2);
  1289. }
  1290. /**
  1291. * Publish (set enabled = 1) an item.
  1292. *
  1293. * @return bool
  1294. */
  1295. public function publish()
  1296. {
  1297. // CSRF prevention
  1298. if ($this->csrfProtection)
  1299. {
  1300. $this->_csrfProtection();
  1301. }
  1302. return $this->setstate(1);
  1303. }
  1304. /**
  1305. * Unpublish (set enabled = 0) an item.
  1306. *
  1307. * @return bool
  1308. */
  1309. public function unpublish()
  1310. {
  1311. // CSRF prevention
  1312. if ($this->csrfProtection)
  1313. {
  1314. $this->_csrfProtection();
  1315. }
  1316. return $this->setstate(0);
  1317. }
  1318. /**
  1319. * Archive (set enabled = 2) an item.
  1320. *
  1321. * @return bool
  1322. */
  1323. public function archive()
  1324. {
  1325. // CSRF prevention
  1326. if ($this->csrfProtection)
  1327. {
  1328. $this->_csrfProtection();
  1329. }
  1330. return $this->setstate(2);
  1331. }
  1332. /**
  1333. * Trash (set enabled = -2) an item.
  1334. *
  1335. * @return bool
  1336. */
  1337. public function trash()
  1338. {
  1339. // CSRF prevention
  1340. if ($this->csrfProtection)
  1341. {
  1342. $this->_csrfProtection();
  1343. }
  1344. return $this->setstate(-2);
  1345. }
  1346. /**
  1347. * Saves the order of the items
  1348. *
  1349. * @return bool
  1350. */
  1351. public function saveorder()
  1352. {
  1353. // CSRF prevention
  1354. if ($this->csrfProtection)
  1355. {
  1356. $this->_csrfProtection();
  1357. }
  1358. $model = $this->getThisModel();
  1359. if (!$model->getId())
  1360. {
  1361. $model->setIDsFromRequest();
  1362. }
  1363. $ordering = $model->getTable()->getColumnAlias('ordering');
  1364. $ids = $model->getIds();
  1365. $orders = $this->input->get('order', array(), 'array');
  1366. if ($n = count($ids))
  1367. {
  1368. for ($i = 0; $i < $n; $i++)
  1369. {
  1370. $model->setId($ids[$i]);
  1371. $neworder = (int) $orders[$i];
  1372. $item = $model->getItem();
  1373. if (!($item instanceof FOFTable))
  1374. {
  1375. return false;
  1376. }
  1377. $key = $item->getKeyName();
  1378. if ($item->$key == $ids[$i])
  1379. {
  1380. $item->$ordering = $neworder;
  1381. $model->save($item);
  1382. }
  1383. }
  1384. }
  1385. $status = $model->reorder();
  1386. // Redirect
  1387. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1388. {
  1389. $customURL = base64_decode($customURL);
  1390. }
  1391. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1392. $this->setRedirect($url);
  1393. return $status;
  1394. }
  1395. /**
  1396. * Moves selected items one position down the ordering list
  1397. *
  1398. * @return bool
  1399. */
  1400. public function orderdown()
  1401. {
  1402. // CSRF prevention
  1403. if ($this->csrfProtection)
  1404. {
  1405. $this->_csrfProtection();
  1406. }
  1407. $model = $this->getThisModel();
  1408. if (!$model->getId())
  1409. {
  1410. $model->setIDsFromRequest();
  1411. }
  1412. $status = $model->move(1);
  1413. // Redirect
  1414. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1415. {
  1416. $customURL = base64_decode($customURL);
  1417. }
  1418. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1419. if (!$status)
  1420. {
  1421. $this->setRedirect($url, $model->getError(), 'error');
  1422. }
  1423. else
  1424. {
  1425. $this->setRedirect($url);
  1426. }
  1427. return $status;
  1428. }
  1429. /**
  1430. * Moves selected items one position up the ordering list
  1431. *
  1432. * @return bool
  1433. */
  1434. public function orderup()
  1435. {
  1436. // CSRF prevention
  1437. if ($this->csrfProtection)
  1438. {
  1439. $this->_csrfProtection();
  1440. }
  1441. $model = $this->getThisModel();
  1442. if (!$model->getId())
  1443. {
  1444. $model->setIDsFromRequest();
  1445. }
  1446. $status = $model->move(-1);
  1447. // Redirect
  1448. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1449. {
  1450. $customURL = base64_decode($customURL);
  1451. }
  1452. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1453. if (!$status)
  1454. {
  1455. $this->setRedirect($url, $model->getError(), 'error');
  1456. }
  1457. else
  1458. {
  1459. $this->setRedirect($url);
  1460. }
  1461. return $status;
  1462. }
  1463. /**
  1464. * Delete selected item(s)
  1465. *
  1466. * @return bool
  1467. */
  1468. public function remove()
  1469. {
  1470. // CSRF prevention
  1471. if ($this->csrfProtection)
  1472. {
  1473. $this->_csrfProtection();
  1474. }
  1475. $model = $this->getThisModel();
  1476. if (!$model->getId())
  1477. {
  1478. $model->setIDsFromRequest();
  1479. }
  1480. $status = $model->delete();
  1481. // Redirect
  1482. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1483. {
  1484. $customURL = base64_decode($customURL);
  1485. }
  1486. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1487. if (!$status)
  1488. {
  1489. $this->setRedirect($url, $model->getError(), 'error');
  1490. }
  1491. else
  1492. {
  1493. $this->setRedirect($url);
  1494. }
  1495. return $status;
  1496. }
  1497. /**
  1498. * Redirects the browser or returns false if no redirect is set.
  1499. *
  1500. * @return boolean False if no redirect exists.
  1501. */
  1502. public function redirect()
  1503. {
  1504. if ($this->redirect)
  1505. {
  1506. $app = JFactory::getApplication();
  1507. $app->enqueueMessage($this->message, $this->messageType);
  1508. $app->redirect($this->redirect);
  1509. return true;
  1510. }
  1511. return false;
  1512. }
  1513. /**
  1514. * Returns true if there is a redirect set in the controller
  1515. *
  1516. * @return boolean
  1517. */
  1518. public function hasRedirect()
  1519. {
  1520. return !empty($this->redirect);
  1521. }
  1522. /**
  1523. * Register the default task to perform if a mapping is not found.
  1524. *
  1525. * @param string $method The name of the method in the derived class to perform if a named task is not found.
  1526. *
  1527. * @return FOFController A FOFController object to support chaining.
  1528. */
  1529. public function registerDefaultTask($method)
  1530. {
  1531. $this->registerTask('__default', $method);
  1532. return $this;
  1533. }
  1534. /**
  1535. * Register (map) a task to a method in the class.
  1536. *
  1537. * @param string $task The task.
  1538. * @param string $method The name of the method in the derived class to perform for this task.
  1539. *
  1540. * @return FOFController A FOFController object to support chaining.
  1541. */
  1542. public function registerTask($task, $method)
  1543. {
  1544. if (in_array(strtolower($method), $this->methods))
  1545. {
  1546. $this->taskMap[strtolower($task)] = $method;
  1547. }
  1548. return $this;
  1549. }
  1550. /**
  1551. * Unregister (unmap) a task in the class.
  1552. *
  1553. * @param string $task The task.
  1554. *
  1555. * @return FOFController This object to support chaining.
  1556. */
  1557. public function unregisterTask($task)
  1558. {
  1559. unset($this->taskMap[strtolower($task)]);
  1560. return $this;
  1561. }
  1562. /**
  1563. * Sets the internal message that is passed with a redirect
  1564. *
  1565. * @param string $text Message to display on redirect.
  1566. * @param string $type Message type. Optional, defaults to 'message'.
  1567. *
  1568. * @return string Previous message
  1569. */
  1570. public function setMessage($text, $type = 'message')
  1571. {
  1572. $previous = $this->message;
  1573. $this->message = $text;
  1574. $this->messageType = $type;
  1575. return $previous;
  1576. }
  1577. /**
  1578. * Sets an entire array of search paths for resources.
  1579. *
  1580. * @param string $type The type of path to set, typically 'view' or 'model'.
  1581. * @param string $path The new set of search paths. If null or false, resets to the current directory only.
  1582. *
  1583. * @return void
  1584. */
  1585. protected function setPath($type, $path)
  1586. {
  1587. // Clear out the prior search dirs
  1588. $this->paths[$type] = array();
  1589. // Actually add the user-specified directories
  1590. $this->addPath($type, $path);
  1591. }
  1592. /**
  1593. * Registers a redirection with an optional message. The redirection is
  1594. * carried out when you use the redirect method.
  1595. *
  1596. * @param string $url The URL to redirect to
  1597. * @param string $msg The message to be pushed to the application
  1598. * @param string $type The message type to be pushed to the application, e.g. 'error'
  1599. *
  1600. * @return FOFController This object to support chaining
  1601. */
  1602. public function setRedirect($url, $msg = null, $type = null)
  1603. {
  1604. // Do the logic only if we're parsing a raw url (index.php?foo=bar&etc=etc)
  1605. if (strpos($url, 'index.php') === 0)
  1606. {
  1607. $isAdmin = FOFPlatform::getInstance()->isBackend();
  1608. $auto = false;
  1609. if (($this->autoRouting == 2 || $this->autoRouting == 3) && $isAdmin)
  1610. {
  1611. $auto = true;
  1612. }
  1613. elseif (($this->autoRouting == 1 || $this->autoRouting == 3) && !$isAdmin)
  1614. {
  1615. $auto = true;
  1616. }
  1617. if ($auto)
  1618. {
  1619. $url = JRoute::_($url, false);
  1620. }
  1621. }
  1622. $this->redirect = $url;
  1623. if ($msg !== null)
  1624. {
  1625. // Controller may have set this directly
  1626. $this->message = $msg;
  1627. }
  1628. // Ensure the type is not overwritten by a previous call to setMessage.
  1629. if (empty($type))
  1630. {
  1631. if (empty($this->messageType))
  1632. {
  1633. $this->messageType = 'message';
  1634. }
  1635. }
  1636. // If the type is explicitly set, set it.
  1637. else
  1638. {
  1639. $this->messageType = $type;
  1640. }
  1641. return $this;
  1642. }
  1643. /**
  1644. * Sets the published state (the enabled field) of the selected item(s)
  1645. *
  1646. * @param integer $state The desired state. 0 is unpublished, 1 is published.
  1647. *
  1648. * @return bool
  1649. */
  1650. final protected function setstate($state = 0)
  1651. {
  1652. $model = $this->getThisModel();
  1653. if (!$model->getId())
  1654. {
  1655. $model->setIDsFromRequest();
  1656. }
  1657. $status = $model->publish($state);
  1658. // Redirect
  1659. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1660. {
  1661. $customURL = base64_decode($customURL);
  1662. }
  1663. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1664. if (!$status)
  1665. {
  1666. $this->setRedirect($url, $model->getError(), 'error');
  1667. }
  1668. else
  1669. {
  1670. $this->setRedirect($url);
  1671. }
  1672. return $status;
  1673. }
  1674. /**
  1675. * Sets the access level of the selected item(s).
  1676. *
  1677. * @param integer $level The desired viewing access level ID
  1678. *
  1679. * @return bool
  1680. */
  1681. final protected function setaccess($level = 0)
  1682. {
  1683. $model = $this->getThisModel();
  1684. if (!$model->getId())
  1685. {
  1686. $model->setIDsFromRequest();
  1687. }
  1688. $id = $model->getId();
  1689. $item = $model->getItem();
  1690. if (!($item instanceof FOFTable))
  1691. {
  1692. return false;
  1693. }
  1694. $key = $item->getKeyName();
  1695. $loadedid = $item->$key;
  1696. if ($id == $loadedid)
  1697. {
  1698. $item->access = $level;
  1699. $status = $model->save($item);
  1700. }
  1701. else
  1702. {
  1703. $status = false;
  1704. }
  1705. // Redirect
  1706. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1707. {
  1708. $customURL = base64_decode($customURL);
  1709. }
  1710. $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . FOFInflector::pluralize($this->view) . $this->getItemidURLSuffix();
  1711. if (!$status)
  1712. {
  1713. $this->setRedirect($url, $model->getError(), 'error');
  1714. }
  1715. else
  1716. {
  1717. $this->setRedirect($url);
  1718. }
  1719. return $status;
  1720. }
  1721. /**
  1722. * Common method to handle apply and save tasks
  1723. *
  1724. * @return boolean Returns true on success
  1725. */
  1726. final protected function applySave()
  1727. {
  1728. // Load the model
  1729. $model = $this->getThisModel();
  1730. if (!$model->getId())
  1731. {
  1732. $model->setIDsFromRequest();
  1733. }
  1734. $id = $model->getId();
  1735. $data = $this->input->getData();
  1736. if (!$this->onBeforeApplySave($data))
  1737. {
  1738. return false;
  1739. }
  1740. // Set the layout to form, if it's not set in the URL
  1741. if (is_null($this->layout))
  1742. {
  1743. $this->layout = 'form';
  1744. }
  1745. // Do I have a form?
  1746. $model->setState('form_name', 'form.' . $this->layout);
  1747. $status = $model->save($data);
  1748. if ($status && ($id != 0))
  1749. {
  1750. FOFPlatform::getInstance()->setHeader('Status', '201 Created', true);
  1751. // Try to check-in the record if it's not a new one
  1752. $status = $model->checkin();
  1753. if ($status)
  1754. {
  1755. $status = $this->onAfterApplySave();
  1756. }
  1757. }
  1758. $this->input->set('id', $model->getId());
  1759. if (!$status)
  1760. {
  1761. // Redirect on error
  1762. $id = $model->getId();
  1763. if ($customURL = $this->input->get('returnurl', '', 'string'))
  1764. {
  1765. $customURL = base64_decode($customURL);
  1766. }
  1767. if (!empty($customURL))
  1768. {
  1769. $url = $customURL;
  1770. }
  1771. elseif ($id != 0)
  1772. {
  1773. $url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix();
  1774. }
  1775. else
  1776. {
  1777. $url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix();
  1778. }
  1779. $this->setRedirect($url, '<li>' . implode('</li><li>', $model->getErrors()) . '</li>', 'error');
  1780. return false;
  1781. }
  1782. else
  1783. {
  1784. $session = JFactory::getSession();
  1785. $session->set($model->getHash() . 'savedata', null);
  1786. return true;
  1787. }
  1788. }
  1789. /**
  1790. * Returns the default model associated with the current view
  1791. *
  1792. * @param array $config Configuration variables for the model
  1793. *
  1794. * @return FOFModel The global instance of the model (singleton)
  1795. */
  1796. final public function getThisModel($config = array())
  1797. {
  1798. if (!is_object($this->_modelObject))
  1799. {
  1800. // Make sure $config is an array
  1801. if (is_object($config))
  1802. {
  1803. $config = (array) $config;
  1804. }
  1805. elseif (!is_array($config))
  1806. {
  1807. $config = array();
  1808. }
  1809. if (!empty($this->modelName))
  1810. {
  1811. $parts = FOFInflector::explode($this->modelName);
  1812. $modelName = ucfirst(array_pop($parts));
  1813. $prefix = FOFInflector::implode($parts);
  1814. }
  1815. else
  1816. {
  1817. $prefix = ucfirst($this->bareComponent) . 'Model';
  1818. $modelName = ucfirst(FOFInflector::pluralize($this->view));
  1819. }
  1820. if (!array_key_exists('input', $config) || !($config['input'] instanceof FOFInput))
  1821. {
  1822. $config['input'] = $this->input;
  1823. }
  1824. $this->_modelObject = $this->getModel($modelName, $prefix, $config);
  1825. }
  1826. return $this->_modelObject;
  1827. }
  1828. /**
  1829. * Method to get a model object, loading it if required.
  1830. *
  1831. * @param string $name The model name. Optional.
  1832. * @param string $prefix The class prefix. Optional.
  1833. * @param array $config Configuration array for model. Optional.
  1834. *
  1835. * @return object The model.
  1836. */
  1837. public function getModel($name = '', $prefix = '', $config = array())
  1838. {
  1839. // Make sure $config is an array
  1840. if (is_object($config))
  1841. {
  1842. $config = (array) $config;
  1843. }
  1844. elseif (!is_array($config) || empty($config))
  1845. {
  1846. // array_merge is required to create a copy instead of assigning by reference
  1847. $config = array_merge($this->config);
  1848. }
  1849. if (empty($name))
  1850. {
  1851. $name = $this->getName();
  1852. }
  1853. if (empty($prefix))
  1854. {
  1855. $prefix = $this->model_prefix;
  1856. }
  1857. if ($model = $this->createModel($name, $prefix, $config))
  1858. {
  1859. // Task is a reserved state
  1860. $model->setState('task', $this->task);
  1861. // Let's get the application object and set menu information if it's available
  1862. if (!FOFPlatform::getInstance()->isCli())
  1863. {
  1864. $app = JFactory::getApplication();
  1865. $menu = $app->getMenu();
  1866. if (is_object($menu))
  1867. {
  1868. if ($item = $menu->getActive())
  1869. {
  1870. $params = $menu->getParams($item->id);
  1871. // Set default state data
  1872. $model->setState('parameters.menu', $params);
  1873. }
  1874. }
  1875. }
  1876. }
  1877. return $model;
  1878. }
  1879. /**
  1880. * Returns current view object
  1881. *
  1882. * @param array $config Configuration variables for the model
  1883. *
  1884. * @return FOFView The global instance of the view object (singleton)
  1885. */
  1886. final public function getThisView($config = array())
  1887. {
  1888. if (!is_object($this->_viewObject))
  1889. {
  1890. // Make sure $config is an array
  1891. if (is_object($config))
  1892. {
  1893. $config = (array) $config;
  1894. }
  1895. elseif (!is_array($config) || empty($config))
  1896. {
  1897. // array_merge is required to create a copy instead of assigning by reference
  1898. $config = array_merge($this->config);
  1899. }
  1900. $prefix = null;
  1901. $viewName = null;
  1902. $viewType = null;
  1903. if (!empty($this->viewName))
  1904. {
  1905. $parts = FOFInflector::explode($this->viewName);
  1906. $viewName = ucfirst(array_pop($parts));
  1907. $prefix = FOFInflector::implode($parts);
  1908. }
  1909. else
  1910. {
  1911. $prefix = ucfirst($this->bareComponent) . 'View';
  1912. $viewName = ucfirst($this->view);
  1913. }
  1914. $document = FOFPlatform::getInstance()->getDocument();
  1915. if ($document instanceof JDocument)
  1916. {
  1917. $viewType = $document->getType();
  1918. }
  1919. else
  1920. {
  1921. $viewType = $this->input->getCmd('format', 'html');
  1922. }
  1923. if (($viewType == 'html') && $this->hasForm)
  1924. {
  1925. $viewType = 'form';
  1926. }
  1927. if (!array_key_exists('input', $config) || !($confi

Large files files are truncated, but you can click here to view the full file