first commit

This commit is contained in:
2025-06-17 11:53:18 +02:00
commit 9f0f7ba12b
8804 changed files with 1369176 additions and 0 deletions

View File

@ -0,0 +1,39 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Psr\Container\ContainerInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Interface which defines that an extension can be booted.
*
* @since 4.0.0
*/
interface BootableExtensionInterface
{
/**
* Booting the extension. This is the function to set up the environment of the extension like
* registering new class loaders, etc.
*
* If required, some initial set up can be done from services of the container, eg.
* registering HTML services.
*
* @param ContainerInterface $container The container
*
* @return void
*
* @since 4.0.0
*/
public function boot(ContainerInterface $container);
}

View File

@ -0,0 +1,61 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\Dispatcher\DispatcherInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to component specific services.
*
* @since 4.0.0
*/
class Component implements ComponentInterface
{
/**
* The dispatcher factory.
*
* @var ComponentDispatcherFactoryInterface
*
* @since 4.0.0
*/
private $dispatcherFactory;
/**
* Component constructor.
*
* @param ComponentDispatcherFactoryInterface $dispatcherFactory The dispatcher factory
*
* @since 4.0.0
*/
public function __construct(ComponentDispatcherFactoryInterface $dispatcherFactory)
{
$this->dispatcherFactory = $dispatcherFactory;
}
/**
* Returns the dispatcher for the given application.
*
* @param CMSApplicationInterface $application The application
*
* @return DispatcherInterface
*
* @since 4.0.0
*/
public function getDispatcher(CMSApplicationInterface $application): DispatcherInterface
{
return $this->dispatcherFactory->createDispatcher($application);
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Dispatcher\DispatcherInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to component specific services.
*
* @since 4.0.0
*/
interface ComponentInterface
{
/**
* Returns the dispatcher for the given application.
*
* @param CMSApplicationInterface $application The application
*
* @return DispatcherInterface
*
* @since 4.0.0
*/
public function getDispatcher(CMSApplicationInterface $application): DispatcherInterface;
}

View File

@ -0,0 +1,25 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Plugin\CMSPlugin;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Placeholder plugin.
*
* @since 4.0.0
*/
class DummyPlugin extends CMSPlugin
{
}

View File

@ -0,0 +1,495 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Factory;
use Joomla\Database\ParameterType;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Extension Helper class.
*
* @since 3.7.4
*/
class ExtensionHelper
{
/**
* The loaded extensions.
*
* @var array
* @since 4.0.0
*/
public static $extensions = [ModuleInterface::class => [], ComponentInterface::class => [], PluginInterface::class => []];
/**
* The loaded extensions.
*
* @var array
* @since 4.0.0
*/
private static $loadedExtensions = [];
/**
* Array of core extensions
* Each element is an array with elements "type", "element", "folder" and
* "client_id".
*
* @var array
* @since 3.7.4
*/
protected static $coreExtensions = [
// Format: `type`, `element`, `folder`, `client_id`
// Core component extensions
['component', 'com_actionlogs', '', 1],
['component', 'com_admin', '', 1],
['component', 'com_ajax', '', 1],
['component', 'com_associations', '', 1],
['component', 'com_banners', '', 1],
['component', 'com_cache', '', 1],
['component', 'com_categories', '', 1],
['component', 'com_checkin', '', 1],
['component', 'com_config', '', 1],
['component', 'com_contact', '', 1],
['component', 'com_content', '', 1],
['component', 'com_contenthistory', '', 1],
['component', 'com_cpanel', '', 1],
['component', 'com_fields', '', 1],
['component', 'com_finder', '', 1],
['component', 'com_guidedtours', '', 1],
['component', 'com_installer', '', 1],
['component', 'com_joomlaupdate', '', 1],
['component', 'com_languages', '', 1],
['component', 'com_login', '', 1],
['component', 'com_mails', '', 1],
['component', 'com_media', '', 1],
['component', 'com_menus', '', 1],
['component', 'com_messages', '', 1],
['component', 'com_modules', '', 1],
['component', 'com_newsfeeds', '', 1],
['component', 'com_plugins', '', 1],
['component', 'com_postinstall', '', 1],
['component', 'com_privacy', '', 1],
['component', 'com_redirect', '', 1],
['component', 'com_scheduler', '', 1],
['component', 'com_tags', '', 1],
['component', 'com_templates', '', 1],
['component', 'com_users', '', 1],
['component', 'com_workflow', '', 1],
['component', 'com_wrapper', '', 1],
// Core file extensions
['file', 'joomla', '', 0],
// Core language extensions - administrator
['language', 'en-GB', '', 1],
// Core language extensions - site
['language', 'en-GB', '', 0],
// Core language extensions - API
['language', 'en-GB', '', 3],
// Core library extensions
['library', 'joomla', '', 0],
['library', 'phpass', '', 0],
// Core module extensions - administrator
['module', 'mod_custom', '', 1],
['module', 'mod_feed', '', 1],
['module', 'mod_frontend', '', 1],
['module', 'mod_guidedtours', '', 1],
['module', 'mod_latest', '', 1],
['module', 'mod_latestactions', '', 1],
['module', 'mod_logged', '', 1],
['module', 'mod_login', '', 1],
['module', 'mod_loginsupport', '', 1],
['module', 'mod_menu', '', 1],
['module', 'mod_messages', '', 1],
['module', 'mod_multilangstatus', '', 1],
['module', 'mod_popular', '', 1],
['module', 'mod_post_installation_messages', '', 1],
['module', 'mod_privacy_dashboard', '', 1],
['module', 'mod_privacy_status', '', 1],
['module', 'mod_quickicon', '', 1],
['module', 'mod_sampledata', '', 1],
['module', 'mod_stats_admin', '', 1],
['module', 'mod_submenu', '', 1],
['module', 'mod_title', '', 1],
['module', 'mod_toolbar', '', 1],
['module', 'mod_user', '', 1],
['module', 'mod_version', '', 1],
// Core module extensions - site
['module', 'mod_articles_archive', '', 0],
['module', 'mod_articles_categories', '', 0],
['module', 'mod_articles_category', '', 0],
['module', 'mod_articles_latest', '', 0],
['module', 'mod_articles_news', '', 0],
['module', 'mod_articles_popular', '', 0],
['module', 'mod_banners', '', 0],
['module', 'mod_breadcrumbs', '', 0],
['module', 'mod_custom', '', 0],
['module', 'mod_feed', '', 0],
['module', 'mod_finder', '', 0],
['module', 'mod_footer', '', 0],
['module', 'mod_languages', '', 0],
['module', 'mod_login', '', 0],
['module', 'mod_menu', '', 0],
['module', 'mod_random_image', '', 0],
['module', 'mod_related_items', '', 0],
['module', 'mod_stats', '', 0],
['module', 'mod_syndicate', '', 0],
['module', 'mod_tags_popular', '', 0],
['module', 'mod_tags_similar', '', 0],
['module', 'mod_users_latest', '', 0],
['module', 'mod_whosonline', '', 0],
['module', 'mod_wrapper', '', 0],
// Core package extensions
['package', 'pkg_en-GB', '', 0],
// Core plugin extensions - actionlog
['plugin', 'joomla', 'actionlog', 0],
// Core plugin extensions - API Authentication
['plugin', 'basic', 'api-authentication', 0],
['plugin', 'token', 'api-authentication', 0],
// Core plugin extensions - authentication
['plugin', 'cookie', 'authentication', 0],
['plugin', 'joomla', 'authentication', 0],
['plugin', 'ldap', 'authentication', 0],
// Core plugin extensions - behaviour
['plugin', 'compat', 'behaviour', 0],
['plugin', 'taggable', 'behaviour', 0],
['plugin', 'versionable', 'behaviour', 0],
// Core plugin extensions - content
['plugin', 'confirmconsent', 'content', 0],
['plugin', 'contact', 'content', 0],
['plugin', 'emailcloak', 'content', 0],
['plugin', 'fields', 'content', 0],
['plugin', 'finder', 'content', 0],
['plugin', 'joomla', 'content', 0],
['plugin', 'loadmodule', 'content', 0],
['plugin', 'pagebreak', 'content', 0],
['plugin', 'pagenavigation', 'content', 0],
['plugin', 'vote', 'content', 0],
// Core plugin extensions - editors
['plugin', 'codemirror', 'editors', 0],
['plugin', 'none', 'editors', 0],
['plugin', 'tinymce', 'editors', 0],
// Core plugin extensions - editors xtd
['plugin', 'article', 'editors-xtd', 0],
['plugin', 'contact', 'editors-xtd', 0],
['plugin', 'fields', 'editors-xtd', 0],
['plugin', 'image', 'editors-xtd', 0],
['plugin', 'menu', 'editors-xtd', 0],
['plugin', 'module', 'editors-xtd', 0],
['plugin', 'pagebreak', 'editors-xtd', 0],
['plugin', 'readmore', 'editors-xtd', 0],
// Core plugin extensions - extension
['plugin', 'joomla', 'extension', 0],
['plugin', 'namespacemap', 'extension', 0],
['plugin', 'finder', 'extension', 0],
// Core plugin extensions - fields
['plugin', 'calendar', 'fields', 0],
['plugin', 'checkboxes', 'fields', 0],
['plugin', 'color', 'fields', 0],
['plugin', 'editor', 'fields', 0],
['plugin', 'imagelist', 'fields', 0],
['plugin', 'integer', 'fields', 0],
['plugin', 'list', 'fields', 0],
['plugin', 'media', 'fields', 0],
['plugin', 'radio', 'fields', 0],
['plugin', 'sql', 'fields', 0],
['plugin', 'subform', 'fields', 0],
['plugin', 'text', 'fields', 0],
['plugin', 'textarea', 'fields', 0],
['plugin', 'url', 'fields', 0],
['plugin', 'user', 'fields', 0],
['plugin', 'usergrouplist', 'fields', 0],
// Core plugin extensions - filesystem
['plugin', 'local', 'filesystem', 0],
// Core plugin extensions - finder
['plugin', 'categories', 'finder', 0],
['plugin', 'contacts', 'finder', 0],
['plugin', 'content', 'finder', 0],
['plugin', 'newsfeeds', 'finder', 0],
['plugin', 'tags', 'finder', 0],
// Core plugin extensions - installer
['plugin', 'folderinstaller', 'installer', 0],
['plugin', 'override', 'installer', 0],
['plugin', 'packageinstaller', 'installer', 0],
['plugin', 'urlinstaller', 'installer', 0],
['plugin', 'webinstaller', 'installer', 0],
// Core plugin extensions - media-action
['plugin', 'crop', 'media-action', 0],
['plugin', 'resize', 'media-action', 0],
['plugin', 'rotate', 'media-action', 0],
// Core plugin extensions - Multi-factor Authentication
['plugin', 'email', 'multifactorauth', 0],
['plugin', 'fixed', 'multifactorauth', 0],
['plugin', 'totp', 'multifactorauth', 0],
['plugin', 'webauthn', 'multifactorauth', 0],
['plugin', 'yubikey', 'multifactorauth', 0],
// Core plugin extensions - privacy
['plugin', 'actionlogs', 'privacy', 0],
['plugin', 'consents', 'privacy', 0],
['plugin', 'contact', 'privacy', 0],
['plugin', 'content', 'privacy', 0],
['plugin', 'message', 'privacy', 0],
['plugin', 'user', 'privacy', 0],
// Core plugin extensions - quick icon
['plugin', 'downloadkey', 'quickicon', 0],
['plugin', 'extensionupdate', 'quickicon', 0],
['plugin', 'joomlaupdate', 'quickicon', 0],
['plugin', 'overridecheck', 'quickicon', 0],
['plugin', 'phpversioncheck', 'quickicon', 0],
['plugin', 'privacycheck', 'quickicon', 0],
['plugin', 'eos', 'quickicon', 0],
// Core plugin extensions - sample data
['plugin', 'blog', 'sampledata', 0],
['plugin', 'multilang', 'sampledata', 0],
// Core plugin extensions - schemaorg
['plugin', 'blogposting', 'schemaorg', 0],
['plugin', 'book', 'schemaorg', 0],
['plugin', 'event', 'schemaorg', 0],
['plugin', 'jobposting', 'schemaorg', 0],
['plugin', 'organization', 'schemaorg', 0],
['plugin', 'person', 'schemaorg', 0],
['plugin', 'recipe', 'schemaorg', 0],
// Core plugin extensions - system
['plugin', 'accessibility', 'system', 0],
['plugin', 'actionlogs', 'system', 0],
['plugin', 'cache', 'system', 0],
['plugin', 'debug', 'system', 0],
['plugin', 'fields', 'system', 0],
['plugin', 'guidedtours', 'system', 0],
['plugin', 'highlight', 'system', 0],
['plugin', 'httpheaders', 'system', 0],
['plugin', 'jooa11y', 'system', 0],
['plugin', 'languagecode', 'system', 0],
['plugin', 'languagefilter', 'system', 0],
['plugin', 'log', 'system', 0],
['plugin', 'logout', 'system', 0],
['plugin', 'privacyconsent', 'system', 0],
['plugin', 'redirect', 'system', 0],
['plugin', 'remember', 'system', 0],
['plugin', 'schedulerunner', 'system', 0],
['plugin', 'schemaorg', 'system', 0],
['plugin', 'sef', 'system', 0],
['plugin', 'shortcut', 'system', 0],
['plugin', 'skipto', 'system', 0],
['plugin', 'stats', 'system', 0],
['plugin', 'tasknotification', 'system', 0],
['plugin', 'webauthn', 'system', 0],
// Core plugin extensions - task scheduler
['plugin', 'checkfiles', 'task', 0],
['plugin', 'deleteactionlogs', 'task', 0],
['plugin', 'globalcheckin', 'task', 0],
['plugin', 'privacyconsent', 'task', 0],
['plugin', 'requests', 'task', 0],
['plugin', 'rotatelogs', 'task', 0],
['plugin', 'sessiongc', 'task', 0],
['plugin', 'sitestatus', 'task', 0],
['plugin', 'updatenotification', 'task', 0],
// Core plugin extensions - user
['plugin', 'contactcreator', 'user', 0],
['plugin', 'joomla', 'user', 0],
['plugin', 'profile', 'user', 0],
['plugin', 'terms', 'user', 0],
['plugin', 'token', 'user', 0],
// Core plugin extensions - webservices
['plugin', 'banners', 'webservices', 0],
['plugin', 'config', 'webservices', 0],
['plugin', 'contact', 'webservices', 0],
['plugin', 'content', 'webservices', 0],
['plugin', 'installer', 'webservices', 0],
['plugin', 'languages', 'webservices', 0],
['plugin', 'media', 'webservices', 0],
['plugin', 'menus', 'webservices', 0],
['plugin', 'messages', 'webservices', 0],
['plugin', 'modules', 'webservices', 0],
['plugin', 'newsfeeds', 'webservices', 0],
['plugin', 'plugins', 'webservices', 0],
['plugin', 'privacy', 'webservices', 0],
['plugin', 'redirect', 'webservices', 0],
['plugin', 'tags', 'webservices', 0],
['plugin', 'templates', 'webservices', 0],
['plugin', 'users', 'webservices', 0],
// Core plugin extensions - workflow
['plugin', 'featuring', 'workflow', 0],
['plugin', 'notification', 'workflow', 0],
['plugin', 'publishing', 'workflow', 0],
// Core template extensions - administrator
['template', 'atum', '', 1],
// Core template extensions - site
['template', 'cassiopeia', '', 0],
];
/**
* Array of core extension IDs.
*
* @var array
* @since 4.0.0
*/
protected static $coreExtensionIds;
/**
* Gets the core extensions.
*
* @return array Array with core extensions.
* Each extension is an array with following format:
* `type`, `element`, `folder`, `client_id`.
*
* @since 3.7.4
*/
public static function getCoreExtensions()
{
return self::$coreExtensions;
}
/**
* Returns an array of core extension IDs.
*
* @return array
*
* @since 4.0.0
* @throws \RuntimeException
*/
public static function getCoreExtensionIds()
{
if (self::$coreExtensionIds !== null) {
return self::$coreExtensionIds;
}
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('extension_id'))
->from($db->quoteName('#__extensions'));
foreach (self::$coreExtensions as $extension) {
$values = $query->bindArray($extension, [ParameterType::STRING, ParameterType::STRING, ParameterType::STRING, ParameterType::INTEGER]);
$query->where(
'(' . $db->quoteName('type') . ' = ' . $values[0] . ' AND ' . $db->quoteName('element') . ' = ' . $values[1]
. ' AND ' . $db->quoteName('folder') . ' = ' . $values[2] . ' AND ' . $db->quoteName('client_id') . ' = ' . $values[3] . ')',
'OR'
);
}
$db->setQuery($query);
self::$coreExtensionIds = $db->loadColumn();
return self::$coreExtensionIds;
}
/**
* Check if an extension is core or not
*
* @param string $type The extension's type.
* @param string $element The extension's element name.
* @param integer $clientId The extension's client ID. Default 0.
* @param string $folder The extension's folder. Default ''.
*
* @return boolean True if core, false if not.
*
* @since 3.7.4
*/
public static function checkIfCoreExtension($type, $element, $clientId = 0, $folder = '')
{
return \in_array([$type, $element, $folder, $clientId], self::$coreExtensions);
}
/**
* Returns an extension record for the given name.
*
* @param string $element The extension element
* @param string $type The extension type
* @param integer|null $clientId The client ID
* @param string|null $folder Plugin folder
*
* @return \stdClass|null The object or null if not found.
*
* @since 4.0.0
* @throws \InvalidArgumentException
*/
public static function getExtensionRecord(string $element, string $type, ?int $clientId = null, ?string $folder = null): ?\stdClass
{
if ($type === 'plugin' && $folder === null) {
throw new \InvalidArgumentException(sprintf('`$folder` is required when `$type` is `plugin` in %s()', __METHOD__));
}
if (\in_array($type, ['module', 'language', 'template'], true) && $clientId === null) {
throw new \InvalidArgumentException(
sprintf('`$clientId` is required when `$type` is `module`, `language` or `template` in %s()', __METHOD__)
);
}
$key = $element . '.' . $type . '.' . $clientId . '.' . $folder;
if (!\array_key_exists($key, self::$loadedExtensions)) {
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->quoteName('#__extensions'))
->where(
[
$db->quoteName('element') . ' = :element',
$db->quoteName('type') . ' = :type',
]
)
->bind(':element', $element)
->bind(':type', $type);
if ($clientId !== null) {
$query->where($db->quoteName('client_id') . ' = :clientId')
->bind(':clientId', $clientId, ParameterType::INTEGER);
}
if ($folder !== null) {
$query->where($db->quoteName('folder') . ' = :folder')
->bind(':folder', $folder);
}
$query->setLimit(1);
$db->setQuery($query);
self::$loadedExtensions[$key] = $db->loadObject();
}
return self::$loadedExtensions[$key];
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Loads extensions.
*
* @since 4.0.0
*/
interface ExtensionManagerInterface
{
/**
* Boots the component with the given name.
*
* @param string $component The component to boot.
*
* @return ComponentInterface
*
* @since 4.0.0
*/
public function bootComponent($component): ComponentInterface;
/**
* Boots the module with the given name.
*
* @param string $module The module to boot
* @param string $applicationName The application name
*
* @return ModuleInterface
*
* @since 4.0.0
*/
public function bootModule($module, $applicationName): ModuleInterface;
/**
* Boots the plugin with the given name and type.
*
* @param string $plugin The plugin name
* @param string $type The type of the plugin
*
* @return PluginInterface
*
* @since 4.0.0
*/
public function bootPlugin($plugin, $type): PluginInterface;
}

View File

@ -0,0 +1,254 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Dispatcher\ModuleDispatcherFactory;
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Helper\HelperFactory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\Exception\ContainerNotFoundException;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Trait for classes which can load extensions
*
* @since 4.0.0
*/
trait ExtensionManagerTrait
{
/**
* Boots the component with the given name.
*
* @param string $component The component to boot.
*
* @return ComponentInterface
*
* @since 4.0.0
*/
public function bootComponent($component): ComponentInterface
{
// Normalize the component name
$component = strtolower($component);
$component = str_starts_with($component, 'com_') ? substr($component, 4) : $component;
// Path to look for services
$path = JPATH_ADMINISTRATOR . '/components/com_' . $component;
return $this->loadExtension(ComponentInterface::class, $component, $path);
}
/**
* Boots the module with the given name.
*
* @param string $module The module to boot
* @param string $applicationName The application name
*
* @return ModuleInterface
*
* @since 4.0.0
*/
public function bootModule($module, $applicationName): ModuleInterface
{
// Normalize the module name
$module = strtolower($module);
$module = str_starts_with($module, 'mod_') ? substr($module, 4) : $module;
// Path to look for services
$path = JPATH_SITE . '/modules/mod_' . $module;
if ($applicationName === 'administrator') {
$path = JPATH_ADMINISTRATOR . '/modules/mod_' . $module;
}
return $this->loadExtension(ModuleInterface::class, $module, $path);
}
/**
* Boots the plugin with the given name and type.
*
* @param string $plugin The plugin name
* @param string $type The type of the plugin
*
* @return PluginInterface
*
* @since 4.0.0
*/
public function bootPlugin($plugin, $type): PluginInterface
{
// Normalize the plugin name
$plugin = strtolower($plugin);
$plugin = str_starts_with($plugin, 'plg_') ? substr($plugin, 4) : $plugin;
// Path to look for services
$path = JPATH_SITE . '/plugins/' . $type . '/' . $plugin;
return $this->loadExtension(PluginInterface::class, $plugin . ':' . $type, $path);
}
/**
* Loads the extension.
*
* @param string $type The extension type
* @param string $extensionName The extension name
* @param string $extensionPath The path of the extension
*
* @return ComponentInterface|ModuleInterface|PluginInterface
*
* @since 4.0.0
*/
private function loadExtension($type, $extensionName, $extensionPath)
{
// Check if the extension is already loaded
if (!empty(ExtensionHelper::$extensions[$type][$extensionName])) {
return ExtensionHelper::$extensions[$type][$extensionName];
}
// The container to get the services from
$container = $this->getContainer()->createChild();
$container->get(DispatcherInterface::class)->dispatch(
'onBeforeExtensionBoot',
AbstractEvent::create(
'onBeforeExtensionBoot',
[
'subject' => $this,
'type' => $type,
'extensionName' => $extensionName,
'container' => $container,
]
)
);
// The path of the loader file
$path = $extensionPath . '/services/provider.php';
if (is_file($path)) {
// Load the file
$provider = require_once $path;
// Check if the extension supports the service provider interface
if ($provider instanceof ServiceProviderInterface) {
$provider->register($container);
}
}
// Fallback to legacy
if (!$container->has($type)) {
switch ($type) {
case ComponentInterface::class:
$container->set($type, new LegacyComponent('com_' . $extensionName));
break;
case ModuleInterface::class:
$container->set($type, new Module(new ModuleDispatcherFactory(''), new HelperFactory('')));
break;
case PluginInterface::class:
list($pluginName, $pluginType) = explode(':', $extensionName);
$container->set($type, $this->loadPluginFromFilesystem($pluginName, $pluginType));
}
}
$container->get(DispatcherInterface::class)->dispatch(
'onAfterExtensionBoot',
AbstractEvent::create(
'onAfterExtensionBoot',
[
'subject' => $this,
'type' => $type,
'extensionName' => $extensionName,
'container' => $container,
]
)
);
$extension = $container->get($type);
if ($extension instanceof BootableExtensionInterface) {
$extension->boot($container);
}
// Cache the extension
ExtensionHelper::$extensions[$type][$extensionName] = $extension;
return $extension;
}
/**
* Creates a CMS plugin from the filesystem.
*
* @param string $plugin The plugin
* @param string $type The type
*
* @return CMSPlugin
*
* @since 4.0.0
*/
private function loadPluginFromFilesystem(string $plugin, string $type)
{
// The dispatcher
$dispatcher = $this->getContainer()->get(DispatcherInterface::class);
// Clear the names
$plugin = preg_replace('/[^A-Z0-9_\.-]/i', '', $plugin);
$type = preg_replace('/[^A-Z0-9_\.-]/i', '', $type);
// The path of the plugin
$path = JPATH_PLUGINS . '/' . $type . '/' . $plugin . '/' . $plugin . '.php';
// Return an empty class when the file doesn't exist
if (!is_file($path)) {
return new DummyPlugin($dispatcher);
}
// Include the file of the plugin
require_once $path;
// Compile the classname
$className = 'Plg' . str_replace('-', '', $type) . $plugin;
// Editors don't follow the convention
if ($type === 'editors') {
$className = 'PlgEditor' . ucfirst($plugin);
}
// Editor buttons don't follow the convention
if ($type === 'editors-xtd') {
$className = 'PlgEditorsXtd' . $plugin;
if (!class_exists($className)) {
$className = 'PlgButton' . $plugin;
}
}
// Return an empty class when the class doesn't exist
if (!class_exists($className)) {
return new DummyPlugin($dispatcher);
}
// Instantiate the plugin
return new $className($dispatcher, (array) PluginHelper::getPlugin($type, $plugin));
}
/**
* Get the DI container.
*
* @return Container
*
* @since 4.0.0
* @throws ContainerNotFoundException May be thrown if the container has not been set.
*/
abstract protected function getContainer();
}

View File

@ -0,0 +1,280 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Categories\CategoryInterface;
use Joomla\CMS\Categories\CategoryServiceInterface;
use Joomla\CMS\Categories\CategoryServiceTrait;
use Joomla\CMS\Categories\SectionNotFoundException;
use Joomla\CMS\Component\Router\RouterInterface;
use Joomla\CMS\Component\Router\RouterLegacy;
use Joomla\CMS\Component\Router\RouterServiceInterface;
use Joomla\CMS\Dispatcher\DispatcherInterface;
use Joomla\CMS\Dispatcher\LegacyComponentDispatcher;
use Joomla\CMS\Fields\FieldsServiceInterface;
use Joomla\CMS\Menu\AbstractMenu;
use Joomla\CMS\MVC\Factory\LegacyFactory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Factory\MVCFactoryServiceInterface;
use Joomla\CMS\Tag\TagServiceInterface;
use Joomla\CMS\Tag\TagServiceTrait;
use Joomla\Filesystem\Path;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to component specific services.
*
* @since 4.0.0
*/
class LegacyComponent implements
ComponentInterface,
MVCFactoryServiceInterface,
CategoryServiceInterface,
FieldsServiceInterface,
RouterServiceInterface,
TagServiceInterface
{
use CategoryServiceTrait, TagServiceTrait {
CategoryServiceTrait::getTableNameForSection insteadof TagServiceTrait;
CategoryServiceTrait::getStateColumnForSection insteadof TagServiceTrait;
}
/**
* @var string
*
* @since 4.0.0
*/
private $component;
/**
* LegacyComponentContainer constructor.
*
* @param string $component The component
*
* @since 4.0.0
*/
public function __construct(string $component)
{
$this->component = str_replace('com_', '', $component);
}
/**
* Returns the dispatcher for the given application.
*
* @param CMSApplicationInterface $application The application
*
* @return DispatcherInterface
*
* @since 4.0.0
*/
public function getDispatcher(CMSApplicationInterface $application): DispatcherInterface
{
return new LegacyComponentDispatcher($application);
}
/**
* Get the factory.
*
* @return MVCFactoryInterface
*
* @since 4.0.0
* @throws \UnexpectedValueException May be thrown if the factory has not been set.
*/
public function getMVCFactory(): MVCFactoryInterface
{
return new LegacyFactory();
}
/**
* Returns the category service.
*
* @param array $options The options
* @param string $section The section
*
* @return CategoryInterface
*
* @since 4.0.0
* @throws SectionNotFoundException
*/
public function getCategory(array $options = [], $section = ''): CategoryInterface
{
$classname = ucfirst($this->component) . ucfirst($section) . 'Categories';
if (!class_exists($classname)) {
$path = JPATH_SITE . '/components/com_' . $this->component . '/helpers/category.php';
if (!is_file($path)) {
throw new SectionNotFoundException();
}
include_once $path;
}
if (!class_exists($classname)) {
throw new SectionNotFoundException();
}
return new $classname($options);
}
/**
* Adds Count Items for Category Manager.
*
* @param \stdClass[] $items The category objects
* @param string $section The section
*
* @return void
*
* @since 4.0.0
* @throws \Exception
*/
public function countItems(array $items, string $section)
{
$helper = $this->loadHelper();
if (!$helper || !\is_callable([$helper, 'countItems'])) {
return;
}
$helper::countItems($items, $section);
}
/**
* Adds Count Items for Tag Manager.
*
* @param \stdClass[] $items The content objects
* @param string $extension The name of the active view.
*
* @return void
*
* @since 4.0.0
* @throws \Exception
*/
public function countTagItems(array $items, string $extension)
{
$helper = $this->loadHelper();
if (!$helper || !\is_callable([$helper, 'countTagItems'])) {
return;
}
$helper::countTagItems($items, $extension);
}
/**
* Returns a valid section for articles. If it is not valid then null
* is returned.
*
* @param string $section The section to get the mapping for
* @param object $item The item
*
* @return string|null The new section
*
* @since 4.0.0
*/
public function validateSection($section, $item = null)
{
$helper = $this->loadHelper();
if (!$helper || !\is_callable([$helper, 'validateSection'])) {
return $section;
}
return $helper::validateSection($section, $item);
}
/**
* Returns valid contexts.
*
* @return array
*
* @since 4.0.0
*/
public function getContexts(): array
{
$helper = $this->loadHelper();
if (!$helper || !\is_callable([$helper, 'getContexts'])) {
return [];
}
return $helper::getContexts();
}
/**
* Returns the router.
*
* @param CMSApplicationInterface $application The application object
* @param AbstractMenu $menu The menu object to work with
*
* @return RouterInterface
*
* @since 4.0.0
*/
public function createRouter(CMSApplicationInterface $application, AbstractMenu $menu): RouterInterface
{
$compname = ucfirst($this->component);
$class = $compname . 'Router';
if (!class_exists($class)) {
// Use the component routing handler if it exists
$path = JPATH_SITE . '/components/com_' . $this->component . '/router.php';
// Use the custom routing handler if it exists
if (is_file($path)) {
require_once $path;
}
}
if (class_exists($class)) {
$reflection = new \ReflectionClass($class);
if (\in_array('Joomla\\CMS\\Component\\Router\\RouterInterface', $reflection->getInterfaceNames())) {
return new $class($application, $menu);
}
}
return new RouterLegacy($compname);
}
/**
* Returns the classname of the legacy helper class. If none is found it returns false.
*
* @return boolean|string
*
* @since 4.0.0
*/
private function loadHelper()
{
$className = ucfirst($this->component) . 'Helper';
if (class_exists($className)) {
return $className;
}
$file = Path::clean(JPATH_ADMINISTRATOR . '/components/com_' . $this->component . '/helpers/' . $this->component . '.php');
if (!is_file($file)) {
return false;
}
\JLoader::register($className, $file);
if (!class_exists($className)) {
return false;
}
return $className;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\MVC\Factory\MVCFactoryServiceInterface;
use Joomla\CMS\MVC\Factory\MVCFactoryServiceTrait;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* MVC Component class.
*
* @since 4.0.0
*/
class MVCComponent extends Component implements MVCFactoryServiceInterface
{
use MVCFactoryServiceTrait;
}

View File

@ -0,0 +1,98 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Dispatcher\DispatcherInterface;
use Joomla\CMS\Dispatcher\ModuleDispatcherFactoryInterface;
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
use Joomla\CMS\Helper\HelperFactoryInterface;
use Joomla\Input\Input;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to module specific services.
*
* @since 4.0.0
*/
class Module implements ModuleInterface, HelperFactoryInterface
{
/**
* The dispatcher factory.
*
* @var ModuleDispatcherFactoryInterface
*
* @since 4.0.0
*/
private $dispatcherFactory;
/**
* The helper factory.
*
* @var HelperFactoryInterface
*
* @since 4.0.0
*/
private $helperFactory;
/**
* Module constructor.
*
* @param ModuleDispatcherFactoryInterface $dispatcherFactory The dispatcher factory
* @param HelperFactoryInterface $helperFactory The helper factory
*
* @since 4.0.0
*/
public function __construct(ModuleDispatcherFactoryInterface $dispatcherFactory, ?HelperFactoryInterface $helperFactory)
{
$this->dispatcherFactory = $dispatcherFactory;
$this->helperFactory = $helperFactory;
}
/**
* Returns the dispatcher for the given application, module and input.
*
* @param \stdClass $module The module
* @param CMSApplicationInterface $application The application
* @param Input $input The input object, defaults to the one in the application
*
* @return DispatcherInterface
*
* @since 4.0.0
*/
public function getDispatcher(\stdClass $module, CMSApplicationInterface $application, Input $input = null): DispatcherInterface
{
$dispatcher = $this->dispatcherFactory->createDispatcher($module, $application, $input);
if ($dispatcher instanceof HelperFactoryAwareInterface) {
$dispatcher->setHelperFactory($this->helperFactory);
}
return $dispatcher;
}
/**
* Returns a helper instance for the given name.
*
* @param string $name The name
* @param array $config The config
*
* @return \stdClass
*
* @since 4.0.0
*/
public function getHelper(string $name, array $config = [])
{
return $this->helperFactory->getHelper($name, $config);
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Dispatcher\DispatcherInterface;
use Joomla\Input\Input;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to module specific services.
*
* @since 4.0.0
*/
interface ModuleInterface
{
/**
* Returns the dispatcher for the given application, module and input.
*
* @param \stdClass $module The module
* @param CMSApplicationInterface $application The application
* @param Input $input The input object, defaults to the one in the application
*
* @return DispatcherInterface
*
* @since 4.0.0
*/
public function getDispatcher(\stdClass $module, CMSApplicationInterface $application, Input $input = null): DispatcherInterface;
}

View File

@ -0,0 +1,33 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension;
use Joomla\Event\DispatcherAwareInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Access to plugin specific services.
*
* @since 4.0.0
*/
interface PluginInterface extends DispatcherAwareInterface
{
/**
* Registers its listeners.
*
* @return void
*
* @since 4.0.0
*/
public function registerListeners();
}

View File

@ -0,0 +1,70 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Categories\CategoryFactoryInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service categories.
*
* @since 4.0.0
*/
class CategoryFactory implements ServiceProviderInterface
{
/**
* The namespace to create the categories from.
*
* @var string
* @since 4.0.0
*/
private $namespace;
/**
* The namespace must be like:
* Joomla\Component\Content
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct($namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
CategoryFactoryInterface::class,
function (Container $container) {
$factory = new \Joomla\CMS\Categories\CategoryFactory($this->namespace);
$factory->setDatabase($container->get(DatabaseInterface::class));
return $factory;
}
);
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service dispatcher factory.
*
* @since 4.0.0
*/
class ComponentDispatcherFactory implements ServiceProviderInterface
{
/**
* The component namespace
*
* @var string
*
* @since 4.0.0
*/
private $namespace;
/**
* ComponentDispatcherFactory constructor.
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
ComponentDispatcherFactoryInterface::class,
function (Container $container) {
return new \Joomla\CMS\Dispatcher\ComponentDispatcherFactory($this->namespace, $container->get(MVCFactoryInterface::class));
}
);
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Helper\HelperFactoryInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service helper factory.
*
* @since 4.0.0
*/
class HelperFactory implements ServiceProviderInterface
{
/**
* The namespace
*
* @var string
*
* @since 4.0.0
*/
private $namespace;
/**
* HelperFactory constructor.
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
HelperFactoryInterface::class,
function (Container $container) {
$factory = new \Joomla\CMS\Helper\HelperFactory($this->namespace);
$factory->setDatabase($container->get(DatabaseInterface::class));
return $factory;
}
);
}
}

View File

@ -0,0 +1,88 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Cache\CacheControllerFactoryInterface;
use Joomla\CMS\Form\FormFactoryInterface;
use Joomla\CMS\Mail\MailerFactoryInterface;
use Joomla\CMS\MVC\Factory\ApiMVCFactory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Router\SiteRouter;
use Joomla\CMS\User\UserFactoryInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:e_JEXECes.SideEffects
/**
* Service provider for the service MVC factory.
*
* @since 4.0.0
*/
class MVCFactory implements ServiceProviderInterface
{
/**
* The extension namespace
*
* @var string
*
* @since 4.0.0
*/
private $namespace;
/**
* MVCFactory constructor.
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
MVCFactoryInterface::class,
function (Container $container) {
if (\Joomla\CMS\Factory::getApplication()->isClient('api')) {
$factory = new ApiMVCFactory($this->namespace);
} else {
$factory = new \Joomla\CMS\MVC\Factory\MVCFactory($this->namespace);
}
$factory->setFormFactory($container->get(FormFactoryInterface::class));
$factory->setDispatcher($container->get(DispatcherInterface::class));
$factory->setDatabase($container->get(DatabaseInterface::class));
$factory->setSiteRouter($container->get(SiteRouter::class));
$factory->setCacheControllerFactory($container->get(CacheControllerFactoryInterface::class));
$factory->setUserFactory($container->get(UserFactoryInterface::class));
$factory->setMailerFactory($container->get(MailerFactoryInterface::class));
return $factory;
}
);
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Dispatcher\ModuleDispatcherFactoryInterface;
use Joomla\CMS\Extension\ModuleInterface;
use Joomla\CMS\Helper\HelperFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service based modules.
*
* @since 4.0.0
*/
class Module implements ServiceProviderInterface
{
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
ModuleInterface::class,
function (Container $container) {
return new \Joomla\CMS\Extension\Module(
$container->get(ModuleDispatcherFactoryInterface::class),
$container->has(HelperFactoryInterface::class) ? $container->get(HelperFactoryInterface::class) : null
);
}
);
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Dispatcher\ModuleDispatcherFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service dispatcher factory.
*
* @since 4.0.0
*/
class ModuleDispatcherFactory implements ServiceProviderInterface
{
/**
* The module namespace
*
* @var string
*
* @since 4.0.0
*/
private $namespace;
/**
* ComponentDispatcherFactory constructor.
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
ModuleDispatcherFactoryInterface::class,
function (Container $container) {
return new \Joomla\CMS\Dispatcher\ModuleDispatcherFactory($this->namespace);
}
);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Extension\Service\Provider;
use Joomla\CMS\Categories\CategoryFactoryInterface;
use Joomla\CMS\Component\Router\RouterFactoryInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Service provider for the service router factory.
*
* @since 4.0.0
*/
class RouterFactory implements ServiceProviderInterface
{
/**
* The module namespace
*
* @var string
*
* @since 4.0.0
*/
private $namespace;
/**
* DispatcherFactory constructor.
*
* @param string $namespace The namespace
*
* @since 4.0.0
*/
public function __construct(string $namespace)
{
$this->namespace = $namespace;
}
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.0.0
*/
public function register(Container $container)
{
$container->set(
RouterFactoryInterface::class,
function (Container $container) {
$categoryFactory = null;
if ($container->has(CategoryFactoryInterface::class)) {
$categoryFactory = $container->get(CategoryFactoryInterface::class);
}
return new \Joomla\CMS\Component\Router\RouterFactory(
$this->namespace,
$categoryFactory,
$container->get(DatabaseInterface::class)
);
}
);
}
}