Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions modules/mod_articles_popular/mod_articles_popular.php

This file was deleted.

2 changes: 1 addition & 1 deletion modules/mod_articles_popular/mod_articles_popular.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<description>MOD_POPULAR_XML_DESCRIPTION</description>
<namespace path="src">Joomla\Module\ArticlesPopular</namespace>
<files>
<filename module="mod_articles_popular">mod_articles_popular.php</filename>
<folder module="mod_articles_popular">services</folder>
<folder>src</folder>
<folder>tmpl</folder>
</files>
Expand Down
42 changes: 42 additions & 0 deletions modules/mod_articles_popular/services/provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/**
* @package Joomla.Site
* @subpackage mod_articles_popular
*
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
* @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 popular 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\\ArticlesPopular'));
$container->registerServiceProvider(new HelperFactory('\\Joomla\\Module\\ArticlesPopular\\Site\\Helper'));

$container->registerServiceProvider(new Module());
}
};
51 changes: 51 additions & 0 deletions modules/mod_articles_popular/src/Dispatcher/Dispatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/**
* @package Joomla.Site
* @subpackage mod_articles_popular
*
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace Joomla\Module\ArticlesPopular\Site\Dispatcher;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
use Joomla\CMS\Helper\HelperFactoryAwareInterface;
use Joomla\CMS\Helper\HelperFactoryAwareTrait;
use Joomla\CMS\Language\Text;

// phpcs:disable PSR1.Files.SideEffects
\defined('JPATH_PLATFORM') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
* Dispatcher class for mod_articles_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();

if (!ComponentHelper::getParams('com_content')->get('record_hits', 1)) {
$data['hitsDisabledMessage'] = Text::_('JGLOBAL_RECORD_HITS_DISABLED');
} else {
$data['list'] = $this->getHelperFactory()->getHelper('ArticlesPopularHelper', $data)->getArticles($data['params'], $data['app']);
}

return $data;
}
}
179 changes: 130 additions & 49 deletions modules/mod_articles_popular/src/Helper/ArticlesPopularHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
namespace Joomla\Module\ArticlesPopular\Site\Helper;

use Joomla\CMS\Access\Access;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Cache\CacheControllerFactoryInterface;
use Joomla\CMS\Cache\Controller\OutputController;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Router\Route;
use Joomla\Component\Content\Administrator\Extension\ContentComponent;
use Joomla\Component\Content\Site\Helper\RouteHelper;
use Joomla\Component\Content\Site\Model\ArticlesModel;
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Registry\Registry;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand All @@ -24,78 +31,152 @@
/**
* Helper for mod_articles_popular
*
* @since 1.6
* @since __DEPLOY_VERSION__
*/
abstract class ArticlesPopularHelper
class ArticlesPopularHelper
{
/**
* Get a list of popular articles from the articles model
* The module instance
*
* @param \Joomla\Registry\Registry &$params object holding the models parameters
* @var \stdClass
*
* @return mixed
* @since __DEPLOY_VERSION__
*/
public static function getList(&$params)
protected $module;

/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
*
* @since __DEPLOY_VERSION__
*/
public function __construct($config = [])
{
$this->module = $config['module'];
}

/**
* Retrieve a list of months with archived articles
*
* @param Registry $params The module parameters.
* @param SiteApplication $app The current application.
*
* @return object[]
*
* @since __DEPLOY_VERSION__
*/
public function getArticles(Registry $moduleParams, SiteApplication $app)
{
$app = Factory::getApplication();
$cacheKey = md5(serialize([$moduleParams->toString(), $this->module->module, $this->module->id]));

// Get an instance of the generic articles model
$model = $app->bootComponent('com_content')
->getMVCFactory()->createModel('Articles', 'Site', ['ignore_request' => true]);
/** @var OutputController $cache */
$cache = Factory::getContainer()->get(CacheControllerFactoryInterface::class)
->createCacheController('output', ['defaultgroup' => 'mod_articles_popular']);

// Set application parameters in model
$appParams = $app->getParams();
$model->setState('params', $appParams);
if (!$cache->contains($cacheKey)) {
$mvcContentFactory = $app->bootComponent('com_content')->getMVCFactory();

$model->setState('list.start', 0);
$model->setState('filter.published', ContentComponent::CONDITION_PUBLISHED);
/** @var ArticlesModel $articlesModel */
$articlesModel = $mvcContentFactory->createModel('Articles', 'Site', ['ignore_request' => true]);

// Set the filters based on the module params
$model->setState('list.limit', (int) $params->get('count', 5));
$model->setState('filter.featured', $params->get('show_front', 1) == 1 ? 'show' : 'hide');
// Set application parameters in model
$appParams = $app->getParams();
$articlesModel->setState('params', $appParams);

// This module does not use tags data
$model->setState('load_tags', false);
$articlesModel->setState('list.start', 0);
$articlesModel->setState('filter.published', ContentComponent::CONDITION_PUBLISHED);

// Access filter
$access = !ComponentHelper::getParams('com_content')->get('show_noauth');
$authorised = Access::getAuthorisedViewLevels(Factory::getUser()->get('id'));
$model->setState('filter.access', $access);
// Set the filters based on the module params
$articlesModel->setState('list.limit', (int) $moduleParams->get('count', 5));
$articlesModel->setState('filter.featured', $moduleParams->get('show_front', 1) == 1 ? 'show' : 'hide');

// Category filter
$model->setState('filter.category_id', $params->get('catid', []));
// This module does not use tags data
$articlesModel->setState('load_tags', false);

// Date filter
$date_filtering = $params->get('date_filtering', 'off');
// Access filter
$access = !ComponentHelper::getParams('com_content')->get('show_noauth');
$articlesModel->setState('filter.access', $access);

if ($date_filtering !== 'off') {
$model->setState('filter.date_filtering', $date_filtering);
$model->setState('filter.date_field', $params->get('date_field', 'a.created'));
$model->setState('filter.start_date_range', $params->get('start_date_range', '1000-01-01 00:00:00'));
$model->setState('filter.end_date_range', $params->get('end_date_range', '9999-12-31 23:59:59'));
$model->setState('filter.relative_date', $params->get('relative_date', 30));
}
// Category filter
$articlesModel->setState('filter.category_id', $moduleParams->get('catid', []));

// Filter by language
$model->setState('filter.language', $app->getLanguageFilter());
// Date filter
$date_filtering = $moduleParams->get('date_filtering', 'off');

// Ordering
$model->setState('list.ordering', 'a.hits');
$model->setState('list.direction', 'DESC');
if ($date_filtering !== 'off') {
$articlesModel->setState('filter.date_filtering', $date_filtering);
$articlesModel->setState('filter.date_field', $moduleParams->get('date_field', 'a.created'));
$articlesModel->setState('filter.start_date_range', $moduleParams->get('start_date_range', '1000-01-01 00:00:00'));
$articlesModel->setState('filter.end_date_range', $moduleParams->get('end_date_range', '9999-12-31 23:59:59'));
$articlesModel->setState('filter.relative_date', $moduleParams->get('relative_date', 30));
}

// Filter by language
$articlesModel->setState('filter.language', $app->getLanguageFilter());

// Ordering
$articlesModel->setState('list.ordering', 'a.hits');
$articlesModel->setState('list.direction', 'DESC');

$items = $model->getItems();
// Prepare the module output
$items = [];
$itemParams = new \stdClass();

foreach ($items as &$item) {
$item->slug = $item->id . ':' . $item->alias;
$itemParams->authorised = Access::getAuthorisedViewLevels($app->getIdentity()->get('id'));
$itemParams->access = $access;

if ($access || \in_array($item->access, $authorised)) {
// We know that user has the privilege to view the article
$item->link = Route::_(RouteHelper::getArticleRoute($item->slug, $item->catid, $item->language));
} else {
$item->link = Route::_('index.php?option=com_users&view=login');
foreach ($articlesModel->getItems() as $item) {
$items[] = $this->prepareItem($item, $itemParams);
}

// Cache the output and return
$cache->store($items, $cacheKey);

return $items;
}

return $items;
// Return the cached output
return $cache->get($cacheKey);
}

/**
* Prepare the article before render.
*
* @param object $item The article to prepare
* @param \stdClass $params The model item
*
* @return object
*
* @since __DEPLOY_VERSION__
*/
private function prepareItem($item, $params): object
{
$item->slug = $item->id . ':' . $item->alias;

if ($params->access || \in_array($item->access, $params->authorised)) {
// We know that user has the privilege to view the article
$item->link = Route::_(RouteHelper::getArticleRoute($item->slug, $item->catid, $item->language));
} else {
$item->link = Route::_('index.php?option=com_users&view=login');
}

return $item;
}

/**
* Get a list of popular articles from the articles model
*
* @param \Joomla\Registry\Registry &$params object holding the models parameters
*
* @return mixed
*
* @since __DEPLOY_VERSION__
*
* @deprecated 5.0 Use the none static function getArticles
*/
public static function getList(&$params)
{
return (new self())->getArticles($params, Factory::getApplication());
}
}
5 changes: 4 additions & 1 deletion modules/mod_articles_popular/tmpl/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

defined('_JEXEC') or die;

if (!$list) {
if (!isset($list)) {
if (isset($hitsDisabledMessage)) {
echo $hitsDisabledMessage;
}
return;
}

Expand Down