diff --git a/administrator/modules/mod_latest/mod_latest.php b/administrator/modules/mod_latest/mod_latest.php
deleted file mode 100644
index 09f9f0b132a8b..0000000000000
--- a/administrator/modules/mod_latest/mod_latest.php
+++ /dev/null
@@ -1,39 +0,0 @@
-
- * @license GNU General Public License version 2 or later; see LICENSE.txt
- */
-
-\defined('_JEXEC') or die;
-
-use Joomla\CMS\Component\ComponentHelper;
-use Joomla\CMS\Helper\ModuleHelper;
-use Joomla\CMS\Layout\LayoutHelper;
-use Joomla\Module\Latest\Administrator\Helper\LatestHelper;
-
-$model = $app->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Administrator', ['ignore_request' => true]);
-$list = LatestHelper::getList($params, $model);
-$workflow_enabled = ComponentHelper::getParams('com_content')->get('workflow_enabled');
-
-if ($workflow_enabled) {
- $app->getLanguage()->load('com_workflow');
-}
-
-if ($params->get('automatic_title', 0)) {
- $module->title = LatestHelper::getTitle($params);
-}
-
-if (\count($list)) {
- require ModuleHelper::getLayoutPath('mod_latest', $params->get('layout', 'default'));
-} else {
- $app->getLanguage()->load('com_content');
-
- echo LayoutHelper::render('joomla.content.emptystate_module', [
- 'textPrefix' => 'COM_CONTENT',
- 'icon' => 'icon-copy',
- ]);
-}
diff --git a/administrator/modules/mod_latest/mod_latest.xml b/administrator/modules/mod_latest/mod_latest.xml
index 0062cca771aab..9452f3b0892ae 100644
--- a/administrator/modules/mod_latest/mod_latest.xml
+++ b/administrator/modules/mod_latest/mod_latest.xml
@@ -11,7 +11,7 @@
MOD_LATEST_XML_DESCRIPTION
Joomla\Module\Latest
- mod_latest.php
+ services
src
tmpl
diff --git a/administrator/modules/mod_latest/services/provider.php b/administrator/modules/mod_latest/services/provider.php
new file mode 100644
index 0000000000000..116e7aebffdd7
--- /dev/null
+++ b/administrator/modules/mod_latest/services/provider.php
@@ -0,0 +1,41 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+\defined('_JEXEC') or die;
+
+use Joomla\CMS\Extension\Service\Provider\HelperFactory;
+use Joomla\CMS\Extension\Service\Provider\Module;
+use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory;
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+
+/**
+ * The latest articles module service provider.
+ *
+ * @since __DEPLOY_VERSION__
+ */
+return new class () implements ServiceProviderInterface {
+ /**
+ * Registers the service provider with a DI container.
+ *
+ * @param Container $container The DI container.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function register(Container $container)
+ {
+ $container->registerServiceProvider(new ModuleDispatcherFactory('\\Joomla\\Module\\Latest'));
+ $container->registerServiceProvider(new HelperFactory('\\Joomla\\Module\\Latest\\Administrator\\Helper'));
+
+ $container->registerServiceProvider(new Module());
+ }
+};
diff --git a/administrator/modules/mod_latest/src/Dispatcher/Dispatcher.php b/administrator/modules/mod_latest/src/Dispatcher/Dispatcher.php
new file mode 100644
index 0000000000000..bf0f1aa97b35d
--- /dev/null
+++ b/administrator/modules/mod_latest/src/Dispatcher/Dispatcher.php
@@ -0,0 +1,110 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+namespace Joomla\Module\Latest\Administrator\Dispatcher;
+
+use Joomla\CMS\Component\ComponentHelper;
+use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
+use Joomla\CMS\Helper\HelperFactoryAwareInterface;
+use Joomla\CMS\Helper\HelperFactoryAwareTrait;
+use Joomla\CMS\Helper\ModuleHelper;
+use Joomla\CMS\Layout\LayoutHelper;
+
+// phpcs:disable PSR1.Files.SideEffects
+\defined('_JEXEC') or die;
+// phpcs:enable PSR1.Files.SideEffects
+
+/**
+ * Dispatcher class for mod_latest
+ *
+ * @since __DEPLOY_VERSION__
+ */
+class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
+{
+ use HelperFactoryAwareTrait;
+
+ /**
+ * Runs the dispatcher.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION_
+ */
+ public function dispatch()
+ {
+ $this->loadLanguage();
+
+ $displayData = $this->getLayoutData();
+
+ // Stop when display data is false
+ if ($displayData === false) {
+ return;
+ }
+
+ // Execute the layout without the module context
+ $loader = static function (array $displayData) {
+ // If $displayData doesn't exist in extracted data, unset the variable.
+ if (!\array_key_exists('displayData', $displayData)) {
+ extract($displayData);
+ unset($displayData);
+ } else {
+ extract($displayData);
+ }
+
+ /**
+ * Extracted variables
+ * -----------------
+ * @var \stdClass $module
+ * @var Registry $params
+ */
+
+ if (\count($list)) {
+ require ModuleHelper::getLayoutPath('mod_latest', $params->get('layout', 'default'));
+ } else {
+ $app->getLanguage()->load('com_content');
+
+ echo LayoutHelper::render('joomla.content.emptystate_module', [
+ 'textPrefix' => 'COM_CONTENT',
+ 'icon' => 'icon-copy',
+ ]);
+ }
+ // End of extracted variables
+ };
+
+ $loader($displayData);
+ }
+
+ /**
+ * Returns the layout data.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION_
+ */
+ protected function getLayoutData()
+ {
+ $data = parent::getLayoutData();
+ $helper = $this->getHelperFactory()->getHelper('LatestHelper');
+
+ $model = $data['app']->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Administrator', ['ignore_request' => true]);
+ $data['list'] = $helper->getArticles($data['params'], $model, $data['app']);
+ $data['workflow_enabled'] = ComponentHelper::getParams('com_content')->get('workflow_enabled');
+
+ if ($data['workflow_enabled']) {
+ $data['app']->getLanguage()->load('com_workflow');
+ }
+
+ if ($data['params']->get('automatic_title', 0)) {
+ $data['module']->title = $helper->getModuleTitle($data['params'], $data['app']);
+ }
+
+ return $data;
+ }
+}
diff --git a/administrator/modules/mod_latest/src/Helper/LatestHelper.php b/administrator/modules/mod_latest/src/Helper/LatestHelper.php
index afab1bb8a8a20..1491861b06559 100644
--- a/administrator/modules/mod_latest/src/Helper/LatestHelper.php
+++ b/administrator/modules/mod_latest/src/Helper/LatestHelper.php
@@ -10,7 +10,7 @@
namespace Joomla\Module\Latest\Administrator\Helper;
-use Joomla\CMS\Categories\Categories;
+use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
@@ -26,19 +26,22 @@
*
* @since 1.5
*/
-abstract class LatestHelper
+class LatestHelper
{
/**
* Get a list of articles.
*
- * @param Registry $params The module parameters.
- * @param ArticlesModel $model The model.
+ * @param Registry $params The module parameters.
+ * @param ArticlesModel $model The model.
+ * @param CMSApplicationInterface $app The application instance.
*
* @return mixed An array of articles, or false on error.
+ *
+ * @since __DEPLOY_VERSION__
*/
- public static function getList(Registry $params, ArticlesModel $model)
+ public function getArticles(Registry $params, ArticlesModel $model, CMSApplicationInterface $app): mixed
{
- $user = Factory::getUser();
+ $user = $app->getIdentity();
// Set List SELECT
$model->setState('list.select', 'a.id, a.title, a.checked_out, a.checked_out_time, a.modified,' .
@@ -107,11 +110,14 @@ public static function getList(Registry $params, ArticlesModel $model)
/**
* Get the alternate title for the module.
*
- * @param \Joomla\Registry\Registry $params The module parameters.
+ * @param Registry $params The module parameters.
+ * @param CMSApplicationInterface $app The application instance.
*
* @return string The alternate title for the module.
+ *
+ * @since __DEPLOY_VERSION__
*/
- public static function getTitle($params)
+ public function getModuleTitle(Registry $params, CMSApplicationInterface $app): string
{
$who = $params->get('user_id', 0);
$catid = (int) $params->get('catid', null);
@@ -119,7 +125,7 @@ public static function getTitle($params)
$title = '';
if ($catid) {
- $category = Categories::getInstance('Content')->get($catid);
+ $category = $app->bootComponent('com_content')->getCategory()->get($catid);
$title = Text::_('MOD_POPULAR_UNEXISTING');
if ($category) {
@@ -133,4 +139,41 @@ public static function getTitle($params)
$title
);
}
+
+ /**
+ * Get a list of articles.
+ *
+ * @param Registry $params The module parameters.
+ * @param ArticlesModel $model The model.
+ *
+ * @return mixed An array of articles, or false on error.
+ *
+ * @deprecated __DEPLOY_VERSION__ will be removed in 7.0
+ * Use the non-static method getArticles
+ * Example: Factory::getApplication()->bootModule('mod_latest', 'administrator')
+ * ->getHelper('LatestHelper')
+ * ->getArticles($params, $model, Factory::getApplication())
+ */
+ public static function getList(Registry $params, ArticlesModel $model)
+ {
+ return (new self())->getArticles($params, $model, Factory::getApplication());
+ }
+
+ /**
+ * Get the alternate title for the module.
+ *
+ * @param Registry $params The module parameters.
+ *
+ * @return string The alternate title for the module.
+ *
+ * @deprecated __DEPLOY_VERSION__ will be removed in 7.0
+ * Use the non-static method getModuleTitle
+ * Example: Factory::getApplication()->bootModule('mod_latest', 'administrator')
+ * ->getHelper('LatestHelper')
+ * ->getModuleTitle($params, Factory::getApplication())
+ */
+ public static function getTitle($params)
+ {
+ return (new self())->getModuleTitle($params, Factory::getApplication());
+ }
}