Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
legacy.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Legacy
4  * @subpackage Controller
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 /**
13  * Base class for a Joomla Controller
14  *
15  * Controller (Controllers are where you put all the actual code.) Provides basic
16  * functionality, such as rendering views (aka displaying templates).
17  *
18  * @package Joomla.Legacy
19  * @subpackage Controller
20  * @since 12.2
21  */
23 {
24  /**
25  * The base path of the controller
26  *
27  * @var string
28  * @since 12.2
29  * @note Replaces _basePath.
30  */
31  protected $basePath;
32 
33  /**
34  * The default view for the display method.
35  *
36  * @var string
37  * @since 12.2
38  */
39  protected $default_view;
40 
41  /**
42  * The mapped task that was performed.
43  *
44  * @var string
45  * @since 12.2
46  * @note Replaces _doTask.
47  */
48  protected $doTask;
49 
50  /**
51  * Redirect message.
52  *
53  * @var string
54  * @since 12.2
55  * @note Replaces _message.
56  */
57  protected $message;
58 
59  /**
60  * Redirect message type.
61  *
62  * @var string
63  * @since 12.2
64  * @note Replaces _messageType.
65  */
66  protected $messageType;
67 
68  /**
69  * Array of class methods
70  *
71  * @var array
72  * @since 12.2
73  * @note Replaces _methods.
74  */
75  protected $methods;
76 
77  /**
78  * The name of the controller
79  *
80  * @var array
81  * @since 12.2
82  * @note Replaces _name.
83  */
84  protected $name;
85 
86  /**
87  * The prefix of the models
88  *
89  * @var string
90  * @since 12.2
91  */
92  protected $model_prefix;
93 
94  /**
95  * The set of search directories for resources (views).
96  *
97  * @var array
98  * @since 12.2
99  * @note Replaces _path.
100  */
101  protected $paths;
102 
103  /**
104  * URL for redirection.
105  *
106  * @var string
107  * @since 12.2
108  * @note Replaces _redirect.
109  */
110  protected $redirect;
111 
112  /**
113  * Current or most recently performed task.
114  *
115  * @var string
116  * @since 12.2
117  * @note Replaces _task.
118  */
119  protected $task;
120 
121  /**
122  * Array of class methods to call for a given task.
123  *
124  * @var array
125  * @since 12.2
126  * @note Replaces _taskMap.
127  */
128  protected $taskMap;
129 
130  /**
131  * Hold a JInput object for easier access to the input variables.
132  *
133  * @var JInput
134  * @since 12.2
135  */
136  protected $input;
137 
138  /**
139  * Instance container.
140  *
141  * @var JControllerLegacy
142  * @since 12.2
143  */
144  protected static $instance;
145 
146  /**
147  * Adds to the stack of model paths in LIFO order.
148  *
149  * @param mixed $path The directory (string), or list of directories (array) to add.
150  * @param string $prefix A prefix for models
151  *
152  * @return void
153  */
154  public static function addModelPath($path, $prefix = '')
155  {
156  JModelLegacy::addIncludePath($path, $prefix);
157  }
158 
159  /**
160  * Create the filename for a resource.
161  *
162  * @param string $type The resource type to create the filename for.
163  * @param array $parts An associative array of filename information. Optional.
164  *
165  * @return string The filename.
166  *
167  * @note Replaced _createFileName.
168  * @since 12.2
169  */
170  protected static function createFileName($type, $parts = array())
171  {
172  $filename = '';
173 
174  switch ($type)
175  {
176  case 'controller':
177  if (!empty($parts['format']))
178  {
179  if ($parts['format'] == 'html')
180  {
181  $parts['format'] = '';
182  }
183  else
184  {
185  $parts['format'] = '.' . $parts['format'];
186  }
187  }
188  else
189  {
190  $parts['format'] = '';
191  }
192 
193  $filename = strtolower($parts['name'] . $parts['format'] . '.php');
194  break;
195 
196  case 'view':
197  if (!empty($parts['type']))
198  {
199  $parts['type'] = '.' . $parts['type'];
200  }
201  else
202  {
203  $parts['type'] = '';
204  }
205 
206  $filename = strtolower($parts['name'] . '/view' . $parts['type'] . '.php');
207  break;
208  }
209 
210  return $filename;
211  }
212 
213  /**
214  * Method to get a singleton controller instance.
215  *
216  * @param string $prefix The prefix for the controller.
217  * @param array $config An array of optional constructor options.
218  *
219  * @return JControllerLegacy
220  *
221  * @since 12.2
222  * @throws Exception if the controller cannot be loaded.
223  */
224  public static function getInstance($prefix, $config = array())
225  {
226  if (is_object(self::$instance))
227  {
228  return self::$instance;
229  }
230 
231  $input = JFactory::getApplication()->input;
232 
233  // Get the environment configuration.
234  $basePath = array_key_exists('base_path', $config) ? $config['base_path'] : JPATH_COMPONENT;
235  $format = $input->getWord('format');
236  $command = $input->get('task', 'display');
237 
238  // Check for array format.
239  $filter = JFilterInput::getInstance();
240 
241  if (is_array($command))
242  {
243  $command = $filter->clean(array_pop(array_keys($command)), 'cmd');
244  }
245  else
246  {
247  $command = $filter->clean($command, 'cmd');
248  }
249 
250  // Check for a controller.task command.
251  if (strpos($command, '.') !== false)
252  {
253  // Explode the controller.task command.
254  list ($type, $task) = explode('.', $command);
255 
256  // Define the controller filename and path.
257  $file = self::createFileName('controller', array('name' => $type, 'format' => $format));
258  $path = $basePath . '/controllers/' . $file;
259  $backuppath = $basePath . '/controller/' . $file;
260 
261  // Reset the task without the controller context.
262  $input->set('task', $task);
263  }
264  else
265  {
266  // Base controller.
267  $type = null;
268 
269  // Define the controller filename and path.
270  $file = self::createFileName('controller', array('name' => 'controller', 'format' => $format));
271  $path = $basePath . '/' . $file;
272  $backupfile = self::createFileName('controller', array('name' => 'controller'));
273  $backuppath = $basePath . '/' . $backupfile;
274  }
275 
276  // Get the controller class name.
277  $class = ucfirst($prefix) . 'Controller' . ucfirst($type);
278 
279  // Include the class if not present.
280  if (!class_exists($class))
281  {
282  // If the controller file path exists, include it.
283  if (file_exists($path))
284  {
285  require_once $path;
286  }
287  elseif (isset($backuppath) && file_exists($backuppath))
288  {
289  require_once $backuppath;
290  }
291  else
292  {
293  throw new InvalidArgumentException(JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER', $type, $format));
294  }
295  }
296 
297  // Instantiate the class.
298  if (class_exists($class))
299  {
300  self::$instance = new $class($config);
301  }
302  else
303  {
304  throw new InvalidArgumentException(JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER_CLASS', $class));
305  }
306 
307  return self::$instance;
308  }
309 
310  /**
311  * Constructor.
312  *
313  * @param array $config An optional associative array of configuration settings.
314  * Recognized key values include 'name', 'default_task', 'model_path', and
315  * 'view_path' (this list is not meant to be comprehensive).
316  *
317  * @since 12.2
318  */
319  public function __construct($config = array())
320  {
321  $this->methods = array();
322  $this->message = null;
323  $this->messageType = 'message';
324  $this->paths = array();
325  $this->redirect = null;
326  $this->taskMap = array();
327 
328  if (defined('JDEBUG') && JDEBUG)
329  {
330  JLog::addLogger(array('text_file' => 'jcontroller.log.php'), JLog::ALL, array('controller'));
331  }
332 
333  $this->input = JFactory::getApplication()->input;
334 
335  // Determine the methods to exclude from the base class.
336  $xMethods = get_class_methods('JControllerLegacy');
337 
338  // Get the public methods in this class using reflection.
339  $r = new ReflectionClass($this);
340  $rMethods = $r->getMethods(ReflectionMethod::IS_PUBLIC);
341 
342  foreach ($rMethods as $rMethod)
343  {
344  $mName = $rMethod->getName();
345 
346  // Add default display method if not explicitly declared.
347  if (!in_array($mName, $xMethods) || $mName == 'display')
348  {
349  $this->methods[] = strtolower($mName);
350 
351  // Auto register the methods as tasks.
352  $this->taskMap[strtolower($mName)] = $mName;
353  }
354  }
355 
356  // Set the view name
357  if (empty($this->name))
358  {
359  if (array_key_exists('name', $config))
360  {
361  $this->name = $config['name'];
362  }
363  else
364  {
365  $this->name = $this->getName();
366  }
367  }
368 
369  // Set a base path for use by the controller
370  if (array_key_exists('base_path', $config))
371  {
372  $this->basePath = $config['base_path'];
373  }
374  else
375  {
376  $this->basePath = JPATH_COMPONENT;
377  }
378 
379  // If the default task is set, register it as such
380  if (array_key_exists('default_task', $config))
381  {
382  $this->registerDefaultTask($config['default_task']);
383  }
384  else
385  {
386  $this->registerDefaultTask('display');
387  }
388 
389  // Set the models prefix
390  if (empty($this->model_prefix))
391  {
392  if (array_key_exists('model_prefix', $config))
393  {
394  // User-defined prefix
395  $this->model_prefix = $config['model_prefix'];
396  }
397  else
398  {
399  $this->model_prefix = $this->name . 'Model';
400  }
401  }
402 
403  // Set the default model search path
404  if (array_key_exists('model_path', $config))
405  {
406  // User-defined dirs
407  $this->addModelPath($config['model_path'], $this->model_prefix);
408  }
409  else
410  {
411  $this->addModelPath($this->basePath . '/models', $this->model_prefix);
412  }
413 
414  // Set the default view search path
415  if (array_key_exists('view_path', $config))
416  {
417  // User-defined dirs
418  $this->setPath('view', $config['view_path']);
419  }
420  else
421  {
422  $this->setPath('view', $this->basePath . '/views');
423  }
424 
425  // Set the default view.
426  if (array_key_exists('default_view', $config))
427  {
428  $this->default_view = $config['default_view'];
429  }
430  elseif (empty($this->default_view))
431  {
432  $this->default_view = $this->getName();
433  }
434 
435  }
436 
437  /**
438  * Adds to the search path for templates and resources.
439  *
440  * @param string $type The path type (e.g. 'model', 'view').
441  * @param mixed $path The directory string or stream array to search.
442  *
443  * @return JControllerLegacy A JControllerLegacy object to support chaining.
444  *
445  * @since 12.2
446  * @note Replaces _addPath.
447  */
448  protected function addPath($type, $path)
449  {
450  // Just force path to array
451  settype($path, 'array');
452 
453  if (!isset($this->paths[$type]))
454  {
455  $this->paths[$type] = array();
456  }
457 
458  // Loop through the path directories
459  foreach ($path as $dir)
460  {
461  // No surrounding spaces allowed!
462  $dir = rtrim(JPath::check($dir, '/'), '/') . '/';
463 
464  // Add to the top of the search dirs
465  array_unshift($this->paths[$type], $dir);
466  }
467 
468  return $this;
469  }
470 
471  /**
472  * Add one or more view paths to the controller's stack, in LIFO order.
473  *
474  * @param mixed $path The directory (string) or list of directories (array) to add.
475  *
476  * @return JControllerLegacy This object to support chaining.
477  */
478  public function addViewPath($path)
479  {
480  $this->addPath('view', $path);
481 
482  return $this;
483  }
484 
485  /**
486  * Authorisation check
487  *
488  * @param string $task The ACO Section Value to check access on.
489  *
490  * @return boolean True if authorised
491  *
492  * @since 12.2
493  * @deprecated 13.3 Use JAccess instead.
494  */
495  public function authorise($task)
496  {
497  JLog::add(__METHOD__ . ' is deprecated. Use JAccess instead.', JLog::WARNING, 'deprecated');
498 
499  return true;
500  }
501 
502  /**
503  * Method to check whether an ID is in the edit list.
504  *
505  * @param string $context The context for the session storage.
506  * @param integer $id The ID of the record to add to the edit list.
507  *
508  * @return boolean True if the ID is in the edit list.
509  *
510  * @since 12.2
511  */
512  protected function checkEditId($context, $id)
513  {
514  if ($id)
515  {
516  $app = JFactory::getApplication();
517  $values = (array) $app->getUserState($context . '.id');
518 
519  $result = in_array((int) $id, $values);
520 
521  if (defined('JDEBUG') && JDEBUG)
522  {
523  JLog::add(
524  sprintf(
525  'Checking edit ID %s.%s: %d %s',
526  $context,
527  $id,
528  (int) $result,
529  str_replace("\n", ' ', print_r($values, 1))
530  ),
531  JLog::INFO,
532  'controller'
533  );
534  }
535 
536  return $result;
537  }
538  else
539  {
540  // No id for a new item.
541  return true;
542  }
543  }
544 
545  /**
546  * Method to load and return a model object.
547  *
548  * @param string $name The name of the model.
549  * @param string $prefix Optional model prefix.
550  * @param array $config Configuration array for the model. Optional.
551  *
552  * @return mixed Model object on success; otherwise null failure.
553  *
554  * @since 12.2
555  * @note Replaces _createModel.
556  */
557  protected function createModel($name, $prefix = '', $config = array())
558  {
559  // Clean the model name
560  $modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
561  $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
562 
563  $result = JModelLegacy::getInstance($modelName, $classPrefix, $config);
564 
565  return $result;
566  }
567 
568  /**
569  * Method to load and return a view object. This method first looks in the
570  * current template directory for a match and, failing that, uses a default
571  * set path to load the view class file.
572  *
573  * Note the "name, prefix, type" order of parameters, which differs from the
574  * "name, type, prefix" order used in related public methods.
575  *
576  * @param string $name The name of the view.
577  * @param string $prefix Optional prefix for the view class name.
578  * @param string $type The type of view.
579  * @param array $config Configuration array for the view. Optional.
580  *
581  * @return mixed View object on success; null or error result on failure.
582  *
583  * @since 12.2
584  * @note Replaces _createView.
585  * @throws Exception
586  */
587  protected function createView($name, $prefix = '', $type = '', $config = array())
588  {
589  // Clean the view name
590  $viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
591  $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
592  $viewType = preg_replace('/[^A-Z0-9_]/i', '', $type);
593 
594  // Build the view class name
595  $viewClass = $classPrefix . $viewName;
596 
597  if (!class_exists($viewClass))
598  {
599  jimport('joomla.filesystem.path');
600  $path = JPath::find($this->paths['view'], $this->createFileName('view', array('name' => $viewName, 'type' => $viewType)));
601 
602  if ($path)
603  {
604  require_once $path;
605 
606  if (!class_exists($viewClass))
607  {
608  throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_CLASS_NOT_FOUND', $viewClass, $path), 500);
609  }
610  }
611  else
612  {
613  return null;
614  }
615  }
616 
617  return new $viewClass($config);
618  }
619 
620  /**
621  * Typical view method for MVC based architecture
622  *
623  * This function is provide as a default implementation, in most cases
624  * you will need to override it in your own controllers.
625  *
626  * @param boolean $cachable If true, the view output will be cached
627  * @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}.
628  *
629  * @return JControllerLegacy A JControllerLegacy object to support chaining.
630  *
631  * @since 12.2
632  */
633  public function display($cachable = false, $urlparams = array())
634  {
635  $document = JFactory::getDocument();
636  $viewType = $document->getType();
637  $viewName = $this->input->get('view', $this->default_view);
638  $viewLayout = $this->input->get('layout', 'default');
639 
640  $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath, 'layout' => $viewLayout));
641 
642  // Get/Create the model
643  if ($model = $this->getModel($viewName))
644  {
645  // Push the model into the view (as default)
646  $view->setModel($model, true);
647  }
648 
649  $view->document = $document;
650 
651  $conf = JFactory::getConfig();
652 
653  // Display the view
654  if ($cachable && $viewType != 'feed' && $conf->get('caching') >= 1)
655  {
656  $option = $this->input->get('option');
657  $cache = JFactory::getCache($option, 'view');
658 
659  if (is_array($urlparams))
660  {
661  $app = JFactory::getApplication();
662 
663  if (!empty($app->registeredurlparams))
664  {
665  $registeredurlparams = $app->registeredurlparams;
666  }
667  else
668  {
669  $registeredurlparams = new stdClass;
670  }
671 
672  foreach ($urlparams as $key => $value)
673  {
674  // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}.
675  $registeredurlparams->$key = $value;
676  }
677 
678  $app->registeredurlparams = $registeredurlparams;
679  }
680 
681  $cache->get($view, 'display');
682  }
683  else
684  {
685  $view->display();
686  }
687 
688  return $this;
689  }
690 
691  /**
692  * Execute a task by triggering a method in the derived class.
693  *
694  * @param string $task The task to perform. If no matching task is found, the '__default' task is executed, if defined.
695  *
696  * @return mixed The value returned by the called method, false in error case.
697  *
698  * @since 12.2
699  * @throws Exception
700  */
701  public function execute($task)
702  {
703  $this->task = $task;
704 
705  $task = strtolower($task);
706  if (isset($this->taskMap[$task]))
707  {
708  $doTask = $this->taskMap[$task];
709  }
710  elseif (isset($this->taskMap['__default']))
711  {
712  $doTask = $this->taskMap['__default'];
713  }
714  else
715  {
716  throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_TASK_NOT_FOUND', $task), 404);
717  }
718 
719  // Record the actual task being fired
720  $this->doTask = $doTask;
721 
722  return $this->$doTask();
723  }
724 
725  /**
726  * Method to get a model object, loading it if required.
727  *
728  * @param string $name The model name. Optional.
729  * @param string $prefix The class prefix. Optional.
730  * @param array $config Configuration array for model. Optional.
731  *
732  * @return object The model.
733  *
734  * @since 12.2
735  */
736  public function getModel($name = '', $prefix = '', $config = array())
737  {
738  if (empty($name))
739  {
740  $name = $this->getName();
741  }
742 
743  if (empty($prefix))
744  {
745  $prefix = $this->model_prefix;
746  }
747 
748  if ($model = $this->createModel($name, $prefix, $config))
749  {
750  // Task is a reserved state
751  $model->setState('task', $this->task);
752 
753  // Let's get the application object and set menu information if it's available
754  $app = JFactory::getApplication();
755  $menu = $app->getMenu();
756 
757  if (is_object($menu))
758  {
759  if ($item = $menu->getActive())
760  {
761  $params = $menu->getParams($item->id);
762 
763  // Set default state data
764  $model->setState('parameters.menu', $params);
765  }
766  }
767  }
768  return $model;
769  }
770 
771  /**
772  * Method to get the controller name
773  *
774  * The dispatcher name is set by default parsed using the classname, or it can be set
775  * by passing a $config['name'] in the class constructor
776  *
777  * @return string The name of the dispatcher
778  *
779  * @since 12.2
780  * @throws Exception
781  */
782  public function getName()
783  {
784  if (empty($this->name))
785  {
786  $r = null;
787  if (!preg_match('/(.*)Controller/i', get_class($this), $r))
788  {
789  throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500);
790  }
791  $this->name = strtolower($r[1]);
792  }
793 
794  return $this->name;
795  }
796 
797  /**
798  * Get the last task that is being performed or was most recently performed.
799  *
800  * @return string The task that is being performed or was most recently performed.
801  *
802  * @since 12.2
803  */
804  public function getTask()
805  {
806  return $this->task;
807  }
808 
809  /**
810  * Gets the available tasks in the controller.
811  *
812  * @return array Array[i] of task names.
813  *
814  * @since 12.2
815  */
816  public function getTasks()
817  {
818  return $this->methods;
819  }
820 
821  /**
822  * Method to get a reference to the current view and load it if necessary.
823  *
824  * @param string $name The view name. Optional, defaults to the controller name.
825  * @param string $type The view type. Optional.
826  * @param string $prefix The class prefix. Optional.
827  * @param array $config Configuration array for view. Optional.
828  *
829  * @return JViewLegacy Reference to the view or an error.
830  *
831  * @since 12.2
832  * @throws Exception
833  */
834  public function getView($name = '', $type = '', $prefix = '', $config = array())
835  {
836  static $views;
837 
838  if (!isset($views))
839  {
840  $views = array();
841  }
842 
843  if (empty($name))
844  {
845  $name = $this->getName();
846  }
847 
848  if (empty($prefix))
849  {
850  $prefix = $this->getName() . 'View';
851  }
852 
853  if (empty($views[$name]))
854  {
855  if ($view = $this->createView($name, $prefix, $type, $config))
856  {
857  $views[$name] = & $view;
858  }
859  else
860  {
861  throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_NOT_FOUND', $name, $type, $prefix), 500);
862  }
863  }
864 
865  return $views[$name];
866  }
867 
868  /**
869  * Method to add a record ID to the edit list.
870  *
871  * @param string $context The context for the session storage.
872  * @param integer $id The ID of the record to add to the edit list.
873  *
874  * @return void
875  *
876  * @since 12.2
877  */
878  protected function holdEditId($context, $id)
879  {
880  $app = JFactory::getApplication();
881  $values = (array) $app->getUserState($context . '.id');
882 
883  // Add the id to the list if non-zero.
884  if (!empty($id))
885  {
886  array_push($values, (int) $id);
887  $values = array_unique($values);
888  $app->setUserState($context . '.id', $values);
889 
890  if (defined('JDEBUG') && JDEBUG)
891  {
892  JLog::add(
893  sprintf(
894  'Holding edit ID %s.%s %s',
895  $context,
896  $id,
897  str_replace("\n", ' ', print_r($values, 1))
898  ),
899  JLog::INFO,
900  'controller'
901  );
902  }
903  }
904  }
905 
906  /**
907  * Redirects the browser or returns false if no redirect is set.
908  *
909  * @return boolean False if no redirect exists.
910  *
911  * @since 12.2
912  */
913  public function redirect()
914  {
915  if ($this->redirect)
916  {
917  $app = JFactory::getApplication();
918 
919  // Enqueue the redirect message
920  $app->enqueueMessage($this->message, $this->messageType);
921 
922  // Execute the redirect
923  $app->redirect($this->redirect);
924  }
925 
926  return false;
927  }
928 
929  /**
930  * Register the default task to perform if a mapping is not found.
931  *
932  * @param string $method The name of the method in the derived class to perform if a named task is not found.
933  *
934  * @return JControllerLegacy A JControllerLegacy object to support chaining.
935  *
936  * @since 12.2
937  */
938  public function registerDefaultTask($method)
939  {
940  $this->registerTask('__default', $method);
941 
942  return $this;
943  }
944 
945  /**
946  * Register (map) a task to a method in the class.
947  *
948  * @param string $task The task.
949  * @param string $method The name of the method in the derived class to perform for this task.
950  *
951  * @return JControllerLegacy A JControllerLegacy object to support chaining.
952  *
953  * @since 12.2
954  */
955  public function registerTask($task, $method)
956  {
957  if (in_array(strtolower($method), $this->methods))
958  {
959  $this->taskMap[strtolower($task)] = $method;
960  }
961 
962  return $this;
963  }
964 
965  /**
966  * Unregister (unmap) a task in the class.
967  *
968  * @param string $task The task.
969  *
970  * @return JControllerLegacy This object to support chaining.
971  *
972  * @since 12.2
973  */
974  public function unregisterTask($task)
975  {
976  unset($this->taskMap[strtolower($task)]);
977 
978  return $this;
979  }
980 
981  /**
982  * Method to check whether an ID is in the edit list.
983  *
984  * @param string $context The context for the session storage.
985  * @param integer $id The ID of the record to add to the edit list.
986  *
987  * @return void
988  *
989  * @since 12.2
990  */
991  protected function releaseEditId($context, $id)
992  {
993  $app = JFactory::getApplication();
994  $values = (array) $app->getUserState($context . '.id');
995 
996  // Do a strict search of the edit list values.
997  $index = array_search((int) $id, $values, true);
998 
999  if (is_int($index))
1000  {
1001  unset($values[$index]);
1002  $app->setUserState($context . '.id', $values);
1003 
1004  if (defined('JDEBUG') && JDEBUG)
1005  {
1006  JLog::add(
1007  sprintf(
1008  'Releasing edit ID %s.%s %s',
1009  $context,
1010  $id,
1011  str_replace("\n", ' ', print_r($values, 1))
1012  ),
1013  JLog::INFO,
1014  'controller'
1015  );
1016  }
1017  }
1018  }
1019 
1020  /**
1021  * Sets the internal message that is passed with a redirect
1022  *
1023  * @param string $text Message to display on redirect.
1024  * @param string $type Message type. Optional, defaults to 'message'.
1025  *
1026  * @return string Previous message
1027  *
1028  * @since 12.2
1029  */
1030  public function setMessage($text, $type = 'message')
1031  {
1032  $previous = $this->message;
1033  $this->message = $text;
1034  $this->messageType = $type;
1035 
1036  return $previous;
1037  }
1038 
1039  /**
1040  * Sets an entire array of search paths for resources.
1041  *
1042  * @param string $type The type of path to set, typically 'view' or 'model'.
1043  * @param string $path The new set of search paths. If null or false, resets to the current directory only.
1044  *
1045  * @return void
1046  *
1047  * @note Replaces _setPath.
1048  * @since 12.2
1049  */
1050  protected function setPath($type, $path)
1051  {
1052  // Clear out the prior search dirs
1053  $this->paths[$type] = array();
1054 
1055  // Actually add the user-specified directories
1056  $this->addPath($type, $path);
1057  }
1058 
1059  /**
1060  * Set a URL for browser redirection.
1061  *
1062  * @param string $url URL to redirect to.
1063  * @param string $msg Message to display on redirect. Optional, defaults to value set internally by controller, if any.
1064  * @param string $type Message type. Optional, defaults to 'message' or the type set by a previous call to setMessage.
1065  *
1066  * @return JControllerLegacy This object to support chaining.
1067  *
1068  * @since 12.2
1069  */
1070  public function setRedirect($url, $msg = null, $type = null)
1071  {
1072  $this->redirect = $url;
1073  if ($msg !== null)
1074  {
1075  // Controller may have set this directly
1076  $this->message = $msg;
1077  }
1078 
1079  // Ensure the type is not overwritten by a previous call to setMessage.
1080  if (empty($type))
1081  {
1082  if (empty($this->messageType))
1083  {
1084  $this->messageType = 'message';
1085  }
1086  }
1087  // If the type is explicitly set, set it.
1088  else
1089  {
1090  $this->messageType = $type;
1091  }
1092 
1093  return $this;
1094  }
1095 }