Skip to content

Commit

Permalink
[4.0] Create the controller through the MVC factory (#19908)
Browse files Browse the repository at this point in the history
* Create the controller through the MVC factory

* Fix docblock

* use the form factory properly

* CS

* CS
  • Loading branch information
laoneo authored and wilsonge committed Mar 25, 2018
1 parent 54f2ed0 commit b2a6817
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 52 deletions.
5 changes: 4 additions & 1 deletion administrator/components/com_content/services/provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ public function register(Container $container)
$container->set(Categories::class, ['' => new Category]);
$container->set(AssociationExtensionInterface::class, new AssociationsHelper);

$container->set(MVCFactoryFactoryInterface::class, new MVCFactoryFactory('\\Joomla\\Component\\Content'));
$factory = new MVCFactoryFactory('\\Joomla\\Component\\Content');
$factory->setFormFactory($container->get(\Joomla\CMS\Form\FormFactoryInterface::class));
$container->set(MVCFactoryFactoryInterface::class, $factory);

$container->set(
DispatcherFactoryInterface::class,
new DispatcherFactory('\\Joomla\\Component\\Content', $container->get(MVCFactoryFactoryInterface::class))
Expand Down
44 changes: 12 additions & 32 deletions libraries/src/Dispatcher/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,6 @@ abstract class Dispatcher implements DispatcherInterface
*/
protected $option;

/**
* The extension namespace
*
* @var string
* @since 4.0.0
*/
protected $namespace;

/**
* The application instance
*
Expand Down Expand Up @@ -82,14 +74,6 @@ abstract class Dispatcher implements DispatcherInterface
*/
public function __construct(CMSApplication $app, Input $input, MVCFactoryFactoryInterface $mvcFactoryFactory)
{
if (empty($this->namespace))
{
$reflect = new \ReflectionClass($this);

// Extract the first three segments from the namespace
$this->namespace = implode('\\', array_slice(explode('\\', $reflect->getNamespaceName()), 0, 3));
}

$this->app = $app;
$this->input = $input;
$this->mvcFactoryFactory = $mvcFactoryFactory;
Expand Down Expand Up @@ -206,26 +190,22 @@ protected function getApplication(): CMSApplication
*/
public function getController(string $name, string $client = '', array $config = array()): BaseController
{
// Set up the namespace
$namespace = rtrim($this->namespace, '\\') . '\\';

// Set up the client
$client = $client ?: ucfirst($this->app->getName());

$controllerClass = $namespace . $client . '\\Controller\\' . ucfirst($name) . 'Controller';

if (!class_exists($controllerClass))
{
throw new \InvalidArgumentException(\JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER_CLASS', $controllerClass));
}

// Create the controller instance
$controller = new $controllerClass($config, $this->mvcFactoryFactory->createFactory($this->app), $this->app, $this->input);

// Set the form factory when possible
if ($controller instanceof FormFactoryAwareInterface)
// Get the controller instance
$controller = $this->mvcFactoryFactory->createFactory($this->app)->createController(
$name,
$client,
$config,
$this->app,
$this->input
);

// Check if the controller could be created
if (!$controller)
{
$controller->setFormFactory(Factory::getContainer()->get(FormFactoryInterface::class));
throw new \InvalidArgumentException(\JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER_CLASS', $name));
}

return $controller;
Expand Down
9 changes: 1 addition & 8 deletions libraries/src/MVC/Controller/FormController.php
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,7 @@ public function getModel($name = '', $prefix = '', $config = array('ignore_reque
$name = $this->context;
}

$model = parent::getModel($name, $prefix, $config);

if ($model instanceof FormFactoryAwareInterface)
{
$model->setFormFactory($this->formFactory);
}

return $model;
return parent::getModel($name, $prefix, $config);
}

/**
Expand Down
29 changes: 25 additions & 4 deletions libraries/src/MVC/Factory/LegacyFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Table\Table;
use Joomla\Input\Input;

/**
* Factory to create MVC objects in legacy mode.
Expand All @@ -23,6 +25,25 @@
*/
class LegacyFactory implements MVCFactoryInterface
{
/**
* Method to load and return a controller object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param array $config Optional configuration array for the view.
* @param CMSApplicationInterface $app The app
* @param Input $input The input
*
* @return \Joomla\CMS\MVC\Controller\ControllerInterface
*
* @since __DEPLOY_VERSION__
* @throws \BadFunctionCallException
*/
public function createController($name, $prefix = '', array $config = [], CMSApplicationInterface $app = null, Input $input = null)
{
throw new \BadFunctionCallException('Legacy controller creation not supported.');
}

/**
* Method to load and return a model object.
*
Expand All @@ -38,7 +59,7 @@ class LegacyFactory implements MVCFactoryInterface
public function createModel($name, $prefix = '', array $config = [])
{
// Clean the model name
$modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$modelName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

return BaseDatabaseModel::getInstance($modelName, $classPrefix, $config);
Expand All @@ -60,9 +81,9 @@ public function createModel($name, $prefix = '', array $config = [])
public function createView($name, $prefix = '', $type = '', array $config = [])
{
// Clean the view name
$viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$viewName = preg_replace('/[^A-Z0-9_]/i', '', $name);
$classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);
$viewType = preg_replace('/[^A-Z0-9_]/i', '', $type);
$viewType = preg_replace('/[^A-Z0-9_]/i', '', $type);

// Build the view class name
$viewClass = $classPrefix . $viewName;
Expand Down Expand Up @@ -103,7 +124,7 @@ public function createView($name, $prefix = '', $type = '', array $config = [])
public function createTable($name, $prefix = 'Table', array $config = [])
{
// Clean the model name
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

return Table::getInstance($name, $prefix, $config);
Expand Down
79 changes: 74 additions & 5 deletions libraries/src/MVC/Factory/MVCFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@

use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormFactoryAwareInterface;
use Joomla\CMS\Form\FormFactoryAwareTrait;
use Joomla\Input\Input;

/**
* Factory to create MVC objects based on a namespace.
*
* @since 4.0.0
*/
class MVCFactory implements MVCFactoryInterface
class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface
{
use FormFactoryAwareTrait;

/**
* The namespace to create the objects from.
*
Expand All @@ -40,7 +45,7 @@ class MVCFactory implements MVCFactoryInterface
* The namespace must be like:
* Joomla\Component\Content
*
* @param string $namespace The namespace.
* @param string $namespace The namespace
* @param CMSApplicationInterface $application The application
*
* @since 4.0.0
Expand All @@ -51,6 +56,39 @@ public function __construct($namespace, CMSApplicationInterface $application)
$this->application = $application;
}

/**
* Method to load and return a controller object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param array $config Optional configuration array for the view.
* @param CMSApplicationInterface $app The app
* @param Input $input The input
*
* @return \Joomla\CMS\MVC\Controller\ControllerInterface
*
* @since __DEPLOY_VERSION__
* @throws \Exception
*/
public function createController($name, $prefix = '', array $config = [], CMSApplicationInterface $app = null, Input $input = null)
{
// Clean the parameters
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

$className = $this->getClassName('Controller\\' . ucfirst($name) . 'Controller', $prefix);

if (!$className)
{
return null;
}

$controller = new $className($config, $this, $app ?: $this->application, $input ?: $this->application->input);
$this->setFormFactoryOnObject($controller);

return $controller;
}

/**
* Method to load and return a model object.
*
Expand All @@ -76,7 +114,10 @@ public function createModel($name, $prefix = '', array $config = [])
return null;
}

return new $className($config, $this);
$model = new $className($config, $this);
$this->setFormFactoryOnObject($model);

return $model;
}

/**
Expand Down Expand Up @@ -106,7 +147,10 @@ public function createView($name, $prefix = '', $type = '', array $config = [])
return null;
}

return new $className($config);
$view = new $className($config);
$this->setFormFactoryOnObject($view);

return $view;
}

/**
Expand All @@ -124,7 +168,7 @@ public function createView($name, $prefix = '', $type = '', array $config = [])
public function createTable($name, $prefix = '', array $config = [])
{
// Clean the parameters
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$name = preg_replace('/[^A-Z0-9_]/i', '', $name);
$prefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix);

$className = $this->getClassName('Table\\' . ucfirst($name) . 'Table', $prefix)
Expand Down Expand Up @@ -173,4 +217,29 @@ private function getClassName(string $suffix, string $prefix)

return $className;
}

/**
* Sets the internal form factory on the given object.
*
* @param object $object The object
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
private function setFormFactoryOnObject($object)
{
if (!$object instanceof FormFactoryAwareInterface)
{
return;
}

try
{
$object->setFormFactory($this->getFormFactory());
}
catch (\UnexpectedValueException $e)
{
}
}
}
18 changes: 16 additions & 2 deletions libraries/src/MVC/Factory/MVCFactoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Form\FormFactoryAwareInterface;
use Joomla\CMS\Form\FormFactoryAwareTrait;

/**
* Factory to create MVC factories.
*
* @since __DEPLOY_VERSION__
*/
class MVCFactoryFactory implements MVCFactoryFactoryInterface
class MVCFactoryFactory implements MVCFactoryFactoryInterface, FormFactoryAwareInterface
{
use FormFactoryAwareTrait;

/**
* The namespace.
*
Expand Down Expand Up @@ -56,6 +60,16 @@ public function createFactory(CMSApplicationInterface $application): MVCFactoryI
return new LegacyFactory;
}

return new MVCFactory($this->namespace, $application);
$factory = new MVCFactory($this->namespace, $application);

try
{
$factory->setFormFactory($this->getFormFactory());
}
catch (\UnexpectedValueException $e)
{
}

return $factory;
}
}
19 changes: 19 additions & 0 deletions libraries/src/MVC/Factory/MVCFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,32 @@

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\Input\Input;

/**
* Factory to create MVC objects.
*
* @since 4.0.0
*/
interface MVCFactoryInterface
{
/**
* Method to load and return a controller object.
*
* @param string $name The name of the view.
* @param string $prefix Optional view prefix.
* @param array $config Optional configuration array for the view.
* @param CMSApplicationInterface $app The app
* @param Input $input The input
*
* @return \Joomla\CMS\MVC\Controller\ControllerInterface
*
* @since __DEPLOY_VERSION__
* @throws \Exception
*/
public function createController($name, $prefix = '', array $config = [], CMSApplicationInterface $app = null, Input $input = null);

/**
* Method to load and return a model object.
*
Expand Down

0 comments on commit b2a6817

Please sign in to comment.