3

I've replicated the mod_article_category module from Joomla 3.3.3 to only show one article, filtered by id (which you can choose in a dropdown).

My main code:

defined('_JEXEC') or die;
require_once __DIR__ . '/helper.php';
$article = ModArticleHelper::getArticle($params)[0];
require JModuleHelper::getLayoutPath('mod_article', $params->get('layout', 'default'));

And my template code:

<?php defined('_JEXEC') or die;
$show_title = $params->get('show_title',true);
$h = $params->get('h','h3');
$class = htmlspecialchars($params->get('moduleclass_sfx'));
?>
<article class="<?= $class ?>">
    <?php if($show_title){echo "<$h>$article->title</$h>";} ?>
    <?= $article->introtext.$article->fulltext ?>   
</article>

If I use this module to show an article in a module position it works. The problem arises when I have this module multiple times. The shown article is always that of the last added module and all the module-specific params (like showing the title of the article) also only listen to the last added module. The sitewide module settings (like showing the module title) DO change.

Why doesn't the module work when in multiple positions?

FULL CODE (helper.php)

defined('_JEXEC') or die;
$com_path = JPATH_SITE . '/components/com_content/';
require_once $com_path . 'helpers/route.php';
JModelLegacy::addIncludePath($com_path . '/models', 'ContentModel');

abstract class ModArticleHelper{
    public static function getArticle(&$params){
        // Get an instance of the generic articles model
        $articles = JModelLegacy::getInstance('Articles', 'ContentModel', array('ignore_request' => true));

        // Set application parameters in model
        $app = JFactory::getApplication();
        $appParams = $app->getParams();
        $articles->setState('params', $appParams);
        $articles->setState('filter.published', 1);

        // Access filter
        $access = !JComponentHelper::getParams('com_content')->get('show_noauth');
        $authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
        $articles->setState('filter.access', $access);

        // Item ID filter
        $articles->setState('filter.id', $params->get('article_id', array()));

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

        $items = $articles->getItems();

        foreach ($items as &$item){
            $item->slug = $item->id . ':' . $item->alias;
            $item->catslug = $item->catid . ':' . $item->category_alias;

            if ($access || in_array($item->access, $authorised)){
                // We know that user has the privilege to view the article
                $item->link = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug));
            } else {
                $item->link = JRoute::_('index.php?option=com_users&view=login');
            }
        }
        return $items;
    }
}
5
  • I do not see anything specific in your code. Can you share full version to test? Aug 28, 2014 at 11:09
  • @DmitryRekun added full helper code.
    – xaddict
    Aug 28, 2014 at 12:01
  • Well here I also do not see anything suspicious. Actually I need your full zipped version to install it on my test site and see/test what's wrong. Aug 28, 2014 at 12:31
  • Have a look at the full package: inft.ly/34UPBJK
    – xaddict
    Aug 28, 2014 at 13:34
  • @xaddict, you now have the privilege to vote in our current moderator election. Please exercise your new democratic privilege. May 6, 2021 at 4:53

2 Answers 2

2

I redid the whole helper code (in under two minutes) to use native joomla database code instead of component helpers. The full helper.php code is now:

defined('_JEXEC') or die;

$com_path = JPATH_SITE . '/components/com_content/';
//require_once $com_path . 'router.php';
require_once $com_path . 'helpers/route.php';

abstract class ModArticleHelper{

    public static function getArticle(&$params){
        $app = JFactory::getApplication();
        $appParams = $app->getParams();

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $query->select('content.*,c.id as catid,c.alias as category_alias');
        $query->from('#__content as content, #__categories as c');
        $query->where('content.id = '.$params->get('article_id'));
        $query->where('content.state = 1');
        $query->where('content.catid = c.id');
        $db->setQuery($query);
        $items = $db->loadObjectList();

        foreach ($items as &$item){
            $item->slug = $item->id . ':' . $item->alias;
            $item->catslug = $item->catid . ':' . $item->category_alias;
            $item->link = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug));
        }
        return $items;
    }
}

and it works!

1

ContentModelArticles has an internal cache.

ContentModelArticles->getItems() => JModelList->getItems(), line 155

    public function getItems()
    {
    // Get a storage key.
    $store = $this->getStoreId();

    // Try to load the data from internal storage.
    if (isset($this->cache[$store]))
    {
        return $this->cache[$store];
    }

As the cache access is based on the StoreId, you should define a different context for each module. E.g. $articles->set('context', 'mod_mymodule' . $id);

2
  • This should be in my helper file, above '$articles->getItems();' ?
    – xaddict
    Aug 28, 2014 at 13:36
  • I've added "$modid = $module->id" to the main file and call "$articles->set('context', 'mod_article' . $modid)" after passing the variable through and there is no difference (noticeable).
    – xaddict
    Aug 28, 2014 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.