Skip to main content
deleted 4111 characters in body
Source Link

UPDATE

I realised that the solution was not to use the article array provided by Joomla but to create a new one. I created an array of the articles in the category, merged it with the arrays of articles in the subcategories. Then I recreated the pagination and applied the filter to the newly created array. Below is the code with these additions and changes.

use Joomla\CMS\Pagination\Pagination;

// To add subcategories items to the list we need to make a new array of items, 
// because the original one made by the component have already applied pagination and filter

// Make a new items array of our category
$model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
$appParams = JFactory::getApplication()->getParams();
$model->setState('params', $appParams);
$model->setState('filter.category_id', $this->category->id);
$model->setState('filter.published', 1);
$this->items = $model->getItems();
$this->total = count($this->items);
$catItems = $model->getItems();
$catItemsCount = count($this->items);

// Get subcategories items and merge them to category items
if ($this->params->get('show_subcats') != '0')
{
    $sub_categories = $this->children[$this->category->id];
    foreach($sub_categories as $sub_category){
        $subcategory_model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
        $appParams = JFactory::getApplication()->getParams();
        $subcategory_model->setState('params', $appParams);
        $subcategory_model->setState('filter.category_id', $sub_category->id);
        $subcategory_model->setState('filter.published', 1);
        $subcategory_items = $subcategory_model->getItems();
        $this->items = array_merge($this->items, $subcategory_items);
        $this->total = count($this->items);
    }
    // Sort new items by date
    usort($this->items, function ($a, $b) {
        $order_date = ($this->params->get('order_date') == 'published') ? 'publish_up' : $this->params->get('order_date');
        return strtotime($b->{$order_date}) - strtotime($a->{$order_date});
    });
}

// If the filter has been used, make a new array with only matching items
if (strlen($this->escape($this->state->get('list.filter'))) > 0){
    $filteredItems = [];
    foreach($this->items as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            array_push($filteredItems, $item);
        }
    }
    // Get the count of filtered articles from the category only (we need it for the "all" in the limitbox)
    $catItemsCount = 0;
    foreach($catItems as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            $catItemsCount++;
        }
    }
    $this->items = $filteredItems;
    $this->total = count($this->items);
}

// Set limit and limitstart for pagination
$this->pagination->limitstart = ($_GET['start'] == '') ? $this->pagination->limitstart : $_GET['start'];
if ($this->pagination->limit > $this->total){
    $this->pagination->limitstart = 0;
}
    //It's used when is selected "all" in the limitbox
if ($this->pagination->limit == $catItemsCount) {
    $this->pagination->limitstart = 0;
    $this->pagination->limit = 0;
}

// Make a new pagination object
$this->pagination = new Pagination($this->total, $this->pagination->limitstart, $this->pagination->limit);
$limitstart = $this->pagination->limitstart;
$limit = $this->pagination->limit;

//The list is ready to be printed ?>

<ul>
    <?php foreach ($this->items as $i => $article) : ?>
        <?php $this->article = &$article; ?>
        <?php $this->article->counter = $i + 1; ?>
        <?php $max_results = $limitstart + $limit;?>
        <?php // Display only the result of the current page ?>
        <?php if ($this->article->counter > $limitstart && $this->article->counter <= $max_results) : ?>
            <li>
                <?php echo $article->title; ?>
                // or everything you want to show of your articles
            </li>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>

UPDATE

I realised that the solution was not to use the article array provided by Joomla but to create a new one. I created an array of the articles in the category, merged it with the arrays of articles in the subcategories. Then I recreated the pagination and applied the filter to the newly created array. Below is the code with these additions and changes.

use Joomla\CMS\Pagination\Pagination;

// To add subcategories items to the list we need to make a new array of items, 
// because the original one made by the component have already applied pagination and filter

// Make a new items array of our category
$model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
$appParams = JFactory::getApplication()->getParams();
$model->setState('params', $appParams);
$model->setState('filter.category_id', $this->category->id);
$model->setState('filter.published', 1);
$this->items = $model->getItems();
$this->total = count($this->items);
$catItems = $model->getItems();
$catItemsCount = count($this->items);

// Get subcategories items and merge them to category items
if ($this->params->get('show_subcats') != '0')
{
    $sub_categories = $this->children[$this->category->id];
    foreach($sub_categories as $sub_category){
        $subcategory_model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
        $appParams = JFactory::getApplication()->getParams();
        $subcategory_model->setState('params', $appParams);
        $subcategory_model->setState('filter.category_id', $sub_category->id);
        $subcategory_model->setState('filter.published', 1);
        $subcategory_items = $subcategory_model->getItems();
        $this->items = array_merge($this->items, $subcategory_items);
        $this->total = count($this->items);
    }
    // Sort new items by date
    usort($this->items, function ($a, $b) {
        $order_date = ($this->params->get('order_date') == 'published') ? 'publish_up' : $this->params->get('order_date');
        return strtotime($b->{$order_date}) - strtotime($a->{$order_date});
    });
}

// If the filter has been used, make a new array with only matching items
if (strlen($this->escape($this->state->get('list.filter'))) > 0){
    $filteredItems = [];
    foreach($this->items as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            array_push($filteredItems, $item);
        }
    }
    // Get the count of filtered articles from the category only (we need it for the "all" in the limitbox)
    $catItemsCount = 0;
    foreach($catItems as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            $catItemsCount++;
        }
    }
    $this->items = $filteredItems;
    $this->total = count($this->items);
}

// Set limit and limitstart for pagination
$this->pagination->limitstart = ($_GET['start'] == '') ? $this->pagination->limitstart : $_GET['start'];
if ($this->pagination->limit > $this->total){
    $this->pagination->limitstart = 0;
}
    //It's used when is selected "all" in the limitbox
if ($this->pagination->limit == $catItemsCount) {
    $this->pagination->limitstart = 0;
    $this->pagination->limit = 0;
}

// Make a new pagination object
$this->pagination = new Pagination($this->total, $this->pagination->limitstart, $this->pagination->limit);
$limitstart = $this->pagination->limitstart;
$limit = $this->pagination->limit;

//The list is ready to be printed ?>

<ul>
    <?php foreach ($this->items as $i => $article) : ?>
        <?php $this->article = &$article; ?>
        <?php $this->article->counter = $i + 1; ?>
        <?php $max_results = $limitstart + $limit;?>
        <?php // Display only the result of the current page ?>
        <?php if ($this->article->counter > $limitstart && $this->article->counter <= $max_results) : ?>
            <li>
                <?php echo $article->title; ?>
                // or everything you want to show of your articles
            </li>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>

added 4111 characters in body
Source Link

UPDATE

I realised that the solution was not to use the article array provided by Joomla but to create a new one. I created an array of the articles in the category, merged it with the arrays of articles in the subcategories. Then I recreated the pagination and applied the filter to the newly created array. Below is the code with these additions and changes.

use Joomla\CMS\Pagination\Pagination;

// To add subcategories items to the list we need to make a new array of items, 
// because the original one made by the component have already applied pagination and filter

// Make a new items array of our category
$model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
$appParams = JFactory::getApplication()->getParams();
$model->setState('params', $appParams);
$model->setState('filter.category_id', $this->category->id);
$model->setState('filter.published', 1);
$this->items = $model->getItems();
$this->total = count($this->items);
$catItems = $model->getItems();
$catItemsCount = count($this->items);

// Get subcategories items and merge them to category items
if ($this->params->get('show_subcats') != '0')
{
    $sub_categories = $this->children[$this->category->id];
    foreach($sub_categories as $sub_category){
        $subcategory_model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
        $appParams = JFactory::getApplication()->getParams();
        $subcategory_model->setState('params', $appParams);
        $subcategory_model->setState('filter.category_id', $sub_category->id);
        $subcategory_model->setState('filter.published', 1);
        $subcategory_items = $subcategory_model->getItems();
        $this->items = array_merge($this->items, $subcategory_items);
        $this->total = count($this->items);
    }
    // Sort new items by date
    usort($this->items, function ($a, $b) {
        $order_date = ($this->params->get('order_date') == 'published') ? 'publish_up' : $this->params->get('order_date');
        return strtotime($b->{$order_date}) - strtotime($a->{$order_date});
    });
}

// If the filter has been used, make a new array with only matching items
if (strlen($this->escape($this->state->get('list.filter'))) > 0){
    $filteredItems = [];
    foreach($this->items as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            array_push($filteredItems, $item);
        }
    }
    // Get the count of filtered articles from the category only (we need it for the "all" in the limitbox)
    $catItemsCount = 0;
    foreach($catItems as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            $catItemsCount++;
        }
    }
    $this->items = $filteredItems;
    $this->total = count($this->items);
}

// Set limit and limitstart for pagination
$this->pagination->limitstart = ($_GET['start'] == '') ? $this->pagination->limitstart : $_GET['start'];
if ($this->pagination->limit > $this->total){
    $this->pagination->limitstart = 0;
}
    //It's used when is selected "all" in the limitbox
if ($this->pagination->limit == $catItemsCount) {
    $this->pagination->limitstart = 0;
    $this->pagination->limit = 0;
}

// Make a new pagination object
$this->pagination = new Pagination($this->total, $this->pagination->limitstart, $this->pagination->limit);
$limitstart = $this->pagination->limitstart;
$limit = $this->pagination->limit;

//The list is ready to be printed ?>

<ul>
    <?php foreach ($this->items as $i => $article) : ?>
        <?php $this->article = &$article; ?>
        <?php $this->article->counter = $i + 1; ?>
        <?php $max_results = $limitstart + $limit;?>
        <?php // Display only the result of the current page ?>
        <?php if ($this->article->counter > $limitstart && $this->article->counter <= $max_results) : ?>
            <li>
                <?php echo $article->title; ?>
                // or everything you want to show of your articles
            </li>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>

UPDATE

I realised that the solution was not to use the article array provided by Joomla but to create a new one. I created an array of the articles in the category, merged it with the arrays of articles in the subcategories. Then I recreated the pagination and applied the filter to the newly created array. Below is the code with these additions and changes.

use Joomla\CMS\Pagination\Pagination;

// To add subcategories items to the list we need to make a new array of items, 
// because the original one made by the component have already applied pagination and filter

// Make a new items array of our category
$model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
$appParams = JFactory::getApplication()->getParams();
$model->setState('params', $appParams);
$model->setState('filter.category_id', $this->category->id);
$model->setState('filter.published', 1);
$this->items = $model->getItems();
$this->total = count($this->items);
$catItems = $model->getItems();
$catItemsCount = count($this->items);

// Get subcategories items and merge them to category items
if ($this->params->get('show_subcats') != '0')
{
    $sub_categories = $this->children[$this->category->id];
    foreach($sub_categories as $sub_category){
        $subcategory_model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
        $appParams = JFactory::getApplication()->getParams();
        $subcategory_model->setState('params', $appParams);
        $subcategory_model->setState('filter.category_id', $sub_category->id);
        $subcategory_model->setState('filter.published', 1);
        $subcategory_items = $subcategory_model->getItems();
        $this->items = array_merge($this->items, $subcategory_items);
        $this->total = count($this->items);
    }
    // Sort new items by date
    usort($this->items, function ($a, $b) {
        $order_date = ($this->params->get('order_date') == 'published') ? 'publish_up' : $this->params->get('order_date');
        return strtotime($b->{$order_date}) - strtotime($a->{$order_date});
    });
}

// If the filter has been used, make a new array with only matching items
if (strlen($this->escape($this->state->get('list.filter'))) > 0){
    $filteredItems = [];
    foreach($this->items as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            array_push($filteredItems, $item);
        }
    }
    // Get the count of filtered articles from the category only (we need it for the "all" in the limitbox)
    $catItemsCount = 0;
    foreach($catItems as $item){
        $word = strtolower($this->escape($this->state->get('list.filter')));
        if (strpos(strtolower($item->title), $word) !== false){
            $catItemsCount++;
        }
    }
    $this->items = $filteredItems;
    $this->total = count($this->items);
}

// Set limit and limitstart for pagination
$this->pagination->limitstart = ($_GET['start'] == '') ? $this->pagination->limitstart : $_GET['start'];
if ($this->pagination->limit > $this->total){
    $this->pagination->limitstart = 0;
}
    //It's used when is selected "all" in the limitbox
if ($this->pagination->limit == $catItemsCount) {
    $this->pagination->limitstart = 0;
    $this->pagination->limit = 0;
}

// Make a new pagination object
$this->pagination = new Pagination($this->total, $this->pagination->limitstart, $this->pagination->limit);
$limitstart = $this->pagination->limitstart;
$limit = $this->pagination->limit;

//The list is ready to be printed ?>

<ul>
    <?php foreach ($this->items as $i => $article) : ?>
        <?php $this->article = &$article; ?>
        <?php $this->article->counter = $i + 1; ?>
        <?php $max_results = $limitstart + $limit;?>
        <?php // Display only the result of the current page ?>
        <?php if ($this->article->counter > $limitstart && $this->article->counter <= $max_results) : ?>
            <li>
                <?php echo $article->title; ?>
                // or everything you want to show of your articles
            </li>
        <?php endif; ?>
    <?php endforeach; ?>
</ul>

Source Link

Edit category list to show items from a category and its subcategories

I'm trying to modify the Category List of the com_content component via override, so that it shows both the articles of the selected category and its subcategories.

I tried to edit the default_articles.php file (in category folder) adding this code:

if (!empty($this->items) && $this->params->get('show_subcats') != '0')
{
    $sub_categories = $this->children[$this->category->id];
    foreach($sub_categories as $sub_category){
        $subcategory_model = JModelList::getInstance('Articles', 'ContentModel', array('ignore_request'=>true));
        $appParams = JFactory::getApplication()->getParams();
        $subcategory_model->setState('params', $appParams);
        $subcategory_model->setState('filter.category_id', $sub_category->id);
        $subcategory_items = $subcategory_model->getItems();
        $this->items = array_merge($this->items, $subcategory_items);
    }
    //Sort new items by date
    usort($this->items, function ($a, $b) {
        $order_date = ($this->params->get('order_date') == 'published') ? 'publish_up' : $this->params->get('order_date');
        return strtotime($b->{$order_date}) - strtotime($a->{$order_date});
    });
}

But I noticed that it's a wrong idea, because pagination and filter are applied before my editing, and they don't consider my new $this->items array.

I was also thinking of editing the pagination and filtering in the default_articles.php, after my edit of $this->items, but I don't know how to do it and if it's possible. Do you have some advice or alternative solution to make a category and subcategories articles list?