diff --git a/installation/src/Application/InstallationApplication.php b/installation/src/Application/InstallationApplication.php index 09c7047ca96e1..dc64e11ea83d5 100644 --- a/installation/src/Application/InstallationApplication.php +++ b/installation/src/Application/InstallationApplication.php @@ -297,7 +297,7 @@ private function executeController() list($controllerName, $task) = explode('.', $task, 2); } - $factory = new MVCFactory('Joomla\\CMS'); + $factory = new MVCFactory('Joomla\\CMS', $this->getLogger()); $factory->setDatabase($this->getContainer()->get(DatabaseInterface::class)); // Create the instance diff --git a/libraries/src/MVC/Controller/AdminController.php b/libraries/src/MVC/Controller/AdminController.php index 5447b5bc76856..8a0f306cdd0c6 100644 --- a/libraries/src/MVC/Controller/AdminController.php +++ b/libraries/src/MVC/Controller/AdminController.php @@ -9,7 +9,7 @@ namespace Joomla\CMS\MVC\Controller; -use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; @@ -33,6 +33,14 @@ */ class AdminController extends BaseController { + /** + * The Application. Redeclared to show this class requires a web application. + * + * @var CMSWebApplicationInterface + * @since __DEPLOY_VERSION__ + */ + protected $app; + /** * The URL option for the component. * @@ -60,16 +68,17 @@ class AdminController extends BaseController /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?Input $input The Input object for the request + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', + * 'model_path', and 'view_path' (this list is not meant to be + * comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSWebApplicationInterface $app The Application for the dispatcher + * @param ?Input $input The Input object for the request * * @since 3.0 */ - public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSApplication $app = null, ?Input $input = null) + public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSWebApplicationInterface $app = null, ?Input $input = null) { parent::__construct($config, $factory, $app, $input); @@ -134,7 +143,7 @@ public function delete() $cid = array_filter($cid); if (empty($cid)) { - $this->app->getLogger()->warning(Text::_($this->text_prefix . '_NO_ITEM_SELECTED'), ['category' => 'jerror']); + $this->getLogger()->warning(Text::_($this->text_prefix . '_NO_ITEM_SELECTED'), ['category' => 'jerror']); } else { // Get the model. $model = $this->getModel(); @@ -196,7 +205,7 @@ public function publish() $cid = array_filter($cid); if (empty($cid)) { - $this->app->getLogger()->warning(Text::_($this->text_prefix . '_NO_ITEM_SELECTED'), ['category' => 'jerror']); + $this->getLogger()->warning(Text::_($this->text_prefix . '_NO_ITEM_SELECTED'), ['category' => 'jerror']); } else { // Get the model. $model = $this->getModel(); @@ -209,7 +218,10 @@ public function publish() if ($value === 1) { if ($errors) { - $this->app->enqueueMessage(Text::plural($this->text_prefix . '_N_ITEMS_FAILED_PUBLISHING', \count($cid)), 'error'); + $this->app->enqueueMessage( + Text::plural($this->text_prefix . '_N_ITEMS_FAILED_PUBLISHING', \count($cid)), + CMSWebApplicationInterface::MSG_ERROR + ); } else { $ntext = $this->text_prefix . '_N_ITEMS_PUBLISHED'; } diff --git a/libraries/src/MVC/Controller/ApiController.php b/libraries/src/MVC/Controller/ApiController.php index cf21176fcc7e0..c73f7226d4207 100644 --- a/libraries/src/MVC/Controller/ApiController.php +++ b/libraries/src/MVC/Controller/ApiController.php @@ -10,7 +10,7 @@ namespace Joomla\CMS\MVC\Controller; use Joomla\CMS\Access\Exception\NotAllowed; -use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; @@ -36,6 +36,14 @@ */ class ApiController extends BaseController { + /** + * The Application. Redeclared to show this class requires a web application. + * + * @var CMSWebApplicationInterface + * @since __DEPLOY_VERSION__ + */ + protected $app; + /** * The content type of the item. * @@ -85,17 +93,18 @@ class ApiController extends BaseController /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?Input $input Input + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', + * 'model_path', and 'view_path' (this list is not meant to be + * comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSWebApplicationInterface $app The Application for the dispatcher + * @param ?Input $input Input * - * @since 4.0.0 * @throws \Exception + * @since 4.0.0 */ - public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSApplication $app = null, ?Input $input = null) + public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSWebApplicationInterface $app = null, ?Input $input = null) { $this->modelState = new CMSObject(); diff --git a/libraries/src/MVC/Controller/BaseController.php b/libraries/src/MVC/Controller/BaseController.php index e7807ee4972d9..5cdf9a504a4db 100644 --- a/libraries/src/MVC/Controller/BaseController.php +++ b/libraries/src/MVC/Controller/BaseController.php @@ -9,7 +9,9 @@ namespace Joomla\CMS\MVC\Controller; -use Joomla\CMS\Application\CMSApplication; +use Joomla\Application\AbstractApplication; +use Joomla\CMS\Application\CMSApplicationInterface; +use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Cache\Exception\CacheExceptionInterface; use Joomla\CMS\Document\DocumentAwareInterface; use Joomla\CMS\Factory; @@ -30,6 +32,10 @@ use Joomla\Event\DispatcherInterface; use Joomla\Filesystem\Path; use Joomla\Input\Input; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -43,8 +49,9 @@ * * @since 2.5.5 */ -class BaseController implements ControllerInterface, DispatcherAwareInterface +class BaseController implements ControllerInterface, DispatcherAwareInterface, LoggerAwareInterface { + use LoggerAwareTrait; use DispatcherAwareTrait; /** @@ -178,7 +185,7 @@ class BaseController implements ControllerInterface, DispatcherAwareInterface /** * The Application * - * @var CMSApplication|null + * @var CMSApplicationInterface * @since 4.0.0 */ protected $app; @@ -348,16 +355,17 @@ public static function getInstance($prefix, $config = []) /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?Input $input Input + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', + * 'model_path', and 'view_path' (this list is not meant to be + * comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSApplicationInterface $app The Application for the dispatcher + * @param ?Input $input Input * * @since 3.0 */ - public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSApplication $app = null, ?Input $input = null) + public function __construct($config = [], MVCFactoryInterface $factory = null, ?CMSApplicationInterface $app = null, ?Input $input = null) { $this->methods = []; $this->message = null; @@ -369,6 +377,15 @@ public function __construct($config = [], MVCFactoryInterface $factory = null, ? $this->app = $app ?: Factory::getApplication(); $this->input = $input ?: $this->app->getInput(); + /** + * @deprecated This is to maintain b/c with the J4.0 implementation of BaseController. In Joomla 6.0 this will be + * removed and instead the logger should be injected by the MVCFactory using + * BaseController::setLogger() + */ + if ($this->app instanceof AbstractApplication) { + $this->setLogger($this->app->getLogger()); + } + if (\defined('JDEBUG') && JDEBUG) { Log::addLogger(['text_file' => 'jcontroller.log.php'], Log::ALL, ['controller']); } @@ -457,7 +474,7 @@ public function __construct($config = [], MVCFactoryInterface $factory = null, ? * @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 BaseController object to support chaining. * * @since 3.0 */ @@ -505,13 +522,24 @@ public function addViewPath($path) */ protected function checkEditId($context, $id) { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + if ($id) { $values = (array) $this->app->getUserState($context . '.id'); $result = \in_array((int) $id, $values); if (\defined('JDEBUG') && JDEBUG) { - $this->app->getLogger()->info( + $this->getLogger()->info( sprintf( 'Checking edit ID %s.%s: %d %s', $context, @@ -608,6 +636,17 @@ protected function createView($name, $prefix = '', $type = '', $config = []) */ public function display($cachable = false, $urlparams = []) { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + $document = $this->app->getDocument(); $viewType = $document->getType(); $viewName = $this->input->get('view', $this->default_view); @@ -729,14 +768,21 @@ public function getModel($name = '', $prefix = '', $config = []) return $model; } - // Let's get the application object and set menu information if it's available - $menu = $this->app->getMenu(); + if ($this->app instanceof CMSWebApplicationInterface) { + // Let's get the application object and set menu information if it's available + $menu = $this->app->getMenu(); + + if (\is_object($menu) && $item = $menu->getActive()) { + // Let's get the application object and set menu information if it's available + $menu = $this->app->getMenu(); - if (\is_object($menu) && $item = $menu->getActive()) { - $params = $menu->getParams($item->id); + if (\is_object($menu) && $item = $menu->getActive()) { + $params = $menu->getParams($item->id); - // Set default state data - $model->setState('parameters.menu', $params); + // Set default state data + $model->setState('parameters.menu', $params); + } + } } } @@ -848,9 +894,21 @@ public function getView($name = '', $type = '', $prefix = '', $config = []) * @return void * * @since 3.0 + * @throws \Exception */ protected function holdEditId($context, $id) { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + $values = (array) $this->app->getUserState($context . '.id'); // Add the id to the list if non-zero. @@ -860,7 +918,7 @@ protected function holdEditId($context, $id) $this->app->setUserState($context . '.id', $values); if (\defined('JDEBUG') && JDEBUG) { - $this->app->getLogger()->info( + $this->getLogger()->info( sprintf( 'Holding edit ID %s.%s %s', $context, @@ -879,9 +937,21 @@ protected function holdEditId($context, $id) * @return boolean False if no redirect exists. * * @since 3.0 + * @throws \Exception */ public function redirect() { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + if ($this->redirect) { // Enqueue the redirect message $this->app->enqueueMessage($this->message, $this->messageType); @@ -953,9 +1023,21 @@ public function unregisterTask($task) * @return void * * @since 3.0 + * @throws \Exception */ protected function releaseEditId($context, $id) { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + $values = (array) $this->app->getUserState($context . '.id'); // Do a strict search of the edit list values. @@ -966,7 +1048,7 @@ protected function releaseEditId($context, $id) $this->app->setUserState($context . '.id', $values); if (\defined('JDEBUG') && JDEBUG) { - $this->app->getLogger()->info( + $this->getLogger()->info( sprintf( 'Releasing edit ID %s.%s %s', $context, @@ -979,6 +1061,23 @@ protected function releaseEditId($context, $id) } } + /** + * Get the logger. + * + * @return LoggerInterface + * + * @since __DEPLOY_VERSION__ + */ + protected function getLogger() + { + // If a logger hasn't been set, use NullLogger + if (!($this->logger instanceof LoggerInterface)) { + $this->setLogger(new NullLogger()); + } + + return $this->logger; + } + /** * Sets the internal message that is passed with a redirect * @@ -1028,10 +1127,22 @@ protected function setPath($type, $path) * @return boolean True if found and valid, otherwise return false or redirect to referrer page. * * @since 3.7.0 + * @throws \Exception * @see Session::checkToken() */ public function checkToken($method = 'post', $redirect = true) { + if (!($this->app instanceof CMSWebApplicationInterface)) { + throw new \Exception( + sprintf( + 'The %s method requires an instance of %s but instead %s was supplied', + __METHOD__, + CMSWebApplicationInterface::class, + get_class($this->app) + ) + ); + } + $valid = Session::checkToken($method); if (!$valid && $redirect) { @@ -1041,7 +1152,7 @@ public function checkToken($method = 'post', $redirect = true) $referrer = 'index.php'; } - $this->app->enqueueMessage(Text::_('JINVALID_TOKEN_NOTICE'), 'warning'); + $this->app->enqueueMessage(Text::_('JINVALID_TOKEN_NOTICE'), CMSWebApplicationInterface::MSG_WARNING); $this->app->redirect($referrer); } diff --git a/libraries/src/MVC/Controller/FormController.php b/libraries/src/MVC/Controller/FormController.php index 06b3ecc92008f..f6c8b886ff0c1 100644 --- a/libraries/src/MVC/Controller/FormController.php +++ b/libraries/src/MVC/Controller/FormController.php @@ -10,7 +10,7 @@ namespace Joomla\CMS\MVC\Controller; use Doctrine\Inflector\InflectorFactory; -use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Event\Model; use Joomla\CMS\Form\FormFactoryAwareInterface; @@ -37,6 +37,14 @@ class FormController extends BaseController implements FormFactoryAwareInterface { use FormFactoryAwareTrait; + /** + * The Application. Redeclared to show this class requires a web application. + * + * @var CMSWebApplicationInterface + * @since __DEPLOY_VERSION__ + */ + protected $app; + /** * The context for storing internal data, e.g. record. * @@ -80,20 +88,21 @@ class FormController extends BaseController implements FormFactoryAwareInterface /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?Input $input Input - * @param ?FormFactoryInterface $formFactory The form factory. + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', + * 'model_path', and 'view_path' (this list is not meant to be + * comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSWebApplicationInterface $app The Application for the dispatcher + * @param ?Input $input Input + * @param ?FormFactoryInterface $formFactory The form factory. * * @since 3.0 */ public function __construct( $config = [], MVCFactoryInterface $factory = null, - ?CMSApplication $app = null, + ?CMSWebApplicationInterface $app = null, ?Input $input = null, FormFactoryInterface $formFactory = null ) { @@ -540,7 +549,6 @@ public function save($key = null, $urlVar = null) // Check for request forgeries. $this->checkToken(); - $app = $this->app; $model = $this->getModel(); $table = $model->getTable(); $data = $this->input->post->get('jform', [], 'array'); @@ -607,7 +615,7 @@ public function save($key = null, $urlVar = null) $form = $model->getForm($data, false); if (!$form) { - $app->enqueueMessage($model->getError(), 'error'); + $this->app->enqueueMessage($model->getError(), CMSWebApplicationInterface::MSG_ERROR); return false; } @@ -635,9 +643,9 @@ public function save($key = null, $urlVar = null) // Push up to three validation messages out to the user. for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) { if ($errors[$i] instanceof \Exception) { - $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); + $this->app->enqueueMessage($errors[$i]->getMessage(), CMSWebApplicationInterface::MSG_WARNING); } else { - $app->enqueueMessage($errors[$i], 'warning'); + $this->app->enqueueMessage($errors[$i], CMSWebApplicationInterface::MSG_WARNING); } } @@ -659,7 +667,7 @@ public function save($key = null, $urlVar = null) } // Save the data in the session. - $app->setUserState($context . '.data', $data); + $this->app->setUserState($context . '.data', $data); // Redirect back to the edit screen. $this->setRedirect( @@ -680,7 +688,7 @@ public function save($key = null, $urlVar = null) // Attempt to save the data. if (!$model->save($validData)) { // Save the data in the session. - $app->setUserState($context . '.data', $validData); + $this->app->setUserState($context . '.data', $validData); // Redirect back to the edit screen. $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error'); @@ -699,7 +707,7 @@ public function save($key = null, $urlVar = null) // Save succeeded, so check-in the record. if ($checkin && $model->checkin($validData[$key]) === false) { // Save the data in the session. - $app->setUserState($context . '.data', $validData); + $this->app->setUserState($context . '.data', $validData); // Check-in failed, so go back to the record and display a notice. $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error'); @@ -715,10 +723,10 @@ public function save($key = null, $urlVar = null) return false; } - $langKey = $this->text_prefix . ($recordId === 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'; + $langKey = $this->text_prefix . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'; $prefix = $this->app->getLanguage()->hasKey($langKey) ? $this->text_prefix : 'JLIB_APPLICATION'; - $this->setMessage(Text::_($prefix . ($recordId === 0 && $app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS')); + $this->setMessage(Text::_($prefix . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS')); // Redirect the user and adjust session state based on the chosen task. switch ($task) { @@ -726,7 +734,7 @@ public function save($key = null, $urlVar = null) // Set the record data in the session. $recordId = $model->getState($model->getName() . '.id'); $this->holdEditId($context, $recordId); - $app->setUserState($context . '.data', null); + $this->app->setUserState($context . '.data', null); $model->checkout($recordId); // Redirect back to the edit screen. @@ -742,7 +750,7 @@ public function save($key = null, $urlVar = null) case 'save2new': // Clear the record id and data from the session. $this->releaseEditId($context, $recordId); - $app->setUserState($context . '.data', null); + $this->app->setUserState($context . '.data', null); // Redirect back to the edit screen. $this->setRedirect( @@ -757,7 +765,7 @@ public function save($key = null, $urlVar = null) default: // Clear the record id and data from the session. $this->releaseEditId($context, $recordId); - $app->setUserState($context . '.data', null); + $this->app->setUserState($context . '.data', null); $url = 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(); @@ -795,7 +803,6 @@ public function reload($key = null, $urlVar = null) // Check for request forgeries. $this->checkToken(); - $app = $this->app; $model = $this->getModel(); $data = $this->input->post->get('jform', [], 'array'); @@ -860,7 +867,7 @@ public function reload($key = null, $urlVar = null) } // Save the data in the session. - $app->setUserState($this->option . '.edit.' . $this->context . '.data', $data); + $this->app->setUserState($this->option . '.edit.' . $this->context . '.data', $data); $this->setRedirect($redirectUrl); $this->redirect(); @@ -879,11 +886,9 @@ public function reload($key = null, $urlVar = null) public function editAssociations() { // Initialise variables. - $app = $this->app; - $input = $app->getInput(); $model = $this->getModel(); + $data = $this->input->get('jform', [], 'array'); - $data = $input->get('jform', [], 'array'); $model->editAssociations($data); } } diff --git a/libraries/src/MVC/Factory/MVCFactory.php b/libraries/src/MVC/Factory/MVCFactory.php index aa78751ae87ca..b2de886101c90 100644 --- a/libraries/src/MVC/Factory/MVCFactory.php +++ b/libraries/src/MVC/Factory/MVCFactory.php @@ -29,6 +29,8 @@ use Joomla\Event\DispatcherAwareInterface; use Joomla\Event\DispatcherAwareTrait; use Joomla\Input\Input; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -57,17 +59,27 @@ class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, Site */ private $namespace; + /** + * The namespace to create the objects from. + * + * @var LoggerInterface + * @since 4.0.0 + */ + private $logger; + /** * The namespace must be like: * Joomla\Component\Content * - * @param string $namespace The namespace + * @param string $namespace The namespace + * @param LoggerInterface|null $logger A logging instance to inject into the controller if required * * @since 4.0.0 */ - public function __construct($namespace) + public function __construct($namespace, LoggerInterface $logger = null) { $this->namespace = $namespace; + $this->logger = $logger; } /** @@ -79,7 +91,7 @@ public function __construct($namespace) * @param CMSApplicationInterface $app The app * @param Input $input The input * - * @return \Joomla\CMS\MVC\Controller\ControllerInterface + * @return \Joomla\CMS\MVC\Controller\ControllerInterface|null * * @since 3.10.0 * @throws \Exception @@ -104,6 +116,10 @@ public function createController($name, $prefix, array $config, CMSApplicationIn $this->setUserFactoryOnObject($controller); $this->setMailerFactoryOnObject($controller); + if ($controller instanceof LoggerAwareInterface && $this->logger !== null) { + $controller->setLogger($this->logger); + } + return $controller; } diff --git a/tests/Unit/Libraries/Cms/MVC/Controller/BaseControllerTest.php b/tests/Unit/Libraries/Cms/MVC/Controller/BaseControllerTest.php index cc79fc9581235..2f23a80263e85 100644 --- a/tests/Unit/Libraries/Cms/MVC/Controller/BaseControllerTest.php +++ b/tests/Unit/Libraries/Cms/MVC/Controller/BaseControllerTest.php @@ -12,6 +12,8 @@ use Exception; use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Application\CMSApplicationInterface; +use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Document\Document; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\MVC\Factory\LegacyFactory; @@ -46,7 +48,7 @@ class BaseControllerTest extends UnitTestCase public function testInjectedDependencies() { $mvcFactory = $this->createStub(MVCFactoryInterface::class); - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSApplicationInterface::class); $input = new Input(); $controller = new class (['base_path' => __DIR__], $mvcFactory, $app, $input) extends BaseController { @@ -79,7 +81,7 @@ public function getInput(): Input */ public function testGetInjectedName() { - $controller = new class (['name' => 'unit test', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['name' => 'unit test', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { }; $this->assertEquals('unit test', $controller->getName()); @@ -94,7 +96,7 @@ public function testGetInjectedName() */ public function testGetCompiledName() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { }; $this->assertStringContainsStringIgnoringCase('base', $controller->getName()); @@ -109,7 +111,7 @@ public function testGetCompiledName() */ public function testAvailableTasks() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function unit() { } @@ -127,7 +129,7 @@ public function unit() */ public function testUnregisterTask() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function list() { return $this->taskMap; @@ -147,7 +149,7 @@ public function list() */ public function testExecuteTask() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function unit() { return 'unit test'; @@ -167,7 +169,7 @@ public function unit() */ public function testExecuteInjectedDefaultTask() { - $controller = new class (['default_task' => 'unit', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['default_task' => 'unit', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function unit() { return 'unit test'; @@ -187,7 +189,7 @@ public function unit() */ public function testExecuteDisplayDefaultTask() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function display($cachable = false, $urlparams = []) { return 'unit test'; @@ -207,7 +209,7 @@ public function display($cachable = false, $urlparams = []) */ public function testExecuteTaskWhichDoesntExist() { - $controller = new class (['default_task' => 'invalid', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['default_task' => 'invalid', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { }; $this->expectException(\Exception::class); @@ -229,7 +231,7 @@ public function testGetModel() }; $mvcFactory->method('createModel')->willReturn($model); - $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $this->assertEquals($model, $controller->getModel()); @@ -247,7 +249,7 @@ public function testGetModelWithInjectedPrefix() $mvcFactory = $this->createMock(LegacyFactory::class); $mvcFactory->expects($this->once())->method('createModel')->with($this->equalTo('Unit'), $this->equalTo('Test')); - $controller = new class (['model_prefix' => 'Test', 'base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['model_prefix' => 'Test', 'base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $controller->getModel('Unit'); } @@ -264,7 +266,7 @@ public function testGetModelWithAppNamePrefix() $mvcFactory = $this->createMock(MVCFactoryInterface::class); $mvcFactory->expects($this->once())->method('createModel')->with($this->equalTo('Unit'), $this->equalTo('Test')); - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSApplicationInterface::class); $app->method('getName')->willReturn('Test'); $controller = new class (['base_path' => __DIR__], $mvcFactory, $app, new Input()) extends BaseController { @@ -283,7 +285,7 @@ public function testGetNullModel() { $mvcFactory = $this->createStub(MVCFactoryInterface::class); - $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $this->assertFalse($controller->getModel()); @@ -310,7 +312,7 @@ public function getUser(): User $mvcFactory->method('createModel')->willReturn($model); $user = new User(); - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSApplicationInterface::class); $app->method('getIdentity')->willReturn($user); $controller = new class (['base_path' => __DIR__], $mvcFactory, $app, new Input()) extends BaseController { @@ -336,7 +338,7 @@ public function display($tpl = null) $mvcFactory = $this->createStub(MVCFactoryInterface::class); $mvcFactory->method('createView')->willReturn($view); - $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $this->assertEquals($view, $controller->getView('testGetView')); @@ -355,7 +357,7 @@ public function testGetViewWithInjectedPrefix() $mvcFactory->expects($this->once())->method('createView')->with($this->equalTo('Unit'), $this->equalTo('TestView')) ->willReturn($this->createStub(AbstractView::class)); - $controller = new class (['name' => 'Test', 'base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['name' => 'Test', 'base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $controller->getView('Unit'); } @@ -371,7 +373,7 @@ public function testGetNullView() { $mvcFactory = $this->createStub(MVCFactoryInterface::class); - $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $mvcFactory, $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { }; $this->expectException(\Exception::class); @@ -404,7 +406,7 @@ public function getUser(): User $mvcFactory->method('createView')->willReturn($view); $user = new User(); - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSApplicationInterface::class); $app->method('getIdentity')->willReturn($user); $controller = new class (['base_path' => __DIR__], $mvcFactory, $app, new Input()) extends BaseController { @@ -423,7 +425,7 @@ public function getUser(): User public function testInjectViewPath() { $path = dirname(__DIR__); - $controller = new class (['view_path' => $path, 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['view_path' => $path, 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function getPaths() { return $this->paths; @@ -443,7 +445,7 @@ public function getPaths() */ public function testAddViewPath() { - $controller = new class (['name' => 'unit test', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class)) extends BaseController { + $controller = new class (['name' => 'unit test', 'base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class)) extends BaseController { public function getPaths() { return $this->paths; @@ -465,7 +467,7 @@ public function getPaths() */ public function testDisplay() { - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSWebApplicationInterface::class); $app->method('getDocument')->willReturn(new Document()); $view = new class (['name' => 'test']) extends AbstractView { @@ -496,7 +498,7 @@ public function display($tpl = null) */ public function testDisplayWithModel() { - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSWebApplicationInterface::class); $app->method('getDocument')->willReturn(new Document()); $model = new class (['name' => 'test']) extends BaseModel { @@ -528,7 +530,7 @@ public function display($tpl = null) */ public function testCheckEditIdExist() { - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSWebApplicationInterface::class); $app->method('getUserState')->willReturn([1]); $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $app, new Input()) extends BaseController { @@ -550,7 +552,7 @@ public function checkEditId($context, $id) */ public function testCheckEditIdNotExist() { - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSWebApplicationInterface::class); $app->method('getUserState')->willReturn([1]); $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $app, new Input()) extends BaseController { @@ -572,7 +574,7 @@ public function checkEditId($context, $id) */ public function testCheckEditEmptyId() { - $app = $this->createStub(CMSApplication::class); + $app = $this->createStub(CMSWebApplicationInterface::class); $app->method('getUserState')->willReturn([1]); $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $app, new Input()) extends BaseController { @@ -594,7 +596,7 @@ public function checkEditId($context, $id) */ public function testHoldEditId() { - $app = $this->createMock(CMSApplication::class); + $app = $this->createMock(CMSWebApplicationInterface::class); $app->expects($this->once())->method('setUserState')->with($this->equalTo('unit.id'), $this->equalTo([1])); $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $app, new Input()) extends BaseController { @@ -615,7 +617,7 @@ public function holdEditId($context, $id) */ public function testHoldEditEmptyId() { - $app = $this->createMock(CMSApplication::class); + $app = $this->createMock(CMSWebApplicationInterface::class); $app->expects($this->never())->method('setUserState'); $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $app, new Input()) extends BaseController { @@ -636,7 +638,7 @@ public function holdEditId($context, $id) */ public function testReleaseEditId() { - $app = $this->createMock(CMSApplication::class); + $app = $this->createMock(CMSWebApplicationInterface::class); $app->method('getUserState')->willReturn([1, 2]); $app->expects($this->once())->method('setUserState')->with($this->equalTo('unit.id'), $this->equalTo([1 => 2])); @@ -658,7 +660,7 @@ public function releaseEditId($context, $id) */ public function testReleaseInvalidEditId() { - $app = $this->createMock(CMSApplication::class); + $app = $this->createMock(CMSWebApplicationInterface::class); $app->method('getUserState')->willReturn([2]); $app->expects($this->never())->method('setUserState'); @@ -680,7 +682,7 @@ public function releaseEditId($context, $id) */ public function testSetRedirect() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { public function getRedirect() { return $this->redirect; @@ -712,7 +714,7 @@ public function getMessageType() */ public function testSetRedirectWithEmptyType() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { public function getMessageType() { return $this->messageType; @@ -732,7 +734,7 @@ public function getMessageType() */ public function testRedirect() { - $app = $this->createMock(CMSApplication::class); + $app = $this->createMock(CMSWebApplicationInterface::class); $app->expects($this->once())->method('redirect')->with($this->equalTo('unit/test')); $app->expects($this->once())->method('enqueueMessage')->with($this->equalTo('unit test')); @@ -758,7 +760,7 @@ public function redirect() */ public function testSetMessage() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { public function getMessage() { return $this->message; @@ -784,7 +786,7 @@ public function getMessageType() */ public function testSetMessageTwice() { - $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplication::class), new Input()) extends BaseController { + $controller = new class (['base_path' => __DIR__], $this->createStub(MVCFactoryInterface::class), $this->createStub(CMSApplicationInterface::class), new Input()) extends BaseController { public function getMessage() { return $this->message;