diff --git a/administrator/language/en-GB/mod_popular.ini b/administrator/language/en-GB/mod_popular.ini
index 3669bb575d9f5..614adfdeb120f 100644
--- a/administrator/language/en-GB/mod_popular.ini
+++ b/administrator/language/en-GB/mod_popular.ini
@@ -11,6 +11,7 @@ MOD_POPULAR_FIELD_VALUE_ADDED_OR_MODIFIED_BY_ME="Added or modified by me"
MOD_POPULAR_FIELD_VALUE_ANYONE="Anyone"
MOD_POPULAR_FIELD_VALUE_NOT_ADDED_OR_MODIFIED_BY_ME="Not added or modified by me"
MOD_POPULAR_ITEMS="Popular Items"
+; The following string is deprecated and will be removed with 7.0
MOD_POPULAR_NO_MATCHING_RESULTS="No Matching Results"
MOD_POPULAR_TITLE="Popular Articles"
MOD_POPULAR_TITLE_1="Top Popular Article"
diff --git a/administrator/modules/mod_popular/mod_popular.php b/administrator/modules/mod_popular/mod_popular.php
deleted file mode 100644
index 1896c3d58aff5..0000000000000
--- a/administrator/modules/mod_popular/mod_popular.php
+++ /dev/null
@@ -1,49 +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\Popular\Administrator\Helper\PopularHelper;
-
-$model = $app->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Administrator', ['ignore_request' => true]);
-$list = PopularHelper::getList($params, $model);
-
-// Get module data.
-if ($params->get('automatic_title', 0)) {
- $module->title = PopularHelper::getTitle($params);
-}
-
-// If recording of hits is disabled.
-if (!ComponentHelper::getParams('com_content')->get('record_hits', 1)) {
- echo LayoutHelper::render('joomla.content.emptystate_module', [
- 'title' => 'JGLOBAL_RECORD_HITS_DISABLED',
- 'icon' => 'icon-minus-circle',
- ]);
-
- return;
-}
-
-// If there are some articles to display.
-if (\count($list)) {
- require ModuleHelper::getLayoutPath('mod_popular', $params->get('layout', 'default'));
-
- return;
-}
-
-// If there are no articles to display, show empty state.
-$app->getLanguage()->load('com_content');
-
-echo LayoutHelper::render('joomla.content.emptystate_module', [
- 'textPrefix' => 'COM_CONTENT',
- 'icon' => 'icon-copy',
- ]);
diff --git a/administrator/modules/mod_popular/mod_popular.xml b/administrator/modules/mod_popular/mod_popular.xml
index 5d1c3e00fcb65..6f937af59d214 100644
--- a/administrator/modules/mod_popular/mod_popular.xml
+++ b/administrator/modules/mod_popular/mod_popular.xml
@@ -11,7 +11,7 @@
MOD_POPULAR_XML_DESCRIPTION
Joomla\Module\Popular
- mod_popular.php
+ services
src
tmpl
diff --git a/administrator/modules/mod_popular/services/provider.php b/administrator/modules/mod_popular/services/provider.php
new file mode 100644
index 0000000000000..6f779e64359e3
--- /dev/null
+++ b/administrator/modules/mod_popular/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\\Popular'));
+ $container->registerServiceProvider(new HelperFactory('\\Joomla\\Module\\Popular\\Administrator\\Helper'));
+
+ $container->registerServiceProvider(new Module());
+ }
+};
diff --git a/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php b/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php
new file mode 100644
index 0000000000000..9cab22828e78b
--- /dev/null
+++ b/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php
@@ -0,0 +1,59 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+namespace Joomla\Module\Popular\Administrator\Dispatcher;
+
+use Joomla\CMS\Component\ComponentHelper;
+use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
+use Joomla\CMS\Helper\HelperFactoryAwareInterface;
+use Joomla\CMS\Helper\HelperFactoryAwareTrait;
+use Joomla\Module\Popular\Administrator\Helper\PopularHelper;
+
+// phpcs:disable PSR1.Files.SideEffects
+\defined('_JEXEC') or die;
+// phpcs:enable PSR1.Files.SideEffects
+
+/**
+ * Dispatcher class for mod_popular
+ *
+ * @since __DEPLOY_VERSION__
+ */
+class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
+{
+ use HelperFactoryAwareTrait;
+
+ /**
+ * Returns the layout data.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected function getLayoutData()
+ {
+ $data = parent::getLayoutData();
+ /** @var PopularHelper $helper */
+ $helper = $this->getHelperFactory()->getHelper('PopularHelper', $data);
+ $articleModel = $this
+ ->getApplication()
+ ->bootComponent('com_content')
+ ->getMVCFactory()
+ ->createModel('Articles', 'Administrator', ['ignore_request' => true]);
+
+ if ($data['params']->get('automatic_title', 0)) {
+ $data['module']->title = $helper->getModuleTitle($data['params']);
+ }
+
+ $data['list'] = $helper->getArticles($data['params'], $articleModel);
+ $data['record_hits'] = (int) ComponentHelper::getParams('com_content')->get('record_hits', 1);
+
+ return $data;
+ }
+}
diff --git a/administrator/modules/mod_popular/src/Helper/PopularHelper.php b/administrator/modules/mod_popular/src/Helper/PopularHelper.php
index aaae5328a09b9..ba52325d7c515 100644
--- a/administrator/modules/mod_popular/src/Helper/PopularHelper.php
+++ b/administrator/modules/mod_popular/src/Helper/PopularHelper.php
@@ -10,8 +10,7 @@
namespace Joomla\Module\Popular\Administrator\Helper;
-use Joomla\CMS\Categories\Categories;
-use Joomla\CMS\Factory;
+use Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Component\Content\Administrator\Model\ArticlesModel;
@@ -26,8 +25,35 @@
*
* @since 1.6
*/
-abstract class PopularHelper
+class PopularHelper
{
+ /**
+ * @var CMSApplicationInterface
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected $app;
+
+ /**
+ * @var Registry
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected $params;
+
+ /**
+ * Helper class constructor
+ *
+ * @param array $config Parameters we are using
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function __construct($config)
+ {
+ $this->app = $config['app'];
+ $this->params = $config['params'];
+ }
+
/**
* Get a list of the most popular articles.
*
@@ -37,10 +63,12 @@ abstract class PopularHelper
* @return mixed An array of articles, or false on error.
*
* @throws \Exception
+ *
+ * @since __DEPLOY_VERSION__
*/
- public static function getList(Registry $params, ArticlesModel $model)
+ public function getArticles(Registry $params, ArticlesModel $model): mixed
{
- $user = Factory::getApplication()->getIdentity();
+ $user = $this->app->getIdentity();
// Set List SELECT
$model->setState('list.select', 'a.id, a.title, a.checked_out, a.checked_out_time, ' .
@@ -102,15 +130,17 @@ public static function getList(Registry $params, ArticlesModel $model)
* @param Registry $params The module parameters.
*
* @return string The alternate title for the module.
+ *
+ * @since __DEPLOY_VERSION__
*/
- public static function getTitle($params)
+ public function getModuleTitle(Registry $params): string
{
$who = $params->get('user_id', 0);
$catid = (int) $params->get('catid', null);
$title = '';
if ($catid) {
- $category = Categories::getInstance('Content')->get($catid);
+ $category = $this->app->bootComponent('com_content')->getCategory()->get($catid);
$title = Text::_('MOD_POPULAR_UNEXISTING');
if ($category) {
diff --git a/administrator/modules/mod_popular/tmpl/default.php b/administrator/modules/mod_popular/tmpl/default.php
index 4949093a8177e..bbec31bf7f940 100644
--- a/administrator/modules/mod_popular/tmpl/default.php
+++ b/administrator/modules/mod_popular/tmpl/default.php
@@ -12,52 +12,66 @@
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
+use Joomla\CMS\Layout\LayoutHelper;
$moduleId = str_replace(' ', '', $module->title) . $module->id;
?>
-
- title; ?>
-
-
- |
- |
- |
-
-
-
-
- $item) : ?>
-
- hits; ?>
- = 10000 ? 'danger' : ($hits >= 1000 ? 'warning' : ($hits >= 100 ? 'info' : 'secondary'))); ?>
-
- |
- checked_out) : ?>
- editor, $item->checked_out_time); ?>
-
- link) : ?>
-
- title, ENT_QUOTES, 'UTF-8'); ?>
-
-
- title, ENT_QUOTES, 'UTF-8'); ?>
-
- |
-
- hits; ?>
- |
-
- publish_up, Text::_('DATE_FORMAT_LC4')); ?>
- |
-
-
+
+ 'JGLOBAL_RECORD_HITS_DISABLED',
+ 'icon' => 'icon-minus-circle',
+ ]); ?>
+
+
+
+ title; ?>
+
+
+ |
+ |
+ |
+
+
+
+ $item) : ?>
+
+ hits; ?>
+ = 10000 ? 'danger' : ($hits >= 1000 ? 'warning' : ($hits >= 100 ? 'info' : 'secondary'))); ?>
+
+ |
+ checked_out) : ?>
+ editor, $item->checked_out_time); ?>
+
+ link) : ?>
+
+ title, ENT_QUOTES, 'UTF-8'); ?>
+
+
+ title, ENT_QUOTES, 'UTF-8'); ?>
+
+ |
+
+ hits; ?>
+ |
+
+ publish_up, Text::_('DATE_FORMAT_LC4')); ?>
+ |
+
+
+
+
+
-
- |
-
- |
-
+ getLanguage()->load('com_content');
+
+ echo LayoutHelper::render('joomla.content.emptystate_module', [
+ 'textPrefix' => 'COM_CONTENT',
+ 'icon' => 'icon-copy',
+ ]);
+ ?>
+
-
-
+