diff --git a/components/com_users/Model/ProfileModel.php b/components/com_users/Model/ProfileModel.php index 5832fc66fb411..b14519f87d32e 100644 --- a/components/com_users/Model/ProfileModel.php +++ b/components/com_users/Model/ProfileModel.php @@ -37,13 +37,14 @@ class ProfileModel extends FormModel /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * @param MVCFactoryInterface $factory The factory. + * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). + * @param MVCFactoryInterface $factory The factory. + * @param FormFactoryInterface $formFactory The form factory.. * * @see \Joomla\CMS\MVC\Model\BaseDatabaseModel * @since 3.2 */ - public function __construct($config = array(), MVCFactoryInterface $factory = null) + public function __construct($config = array(), MVCFactoryInterface $factory = null, FormFactoryInterface $formFactory = null) { $config = array_merge( array( @@ -51,7 +52,7 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu ), $config ); - parent::__construct($config, $factory); + parent::__construct($config, $factory, $formFactory); } /** diff --git a/components/com_users/Model/RegistrationModel.php b/components/com_users/Model/RegistrationModel.php index ffc57303102cb..c007fb816c57f 100644 --- a/components/com_users/Model/RegistrationModel.php +++ b/components/com_users/Model/RegistrationModel.php @@ -33,13 +33,14 @@ class RegistrationModel extends FormModel /** * Constructor. * - * @param array $config An optional associative array of configuration settings. - * @param MVCFactoryInterface $factory The factory. + * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). + * @param MVCFactoryInterface $factory The factory. + * @param FormFactoryInterface $formFactory The form factory. * * @see \Joomla\CMS\MVC\Model\BaseDatabaseModel * @since 3.2 */ - public function __construct($config = array(), MVCFactoryInterface $factory = null) + public function __construct($config = array(), MVCFactoryInterface $factory = null, FormFactoryInterface $formFactory = null) { $config = array_merge( array( @@ -47,7 +48,7 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu ), $config ); - parent::__construct($config, $factory); + parent::__construct($config, $factory, $formFactory); } /** diff --git a/libraries/src/Dispatcher/Dispatcher.php b/libraries/src/Dispatcher/Dispatcher.php index 4f6c189d5b85e..abcae04414ce5 100644 --- a/libraries/src/Dispatcher/Dispatcher.php +++ b/libraries/src/Dispatcher/Dispatcher.php @@ -12,9 +12,12 @@ use Joomla\CMS\Access\Exception\NotAllowed; use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Form\FormFactoryAwareInterface; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\Input\Input; use Joomla\CMS\MVC\Factory\MVCFactory; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\FormFactoryInterface; /** * Base class for a Joomla Dispatcher @@ -204,6 +207,13 @@ public function getController(string $name, string $client = '', array $config = throw new \InvalidArgumentException(\JText::sprintf('JLIB_APPLICATION_ERROR_INVALID_CONTROLLER_CLASS', $controllerClass)); } - return new $controllerClass($config, new MVCFactory($namespace, $this->app), $this->app, $this->input); + $controller = new $controllerClass($config, new MVCFactory($namespace, $this->app), $this->app, $this->input); + + if ($controller instanceof FormFactoryAwareInterface) + { + $controller->setFormFactory(Factory::getContainer()->get(FormFactoryInterface::class)); + } + + return $controller; } } diff --git a/libraries/src/Form/FormFactoryAwareInterface.php b/libraries/src/Form/FormFactoryAwareInterface.php new file mode 100644 index 0000000000000..db7ffa57fd96e --- /dev/null +++ b/libraries/src/Form/FormFactoryAwareInterface.php @@ -0,0 +1,30 @@ +formFactory) + { + return $this->formFactory; + } + + throw new \UnexpectedValueException('FormFactory not set in ' . __CLASS__); + } + + /** + * Set the form factory to use. + * + * @param FormFactoryInterface $formFactory The form factory to use. + * + * @return $this + * + * @since __DEPLOY_VERSION__ + */ + public function setFormFactory(FormFactoryInterface $formFactory = null) + { + $this->formFactory = $formFactory; + + return $this; + } +} diff --git a/libraries/src/MVC/Controller/FormController.php b/libraries/src/MVC/Controller/FormController.php index 9d0058a6c5173..fd6017abfade5 100644 --- a/libraries/src/MVC/Controller/FormController.php +++ b/libraries/src/MVC/Controller/FormController.php @@ -13,6 +13,9 @@ use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\BaseDatabaseModel; +use Joomla\CMS\Form\FormFactoryAwareInterface; +use Joomla\CMS\Form\FormFactoryAwareTrait; +use Joomla\CMS\Form\FormFactoryInterface; /** * Controller tailored to suit most form-based admin operations. @@ -20,8 +23,10 @@ * @since 1.6 * @todo Add ability to set redirect manually to better cope with frontend usage. */ -class FormController extends BaseController +class FormController extends BaseController implements FormFactoryAwareInterface { + use FormFactoryAwareTrait; + /** * The context for storing internal data, e.g. record. * @@ -65,16 +70,17 @@ class FormController 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 JApplication for the dispatcher - * @param \JInput $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 CMSApplication $app The JApplication for the dispatcher + * @param \JInput $input Input + * @param FormFactoryInterface $formFactory The form factory. * * @since 3.0 */ - public function __construct($config = array(), MVCFactoryInterface $factory = null, $app = null, $input = null) + public function __construct($config = array(), MVCFactoryInterface $factory = null, $app = null, $input = null, FormFactoryInterface $formFactory = null) { parent::__construct($config, $factory, $app, $input); @@ -124,6 +130,8 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu $this->view_list = \Joomla\String\Inflector::getInstance()->toPlural($this->view_item); } + $this->setFormFactory($formFactory); + // Apply, Save & New, and Save As copy should be standard on forms. $this->registerTask('apply', 'save'); $this->registerTask('save2new', 'save'); @@ -428,7 +436,14 @@ public function getModel($name = '', $prefix = '', $config = array('ignore_reque $name = $this->context; } - return parent::getModel($name, $prefix, $config); + $model = parent::getModel($name, $prefix, $config); + + if ($model instanceof FormFactoryAwareInterface) + { + $model->setFormFactory($this->formFactory); + } + + return $model; } /** diff --git a/libraries/src/MVC/Model/AdminModel.php b/libraries/src/MVC/Model/AdminModel.php index f326575957752..38969a073b0b1 100644 --- a/libraries/src/MVC/Model/AdminModel.php +++ b/libraries/src/MVC/Model/AdminModel.php @@ -151,15 +151,16 @@ abstract class AdminModel extends FormModel /** * Constructor. * - * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). - * @param MVCFactoryInterface $factory The factory. + * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). + * @param MVCFactoryInterface $factory The factory. + * @param FormFactoryInterface $formFactory The form factory. * * @since 1.6 * @throws \Exception */ - public function __construct($config = array(), MVCFactoryInterface $factory = null) + public function __construct($config = array(), MVCFactoryInterface $factory = null, FormFactoryInterface $formFactory = null) { - parent::__construct($config, $factory); + parent::__construct($config, $factory, $formFactory); if (isset($config['event_after_delete'])) { diff --git a/libraries/src/MVC/Model/FormModel.php b/libraries/src/MVC/Model/FormModel.php index 943af11d86297..7de31cd4368ef 100644 --- a/libraries/src/MVC/Model/FormModel.php +++ b/libraries/src/MVC/Model/FormModel.php @@ -11,6 +11,10 @@ defined('JPATH_PLATFORM') or die; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\FormFactoryAwareInterface; +use Joomla\CMS\Form\FormFactoryAwareTrait; +use Joomla\CMS\Form\FormFactoryInterface; use Joomla\Utilities\ArrayHelper; /** @@ -21,8 +25,10 @@ * @see \JFormRule * @since 1.6 */ -abstract class FormModel extends BaseDatabaseModel +abstract class FormModel extends BaseDatabaseModel implements FormFactoryAwareInterface { + use FormFactoryAwareTrait; + /** * Array of form objects. * @@ -42,13 +48,14 @@ abstract class FormModel extends BaseDatabaseModel /** * Constructor * - * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). - * @param MVCFactoryInterface $factory The factory. + * @param array $config An array of configuration options (name, state, dbo, table_path, ignore_request). + * @param MVCFactoryInterface $factory The factory. + * @param FormFactoryInterface $formFactory The form factory. * * @since 3.6 * @throws \Exception */ - public function __construct($config = array(), MVCFactoryInterface $factory = null) + public function __construct($config = array(), MVCFactoryInterface $factory = null, FormFactoryInterface $formFactory = null) { $config['events_map'] = $config['events_map'] ?? array(); @@ -60,6 +67,8 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu ); parent::__construct($config, $factory); + + $this->setFormFactory($formFactory); } /** @@ -228,7 +237,33 @@ protected function loadForm($name, $source = null, $options = array(), $clear = try { - $form = \JForm::getInstance($name, $source, $options, false, $xpath); + $formFactory = $this->getFormFactory(); + } + catch (\UnexpectedValueException $e) + { + // @Todo can be removed when the constructor argument becomes mandatory + $formFactory = Factory::getContainer()->get(FormFactoryInterface::class); + } + + try + { + $form = $formFactory->createForm($name, $options); + + // Load the data. + if (substr($source, 0, 1) == '<') + { + if ($form->load($source, false, $xpath) == false) + { + throw new \RuntimeException('Form::loadForm could not load form'); + } + } + else + { + if ($form->loadFile($source, false, $xpath) == false) + { + throw new \RuntimeException('Form::loadForm could not load file'); + } + } if (isset($options['load_data']) && $options['load_data']) {