2

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;
    }
}
  • I do not see anything specific in your code. Can you share full version to test? – Dmitry Rekun Aug 28 '14 at 11:09
  • @DmitryRekun added full helper code. – xaddict Aug 28 '14 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. – Dmitry Rekun Aug 28 '14 at 12:31
  • Have a look at the full package: inft.ly/34UPBJK – xaddict Aug 28 '14 at 13:34
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);

  • This should be in my helper file, above '$articles->getItems();' ? – xaddict Aug 28 '14 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 '14 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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