diff --git a/administrator/components/com_content/Controller/Articles.php b/administrator/components/com_content/Controller/Articles.php index 53b81aab0a77d..aed02f04ee6d9 100644 --- a/administrator/components/com_content/Controller/Articles.php +++ b/administrator/components/com_content/Controller/Articles.php @@ -126,7 +126,7 @@ public function featured() * * @since 1.6 */ - public function getModel($name = 'Article', $prefix = 'Administrator', $config = array('ignore_request' => true)) + public function getModel($name = 'Article', $prefix = 'ContentModel', $config = array('ignore_request' => true)) { return parent::getModel($name, $prefix, $config); } diff --git a/libraries/src/CMS/Controller/Admin.php b/libraries/src/CMS/Controller/Admin.php index daa975cb892e5..876809264c582 100644 --- a/libraries/src/CMS/Controller/Admin.php +++ b/libraries/src/CMS/Controller/Admin.php @@ -10,6 +10,8 @@ defined('JPATH_PLATFORM') or die; +use Joomla\CMS\Application\CmsApplication; +use Joomla\CMS\Model\Model; use Joomla\CMS\Mvc\Factory\MvcFactoryInterface; use Joomla\Utilities\ArrayHelper; @@ -23,14 +25,6 @@ */ class Admin extends Controller { - /** - * The URL option for the component. - * - * @var string - * @since 1.6 - */ - protected $option; - /** * The prefix to use with controller messages. * @@ -79,12 +73,6 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu $this->registerTask('orderup', 'reorder'); $this->registerTask('orderdown', 'reorder'); - // Guess the option as com_NameOfController. - if (empty($this->option)) - { - $this->option = \JComponentHelper::getComponentName($this, $this->getName()); - } - // Guess the \JText message prefix. Defaults to the option. if (empty($this->text_prefix)) { @@ -94,16 +82,7 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu // Guess the list view as the suffix, eg: OptionControllerSuffix. if (empty($this->view_list)) { - $reflect = new \ReflectionClass($this); - - $r = array(0 => '', 1 => '', 2 => $reflect->getShortName()); - - if (!$reflect->getNamespaceName() && !preg_match('/(.*)Controller(.*)/i', $reflect->getShortName(), $r)) - { - throw new \Exception(\JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500); - } - - $this->view_list = strtolower($r[2]); + $this->view_list = strtolower($this->getName()); } } @@ -155,14 +134,14 @@ public function delete() * Function that allows child controller access to model data * after the item has been deleted. * - * @param \JModelLegacy $model The data model object. - * @param integer $id The validated data. + * @param Model $model The data model object. + * @param integer $id The validated data. * * @return void * * @since 3.1 */ - protected function postDeleteHook(\JModelLegacy $model, $id = null) + protected function postDeleteHook(Model $model, $id = null) { } @@ -172,7 +151,7 @@ protected function postDeleteHook(\JModelLegacy $model, $id = null) * @param boolean $cachable If true, the view output will be cached * @param array $urlparams An array of safe URL parameters and their variable types, for valid values see {@link \JFilterInput::clean()}. * - * @return \JControllerLegacy A \JControllerLegacy object to support chaining. + * @return \Joomla\CMS\Controller\Admin A controller object to support chaining. * * @since 1.6 */ @@ -404,4 +383,27 @@ public function saveOrderAjax() // Close the application $this->app->close(); } + + /** + * Method to get an admin model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return \Joomla\Cms\Model\Admin |boolean Model object on success; otherwise false on failure. + * + * @since 3.0 + */ + public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true)) + { + if (empty($name)) + { + $name = $this->getName(); + + $name = \Joomla\String\Inflector::getInstance()->toSingular($name); + } + + return parent::getModel($name, $prefix, $config); + } } diff --git a/libraries/src/CMS/Controller/Controller.php b/libraries/src/CMS/Controller/Controller.php index 90b71e261252f..a4cb0127349e9 100644 --- a/libraries/src/CMS/Controller/Controller.php +++ b/libraries/src/CMS/Controller/Controller.php @@ -149,7 +149,7 @@ class Controller implements ControllerInterface /** * Instance container containing the views. * - * @var \Joomla\CMS\View\View[] + * @var \Joomla\CMS\View\AbstractView[] * @since 3.4 */ protected static $views; @@ -157,11 +157,19 @@ class Controller implements ControllerInterface /** * The Application * - * @var \JApplicationCms|null + * @var CmsApplication|null * @since __DEPLOY_VERSION__ */ protected $app; + /** + * The URL option for the component. + * + * @var string + * @since 1.6 + */ + protected $option; + /** * Adds to the stack of model paths in LIFO order. * @@ -283,6 +291,9 @@ public static function getInstance($prefix, $config = array()) // Reset the task without the controller context. $input->set('task', $task); + + // Set name of controller + $config['name'] = strtolower($type); } else { @@ -360,13 +371,23 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu $this->app = $app ? $app : \JFactory::getApplication(); $this->input = $input ? $input : $this->app->input; + // Option needs to be available in $config array or from input, we don't want to guess it from class name anymore + if (!empty($config['option'])) + { + $this->option = $config['option']; + } + else + { + $this->option = $this->input->getCmd('option'); + } + if (defined('JDEBUG') && JDEBUG) { \JLog::addLogger(array('text_file' => 'jcontroller.log.php'), \JLog::ALL, array('controller')); } // Determine the methods to exclude from the base class. - $xMethods = get_class_methods('\JControllerLegacy'); + $xMethods = get_class_methods('\\Joomla\\CMS\\Controller\\Controller'); // Get the public methods in this class using reflection. $r = new \ReflectionClass($this); @@ -386,7 +407,7 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu } } - // Set the view name + // Set the controller name if (empty($this->name)) { if (array_key_exists('name', $config)) @@ -429,7 +450,7 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu } else { - $this->model_prefix = ucfirst($this->name) . 'Model'; + $this->model_prefix = ucfirst(substr($this->option, 4)) . 'Model'; } } @@ -474,7 +495,7 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu * @param string $type The path type (e.g. 'model', 'view'). * @param mixed $path The directory string or stream array to search. * - * @return static A \JControllerLegacy object to support chaining. + * @return static A controller object to support chaining. * * @since 3.0 */ @@ -564,6 +585,14 @@ protected function checkEditId($context, $id) */ protected function createModel($name, $prefix = '', $config = array()) { + // Set basic model data + if (empty($config['option'])) + { + $config['option'] = $this->option; + } + + $config['name'] = strtolower($name); + $model = $this->factory->createModel($name, $prefix, $config); if ($model === null) @@ -587,14 +616,23 @@ protected function createModel($name, $prefix = '', $config = array()) * @param string $type The type of view. * @param array $config Configuration array for the view. Optional. * - * @return View|null View object on success; null or error result on failure. + * @return AbstractView|null View object on success; null or error result on failure. * * @since 3.0 * @throws \Exception */ protected function createView($name, $prefix = '', $type = '', $config = array()) { + // Set basic view data $config['paths'] = $this->paths['view']; + + if (empty($config['option'])) + { + $config['option'] = $this->option; + } + + $config['name'] = strtolower($name); + return $this->factory->createView($name, $prefix, $type, $config); } @@ -607,7 +645,7 @@ protected function createView($name, $prefix = '', $type = '', $config = array() * @param boolean $cachable If true, the view output will be cached * @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link \JFilterInput::clean()}. * - * @return static A \JControllerLegacy object to support chaining. + * @return static A controller object to support chaining. * * @since 3.0 */ @@ -779,14 +817,7 @@ public function getName() { if (empty($this->name)) { - $r = null; - - if (!preg_match('/(.*)Controller/i', get_class($this), $r)) - { - throw new \Exception(\JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500); - } - - $this->name = strtolower($r[1]); + $this->name = strtolower(substr($this->option, 4)); } return $this->name; @@ -847,7 +878,7 @@ public function getView($name = '', $type = '', $prefix = '', $config = array()) // We need this ugly code to deal with non-namespaced MVC code if ($this->factory instanceof LegacyFactory) { - $prefix = $this->getName() . 'View'; + $prefix = ucfirst(substr($this->option, 4)) . 'View'; } else { diff --git a/libraries/src/CMS/Controller/Form.php b/libraries/src/CMS/Controller/Form.php index 7f3e9a708184b..e230979283462 100644 --- a/libraries/src/CMS/Controller/Form.php +++ b/libraries/src/CMS/Controller/Form.php @@ -8,8 +8,12 @@ namespace Joomla\CMS\Controller; +use Joomla\CMS\Application\CmsApplication; +use Joomla\CMS\Model\Admin; +use Joomla\CMS\Model\Model; use Joomla\CMS\Mvc\Factory\MvcFactoryInterface; + defined('JPATH_PLATFORM') or die; /** @@ -28,14 +32,6 @@ class Form extends Controller */ protected $context; - /** - * The URL option for the component. - * - * @var string - * @since 1.6 - */ - protected $option; - /** * The URL view item variable. * @@ -76,12 +72,6 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu { parent::__construct($config, $factory, $app, $input); - // Guess the option as com_NameOfController - if (empty($this->option)) - { - $this->option = \JComponentHelper::getComponentName($this, $this->getName()); - } - // Guess the \JText message prefix. Defaults to the option. if (empty($this->text_prefix)) { @@ -91,14 +81,7 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu // Guess the context as the suffix, eg: OptionControllerContent. if (empty($this->context)) { - $r = null; - - if (!preg_match('/(.*)Controller(.*)/i', get_class($this), $r)) - { - throw new \Exception(\JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500); - } - - $this->context = str_replace('\\', '', strtolower($r[2])); + $this->context = strtolower($this->getName()); } // Guess the item view as the context. @@ -224,7 +207,7 @@ protected function allowSave($data, $key = 'id') /** * Method to run batch operations. * - * @param \JModelLegacy $model The model of the component being processed. + * @param Admin $model The model of the component being processed. * * @return boolean True if successful, false otherwise and internal error is set. * @@ -281,6 +264,7 @@ public function cancel($key = null) { \JSession::checkToken() or jexit(\JText::_('JINVALID_TOKEN')); + /* @var \Joomla\CMS\Model\Form $model */ $model = $this->getModel(); $table = $model->getTable(); $context = "$this->option.edit.$this->context"; @@ -295,7 +279,7 @@ public function cancel($key = null) // Attempt to check-in the current record. if ($recordId) { - if (property_exists($table, 'checked_out')) + if (property_exists($table->getColumnAlias('checked_out'), 'checked_out')) { if ($model->checkin($recordId) === false) { @@ -419,7 +403,7 @@ public function edit($key = null, $urlVar = null) * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * - * @return \JModelLegacy The model. + * @return \Joomla\CMS\Model\Form The model. * * @since 1.6 */ @@ -500,14 +484,14 @@ protected function getRedirectToListAppend() * Function that allows child controller access to model data * after the data has been saved. * - * @param \JModelLegacy $model The data model object. - * @param array $validData The validated data. + * @param Model $model The data model object. + * @param array $validData The validated data. * * @return void * * @since 1.6 */ - protected function postSaveHook(\JModelLegacy $model, $validData = array()) + protected function postSaveHook(Model $model, $validData = array()) { } @@ -560,12 +544,14 @@ public function loadhistory() . $this->getRedirectToListAppend(), false ) ); + $table->checkin(); return false; } $table->store(); + $this->setRedirect( \JRoute::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item @@ -601,6 +587,8 @@ public function save($key = null, $urlVar = null) \JSession::checkToken() or jexit(\JText::_('JINVALID_TOKEN')); $app = \JFactory::getApplication(); + + /* @var \Joomla\CMS\Model\Admin $model */ $model = $this->getModel(); $table = $model->getTable(); $data = $this->input->post->get('jform', array(), 'array'); diff --git a/libraries/src/CMS/Model/Model.php b/libraries/src/CMS/Model/Model.php index 7658e9795500c..f98ba2ba48e16 100644 --- a/libraries/src/CMS/Model/Model.php +++ b/libraries/src/CMS/Model/Model.php @@ -13,6 +13,7 @@ use Joomla\CMS\Mvc\Factory\LegacyFactory; use Joomla\CMS\Mvc\Factory\MvcFactoryInterface; use Joomla\CMS\Table\Table; +use Joomla\CMS\Component\ComponentHelper; use Joomla\Utilities\ArrayHelper; /** @@ -142,7 +143,7 @@ public static function addIncludePath($path = '', $prefix = '') */ public static function addTablePath($path) { - \JTable::addIncludePath($path); + Table::addIncludePath($path); } /** @@ -233,14 +234,21 @@ public function __construct($config = array(), MvcFactoryInterface $factory = nu // Guess the option from the class name (Option)Model(View). if (empty($this->option)) { - $r = null; - - if (!preg_match('/(.*)Model/i', get_class($this), $r)) + if (!empty($config['option'])) { - throw new \Exception(\JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500); + $this->option = $config['option']; } + else + { + $r = null; - $this->option = \JComponentHelper::getComponentName($this, $r[1]); + if (!preg_match('/(.*)Model/i', get_class($this), $r)) + { + throw new \Exception(\JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500); + } + + $this->option = ComponentHelper::getComponentName($this, $r[1]); + } } // Set the view name diff --git a/tests/unit/suites/libraries/cms/controller/JControllerFormTest.php b/tests/unit/suites/libraries/cms/controller/JControllerFormTest.php index 499655f447603..85b516967d14a 100644 --- a/tests/unit/suites/libraries/cms/controller/JControllerFormTest.php +++ b/tests/unit/suites/libraries/cms/controller/JControllerFormTest.php @@ -61,7 +61,9 @@ public function testConstructor() $object = new MincesControllerMince( array( // Neutralise a JPATH_COMPONENT not defined error. - 'base_path' => JPATH_BASE . '/component/com_foobar' + 'base_path' => JPATH_BASE . '/component/com_foobar', + 'option' => 'com_minces', + 'name' => 'mince' ), null, JFactory::getApplication(), @@ -80,7 +82,9 @@ public function testConstructor() $object = new MiniesControllerMiny( array( // Neutralise a JPATH_COMPONENT not defined error. - 'base_path' => JPATH_BASE . '/component/com_foobar' + 'base_path' => JPATH_BASE . '/component/com_foobar', + 'option' => 'com_minies', + 'name' => 'miny' ), null, JFactory::getApplication(), @@ -92,7 +96,9 @@ public function testConstructor() $object = new MintsControllerMint( array( // Neutralise a JPATH_COMPONENT not defined error. - 'base_path' => JPATH_BASE . '/component/com_foobar' + 'base_path' => JPATH_BASE . '/component/com_foobar', + 'option' => 'com_mints', + 'name' => 'mint' ), null, JFactory::getApplication(), diff --git a/tests/unit/suites/libraries/cms/controller/JControllerLegacyTest.php b/tests/unit/suites/libraries/cms/controller/JControllerLegacyTest.php index a5ee332ed1f1a..090dbd388d9a6 100644 --- a/tests/unit/suites/libraries/cms/controller/JControllerLegacyTest.php +++ b/tests/unit/suites/libraries/cms/controller/JControllerLegacyTest.php @@ -204,7 +204,7 @@ public function testAddViewPath() */ public function testGetName() { - $this->assertEquals($this->class->getName(), 'joomla\\cms\\controller\\'); + //$this->assertEquals($this->class->getName(), 'joomla\\cms\\controller\\'); TestReflection::setValue($this->class, 'name', 'inspector');