diff --git a/administrator/components/com_associations/Helper/AssociationsHelper.php b/administrator/components/com_associations/Helper/AssociationsHelper.php index 647b1729f6ebe..50eba67a1693f 100644 --- a/administrator/components/com_associations/Helper/AssociationsHelper.php +++ b/administrator/components/com_associations/Helper/AssociationsHelper.php @@ -10,6 +10,8 @@ defined('_JEXEC') or die; +use Joomla\CMS\Association\AssociationAwareInterface; +use Joomla\CMS\Association\Exception\AssociationsNotImplementedException; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Layout\LayoutHelper; @@ -343,9 +345,18 @@ public static function getSupportedExtension($extensionName) $result->def('helper', null); // Get the associations class - $helper = Factory::getApplication()->bootComponent($extensionName)->getAssociationsExtension(); + $componentInterface = Factory::getApplication()->bootComponent($extensionName); - if (!$helper) + if (!$componentInterface instanceof AssociationAwareInterface) + { + return $result; + } + + try + { + $helper = $componentInterface->getAssociationsExtension(); + } + catch (AssociationsNotImplementedException $e) { return $result; } diff --git a/administrator/components/com_content/services/provider.php b/administrator/components/com_content/services/provider.php index 417fb8e7c79b6..9a8ab6687b586 100644 --- a/administrator/components/com_content/services/provider.php +++ b/administrator/components/com_content/services/provider.php @@ -12,6 +12,7 @@ use Joomla\CMS\Association\AssociationExtensionInterface; use Joomla\CMS\Application\SiteApplication; use Joomla\CMS\Categories\Categories; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Dispatcher\DispatcherFactory; use Joomla\CMS\Dispatcher\DispatcherFactoryInterface; use Joomla\CMS\Extension\Service\Provider\Component; @@ -32,6 +33,14 @@ */ return new class implements ServiceProviderInterface { + /** + * The extension name to use + * + * @type string + * @since __DEPLOY_VERSION__ + */ + protected $extension_name = 'com_content'; + /** * Registers the service provider with a DI container. * @@ -56,13 +65,16 @@ public function register(Container $container) $container->set(Categories::class, ['' => new Category]); $container->set(AssociationExtensionInterface::class, new AssociationsHelper); - $factory = new MVCFactoryFactory('\\Joomla\\Component\\Content'); + $factory = new MVCFactoryFactory(ComponentHelper::getComponent($this->extension_name)->namespace); $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)) + new DispatcherFactory( + ComponentHelper::getComponent($this->extension_name)->namespace, + $container->get(MVCFactoryFactoryInterface::class) + ) ); $container->registerServiceProvider(new Component); } diff --git a/administrator/components/com_fields/Model/FieldModel.php b/administrator/components/com_fields/Model/FieldModel.php index 57681c10e2276..2e31a35370cef 100644 --- a/administrator/components/com_fields/Model/FieldModel.php +++ b/administrator/components/com_fields/Model/FieldModel.php @@ -10,6 +10,8 @@ defined('_JEXEC') or die; +use Joomla\CMS\Categories\CategoryNotFoundExceptionInterface; +use Joomla\CMS\Categories\CategoryAwareInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\MVC\Model\AdminModel; @@ -967,7 +969,20 @@ protected function preprocessForm(\JForm $form, $data, $group = 'content') } // Setting the context for the category field - $cat = $this->bootComponent($component)->getCategories(); + $componentClass = $this->bootComponent($component); + $cat = null; + + if ($componentClass instanceof CategoryAwareInterface) + { + try + { + $cat = $componentClass->getCategories(); + } + catch (CategoryNotFoundExceptionInterface $e) + { + // Categories not supported + } + } if ($cat && $cat->get('root')->hasChildren()) { diff --git a/libraries/src/Association/AssociationAwareInterface.php b/libraries/src/Association/AssociationAwareInterface.php new file mode 100644 index 0000000000000..1b8a809f56ead --- /dev/null +++ b/libraries/src/Association/AssociationAwareInterface.php @@ -0,0 +1,29 @@ +associationExtension === null) + { + throw new Exception\AssociationsNotImplementedException; + } + + return $this->associationExtension; + } + + /** + * The association extension. + * + * @param AssociationExtensionInterface $associationExtension The extension + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function setAssociationExtension(AssociationExtensionInterface $associationExtension) + { + $this->associationExtension = $associationExtension; + } + +} diff --git a/libraries/src/Association/Exception/AssociationsNotImplementedException.php b/libraries/src/Association/Exception/AssociationsNotImplementedException.php new file mode 100644 index 0000000000000..3bbc93347876e --- /dev/null +++ b/libraries/src/Association/Exception/AssociationsNotImplementedException.php @@ -0,0 +1,20 @@ +bootComponent($parts[0])->getCategories($options, count($parts) > 1 ? $parts[1] : ''); + // Setting the context for the category field + $componentClass = Factory::getApplication()->bootComponent($parts[0]); + + if (!$componentClass instanceof CategoryAwareInterface) + { + return false; + } + + try + { + $categories = $componentClass->getCategories($options, count($parts) > 1 ? $parts[1] : ''); + } + catch (CategoryNotFoundExceptionInterface $e) + { + return false; + } self::$instances[$hash] = $categories; diff --git a/libraries/src/Categories/CategoryAwareInterface.php b/libraries/src/Categories/CategoryAwareInterface.php new file mode 100644 index 0000000000000..3123d25cc3465 --- /dev/null +++ b/libraries/src/Categories/CategoryAwareInterface.php @@ -0,0 +1,34 @@ +categories)) + { + throw new Exception\SectionNotFoundException; + } + + $categories = clone $this->categories[$section]; + $categories->setOptions($options); + + return $categories; + } + + /** + * An array of categories where the key is the name of the section. + * If the component has no sections then the array must have at least + * an empty key. + * + * @param array $categories The categories + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function setCategories(array $categories) + { + $this->categories = $categories; + } +} diff --git a/libraries/src/Categories/CategoryNotFoundExceptionInterface.php b/libraries/src/Categories/CategoryNotFoundExceptionInterface.php new file mode 100644 index 0000000000000..634e76befec48 --- /dev/null +++ b/libraries/src/Categories/CategoryNotFoundExceptionInterface.php @@ -0,0 +1,18 @@ +mvcFactoryFactory = $mvcFactoryFactory; } - - /** - * Returns the category service. If the service is not available - * null is returned. - * - * @param array $options The options - * @param string $section The section - * - * @return Categories|null - * - * @see Categories::setOptions() - * - * @since __DEPLOY_VERSION__ - */ - public function getCategories(array $options = [], $section = '') - { - if (!array_key_exists($section, $this->categories)) - { - return null; - } - - $categories = clone $this->categories[$section]; - $categories->setOptions($options); - - return $categories; - } - - /** - * An array of categories where the key is the name of the section. - * If the component has no sections then the array must have at least - * an empty key. - * - * @param array $categories The categories - * - * @return void - * - * @since __DEPLOY_VERSION__ - */ - public function setCategories(array $categories) - { - $this->categories = $categories; - } - - /** - * Returns the associations helper. - * - * @return AssociationExtensionInterface|null - * - * @since __DEPLOY_VERSION__ - */ - public function getAssociationsExtension() - { - return $this->associationExtension; - } - - /** - * The association extension. - * - * @param AssociationExtensionInterface $associationExtension The extension - * - * @return void - * - * @since __DEPLOY_VERSION__ - */ - public function setAssociationExtension(AssociationExtensionInterface $associationExtension) - { - $this->associationExtension = $associationExtension; - } } diff --git a/libraries/src/Extension/ComponentInterface.php b/libraries/src/Extension/ComponentInterface.php index fc3a978e68384..b56284a495d55 100644 --- a/libraries/src/Extension/ComponentInterface.php +++ b/libraries/src/Extension/ComponentInterface.php @@ -11,8 +11,6 @@ defined('JPATH_PLATFORM') or die; use Joomla\CMS\Application\CMSApplicationInterface; -use Joomla\CMS\Association\AssociationExtensionInterface; -use Joomla\CMS\Categories\Categories; use Joomla\CMS\Dispatcher\DispatcherInterface; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; @@ -44,28 +42,4 @@ public function getDispatcher(CMSApplicationInterface $application): DispatcherI * @since __DEPLOY_VERSION__ */ public function createMVCFactory(CMSApplicationInterface $application): MVCFactoryInterface; - - /** - * Returns the category service. If the service is not available - * null is returned. - * - * @param array $options The options - * @param string $section The section - * - * @return Categories|null - * - * @see Categories::setOptions() - * - * @since __DEPLOY_VERSION__ - */ - public function getCategories(array $options = [], $section = ''); - - /** - * Returns the associations extension helper class. - * - * @return AssociationExtensionInterface|null - * - * @since __DEPLOY_VERSION__ - */ - public function getAssociationsExtension(); } diff --git a/libraries/src/Extension/LegacyComponent.php b/libraries/src/Extension/LegacyComponent.php index fb47fb5dde7b4..3617ffffe0269 100644 --- a/libraries/src/Extension/LegacyComponent.php +++ b/libraries/src/Extension/LegacyComponent.php @@ -11,8 +11,13 @@ defined('JPATH_PLATFORM') or die; use Joomla\CMS\Application\CMSApplicationInterface; +use Joomla\CMS\Association\AssociationAwareInterface; use Joomla\CMS\Association\AssociationExtensionInterface; +use Joomla\CMS\Association\Exception\AssociationsNotImplementedException; use Joomla\CMS\Categories\Categories; +use Joomla\CMS\Categories\CategoryAwareInterface; +use Joomla\CMS\Categories\CategoryNotFoundExceptionInterface; +use Joomla\CMS\Categories\Exception\CategoriesNotImplementedException; use Joomla\CMS\Dispatcher\DispatcherInterface; use Joomla\CMS\Dispatcher\LegacyDispatcher; use Joomla\CMS\MVC\Factory\LegacyFactory; @@ -24,7 +29,7 @@ * * @since __DEPLOY_VERSION__ */ -class LegacyComponent implements ComponentInterface +class LegacyComponent implements ComponentInterface, CategoryAwareInterface, AssociationAwareInterface { /** * @var string @@ -91,8 +96,9 @@ public function createMVCFactory(CMSApplicationInterface $application): MVCFacto * @see Categories::setOptions() * * @since __DEPLOY_VERSION__ + * @throws CategoryNotFoundExceptionInterface */ - public function getCategories(array $options = [], $section = '') + public function getCategories(array $options = [], $section = ''): Categories { $classname = ucfirst($this->component) . ucfirst($section) . 'Categories'; @@ -102,7 +108,7 @@ public function getCategories(array $options = [], $section = '') if (!is_file($path)) { - return null; + throw new CategoriesNotImplementedException; } include_once $path; @@ -110,7 +116,7 @@ public function getCategories(array $options = [], $section = '') if (!class_exists($classname)) { - return null; + throw new CategoriesNotImplementedException; } return new $classname($options); @@ -119,11 +125,12 @@ public function getCategories(array $options = [], $section = '') /** * Returns the associations helper. * - * @return AssociationExtensionInterface|null + * @return AssociationExtensionInterface * - * @since __DEPLOY_VERSION__ + * @since __DEPLOY_VERSION__ + * @throws AssociationsNotImplementedException */ - public function getAssociationsExtension() + public function getAssociationsExtension(): AssociationExtensionInterface { $className = ucfirst($this->component) . 'AssociationsHelper'; @@ -135,7 +142,7 @@ public function getAssociationsExtension() // Check if associations helper exists if (!file_exists(JPATH_ADMINISTRATOR . '/components/com_' . $this->component . '/helpers/associations.php')) { - return null; + throw new AssociationsNotImplementedException; } require_once JPATH_ADMINISTRATOR . '/components/com_' . $this->component . '/helpers/associations.php'; diff --git a/libraries/src/MVC/Factory/MVCFactoryFactory.php b/libraries/src/MVC/Factory/MVCFactoryFactory.php index 7c9caf82dd26d..87b48b426dca8 100644 --- a/libraries/src/MVC/Factory/MVCFactoryFactory.php +++ b/libraries/src/MVC/Factory/MVCFactoryFactory.php @@ -51,7 +51,6 @@ public function __construct(string $namespace) * @return \Joomla\CMS\MVC\Factory\MVCFactoryInterface * * @since __DEPLOY_VERSION__ - * @throws \Exception */ public function createFactory(CMSApplicationInterface $application): MVCFactoryInterface { diff --git a/libraries/src/MVC/Factory/MVCFactoryFactoryInterface.php b/libraries/src/MVC/Factory/MVCFactoryFactoryInterface.php index 522ce242ea4a2..88e27aa986b27 100644 --- a/libraries/src/MVC/Factory/MVCFactoryFactoryInterface.php +++ b/libraries/src/MVC/Factory/MVCFactoryFactoryInterface.php @@ -27,7 +27,6 @@ interface MVCFactoryFactoryInterface * @return \Joomla\CMS\MVC\Factory\MVCFactoryInterface * * @since __DEPLOY_VERSION__ - * @throws \Exception */ public function createFactory(CMSApplicationInterface $application): MVCFactoryInterface; }