User tests: Successful: Unsuccessful:
Fixes incorrect article counts in frontend category views when articles are expired.
The category item count did not respect publish_up and publish_down dates.
Articles that were expired (Finish Publishing date in the past) were still
counted as published, causing categories to show incorrect item counts and
appear non-empty even when no articles were visible in the frontend.
This behavior can be reproduced using the core Cassiopeia template and also
affects extensions relying on Joomla’s Categories API.
Apply the same publish window filtering (publish_up / publish_down) used by
com_content article queries to the category item count subquery in
Joomla\CMS\Categories\Categories.
Fixes #46614
| Status | New | ⇒ | Pending |
| Category | ⇒ | Libraries |
This is a valid concern thanks for raising it.
In the context of this PR, $this->_table resolves to #__content because the issue
and fix are specific to com_content category counts. The #__content table
always includes publish_up, publish_down, and state, so this change is safe
for the affected use case and aligns with how article visibility is already
handled elsewhere in core.
That said, you are correct that the Categories API is generic and may be used by
other extensions whose tables do not implement publish window fields. A fully
generic solution would require either:
I see this PR as restoring consistency for com_content (fixing a real frontend
bug where expired articles are counted as visible), while a more generic,
extension-agnostic solution could be explored separately if needed.
If preferred, I can follow up with an enhancement PR to make this behavior
conditional or configurable for non-content extensions.
This is a valid concern thanks for raising it.
You're welcome.
Although it's been raised before.
This can be seen in the various issues and PRs that have now been created.
But I'm glad it's been found and it seems to be resolved now.
I have tested this item ✅ successfully on 57f76ab
After applying the patch the article count in a "Category List" view was correct, and articles with an expired "Finish Publishing" date were not counted anymore.
But: I can NOT say anything about the possible mentioned implications in #40172 (comment)
I have tested this item 🔴 unsuccessfully on 57f76ab
To validate the comments from the original PR that this will fail with any component that uses categories but does NOT have published up/down fields I deleted those fields from the #__contact_details table and then created a menu item to list the contacts. As expected this produces an error
Unknown column 'i.publish_up' in 'where clause'
This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/46653.
I understand that this now works for the table of contents.
And that's also what I need in combination with Yootheme.
I understand that it doesn't work with another component that doesn't have those fields in the table.
But why didn't we test it successfully?
Because it works with the table of contents, right?
Otherwise, we now know it works, but not on all components.
How can we get this into the code now to solve the article count issue?
The problem is NOT that this change doesnt work with all components using categories
The problem is that this change BREAKS any component using categories that does not use publish_up/publish_down
That way.
I understand.
That shouldn't be necessary, of course.
Can that function then check whether the field is present or not?
| Labels |
Added:
PR-5.4-dev
|
||
@brianteeman Thank you for catching that critical issue! I've updated the PR to safely handle components without publish date fields.
Added a field existence check before applying publish date filtering:
$tableColumns = $db->getTableColumns($this->_table);
if (isset($tableColumns['publish_up']) && isset($tableColumns['publish_down'])) {
// Only apply date filtering if fields exist
}This addresses your concern from #40172 while maintaining the fix for #46614.
contacts DOES have the publish_up/down fields - I just removed them for testing purposes
Looking at the check, it will work fine for the contacts.
Because they do contain the fields, and the filter can still be activated.
Has this check already been incorporated into the PR for testing purposes?
It's great that it's now being thoroughly investigated and that they're working on a solution.
@brianteeman If you prefer, I could make this even more explicit by:
Option 1: Add a configurable option in $this->_options:
if ($this->_options['published'] == 1) {
$subQuery->where($db->quoteName($db->escape('i.' . $this->_statefield)) . ' = 1');
// Only apply if explicitly enabled via options
if (!empty($this->_options['respectPublishDates'])) {
$tableColumns = $db->getTableColumns($this->_table);
if (isset($tableColumns['publish_up']) && isset($tableColumns['publish_down'])) {
// ... date filtering
}
}
}Option 2: Only apply for com_content specifically:
if ($this->_extension === 'com_content' && $this->_options['published'] == 1) {
$tableColumns = $db->getTableColumns($this->_table);
// ... date filtering
}Which approach would you prefer? The current field-check approach seems safest to me, but I'm open to your guidance.
As the bug appears everywhere I would go for option 1
| Category | Libraries | ⇒ | Front End com_content Libraries |
@brianteeman Implemented Option 1 as suggested! The publish date filtering is now opt-in via a configurable option.
1. Added respectPublishDates option in Categories.php:
false (disabled) to maintain backward compatibility2. Enabled the option in com_content models:
components/com_content/src/Model/CategoriesModel.phpcomponents/com_content/src/Model/CategoryModel.phpBoth models now set $options['respectPublishDates'] = true; when creating Categories instances.
For com_content (Articles):
For other components (Contacts, Tags, etc.):
Safety layer:
publish_up/publish_down fields existThis approach gives each component control while fixing the bug for com_content. Ready for testing!
I've re-enabled the PR on my test site, but where can I find the options to configure this?
I look at the article or category options and don't see anything.
@webmasterab Thanks for testing! There's no UI option to configure - it's enabled automatically in the code for com_content.
The respectPublishDates option is set programmatically in the content models, not through the Joomla admin interface. It works automatically now for articles.
Test Setup:
Expected Result:
Does the article count now correctly exclude expired articles in your test?
I have tested this item ✅ successfully on 0823ad3
I followed the steps.
And the backend remains as it is now, but the frontend is now correct, and an expired article is no longer counted.
I'm glad this has been resolved and I can use this for my Yootheme template to display or hide items based on whether a category has no published articles.
I want to sincerely thank you for creating this solution.
And everyone who helped and contributed to this.
This is how Joomla improves.
I've also mentioned it here: https://yootheme.com/support/question/172237#answer-562033.
Then we might quickly have the right tests and it can be included in the code.
Happy with it.
I don't see a reason for the option and the implementation based on the idea that every tables uses the naming published_up and published_down which might not be the case so the name needs to be get by the table object.
@HLeithner That's annoying.
It's actually a nice addition and a solution to a problem currently in Joomla.
So why wouldn't you want it?
@HLeithner That's annoying.
It's actually a nice addition and a solution to a problem currently in Joomla.
So why wouldn't you want it?
@webmasterab I think @HLeithner was clear in his comment. It is an overhead to use a configuration option to control if the published up and down dates should be used ot not. Furthermore, the category system is not only used for articles by the core but also for other kinds of content, including such of 3rd party extensions. Those might not provide the published up and down at all in their table, or they provide them but with different column names. So a clean implementation should check if these columns exist and if there are column alias. The table object can be used to do that.
@richard67 en @HLeithner My apologies.
I'm not a developer, so I must have misread it.
I'm glad they're looking into solving it, albeit in a different way.
@HLeithner Thank you for the feedback! I understand your concerns about the implementation.
Questions to clarify the best approach:
getColumnAlias() method to get the actual column names? For example:$table = Table::getInstance('Content', 'Joomla\\CMS\\Table\\');
$publishUpColumn = $table->getColumnAlias('publish_up');
$publishDownColumn = $table->getColumnAlias('publish_down');Removing the option: If I remove the respectPublishDates option and make the behavior automatic (with proper column detection), would that be the preferred approach?
Column detection strategy: Should I:
$db->getTableColumns()Proposed alternative approach:
Remove the option entirely and make it work automatically by:
Would this be more in line with what you're suggesting? I want to make sure I implement this correctly rather than adding technical debt.
@richard67 @brianteeman - Your guidance would also be appreciated on the best implementation approach here.
I have tested this item 🔴 unsuccessfully on dd35a3e
Tested this patch
Observation:
Published, but has expired.
Start: 2026-01-30 14:35
Finish: 2026-01-30 14:44
Select to unpublish
@komalm The number in the backend correctly reflects the unpublished article.
The number also applies to the frontend.
I don't know if you've tested that.
In the backend, it's correct that the article is included in the green number.
But it's no longer included in the frontend, which is the intention.
I have tested this item ✅ successfully on dd35a3e
This issue is fixed. I had tested successfully.
@Vineet7875 Thanks
I have tested this item ✅ successfully on dd35a3e
I have tested with 2 articles
Articles that will be published in future and articles that are expired
@tekvishal Thanks
@HLeithner @richard67 @brianteeman
I posted some questions 2 weeks ago about the best implementation approach, but haven't received guidance yet. The PR is getting successful tests from the community, but I want to make sure the architecture is correct before proceeding.
Current status:
Question: Should I:
respectPublishDates option)?getColumnAlias()?I'm happy to refactor based on your preferred architecture pattern. Just need direction on which approach aligns best with Joomla's standards.
The bug is real and affects users - I want to fix it the right way.
Thanks!
Question: Should I:
1. Keep the current opt-in approach (`respectPublishDates` option)?
No.
2. Refactor to use table objects with `getColumnAlias()`?
Yes.
3. Make it fully automatic without the option?
Yes.
@HLeithner Feel free to correct me if I did get something wrong.
| Labels |
Added:
Updates Requested
|
||
Changes implemented and tested locally
What was changed:
respectPublishDates option entirely from all filesTable::getInstance() and getColumnAlias()Files modified:
libraries/src/Categories/Categories.php - Uses table objects to detect and respect column aliasescomponents/com_content/src/Model/CategoriesModel.php - Removed optioncomponents/com_content/src/Model/CategoryModel.php - Removed optionLocal testing results:
Test scenario:
The implementation now uses table objects as requested and works automatically for all components with publish date support.
Ready for review!
@RudraHingu001 Thanks for your work. On a first quick review it looks to me as it does what it should do. However, we get a new issue reported by PHPstan about using the deprecated getInstance method: https://github.com/joomla/joomla-cms/actions/runs/21795999523/job/62885027828?pr=46653
The deprecation message suggests to use the MVC factory instead:
Call to deprecated method getInstance() of class Joomla\CMS\Table\Table:
4.3 will be removed in 6.0
Use the MvcFactory instead
Example: Factory::getApplication()->bootComponent('...')->getMVCFactory()->createTable($name, $prefix, $config);
Unfortunately I'm not an expert on that.
@HLeithner What do you suggest? Can it be implemented in the way suggested by that message? Or would that not work so we have to add an entry to the phpstan-baseline.neon file?
@richard67 @brianteeman @HLeithner
I see there's discussion about this PR potentially conflicting with #44950 and whether it should target 5.4-dev or 6.1-dev.
Current status of my PR:
Questions:
I'm happy to adjust the target branch or coordinate with #44950 as needed. Just let me know the preferred approach!
@RudraHingu001 I didn't looked at the version yet but you are right actually this is not a bugfix it's a feature so should go to 6.1 anyway.
| Title |
|
||||||
| Category | Libraries Front End com_content | ⇒ | Administration Language & Strings Front End com_content Installation Libraries Unit Tests |
| Labels |
Added:
Unit/System Tests
Language Change
PR-6.1-dev
Removed: PR-5.4-dev |
||
| Category | Libraries Front End com_content Administration Language & Strings Installation Unit Tests | ⇒ | Front End com_content Libraries Unit Tests |
@RudraHingu001 I've just rebased your PR to 6.1-dev. Unfortunately your PR shows unrelated changes now. That can happen and would be fixed after the next upmerges (from 5.4-dev to 6.0-dev and then from 6.0-dev to 6.1-dev), which will be done by the release managers. But that will maybe be too late for 6.1.0-beta1. So maybe it is better if you redo your PR for the 6.1-dev branch. Let me know if you have questions or need help. Thanks in advance.
don't worry we will do an upmerge in the next days but the code style issue is strange
| Labels |
Removed:
Language Change
|
||
don't worry we will do an upmerge in the next days but the code style issue is strange
Only strange that it appeared again. My suggestion for the fix was still there, so I've just applied it, and PHPCS should be ok.
What remains are the unrelated changes from @since __DEPLOY_VERSION__ to @since 5.4.3 in diverse PHP files which were caused by the upmerge (and 5.4-dev and this PR being in advance to 6.1-dev with these commits). They should be reverted to @since __DEPLOY_VERSION__ (or the corresponding conflicts need to be resolved after the next upmerge).
Thank you for rebasing this to 6.1-dev and fixing the code style issues!
I understand there are some unrelated @since version conflicts that will be resolved after the upmerge. I'm ready to make any additional changes if needed.
Looking forward to getting this into 6.1.0-beta1!
Thanks for creating this code and solution.
Do I understand correctly that it's available in both 6 and 5?
Do I understand correctly that it's available in both 6 and 5?
@webmasterab This PR is now targeting the 6.1-dev branch. If merged, it will be included in 6.1.x. It is not included in 5.4.x or 6.0.x.
@muhme That's a shame. Then I'll have to start planning how to convert the sites.
It would be great if it came in 5 as well.
no it's not a shame, that's how we agreed to manage joomla versioning. If you like to know more please visit https://semver.org
Move on how we move forward can be found at https://manual.joomla.org/docs/development-strategy/
All checks are passing now!
I see there's one review comment thread that needs to be resolved to unblock merging.
The code style issue has been fixed. Is there anything else I need to address, or can that comment thread be marked as resolved?
Thank you for all your help getting this ready for 6.1-beta1!
I see there's one review comment thread that needs to be resolved to unblock merging.
@RudraHingu001 That was @HLeithner 's review comment about using Table::getInstance. To me it seems that is resolved now. @HLeithner Can you confirm and if it is ok, dismiss your change request?
why all of these uneeded change to unit test files?
@alikon See my comment above:
What remains are the unrelated changes from
@since __DEPLOY_VERSION__to@since 5.4.3in diverse PHP files which were caused by the upmerge (and 5.4-dev and this PR being in advance to 6.1-dev with these commits). They should be reverted to@since __DEPLOY_VERSION__(or the corresponding conflicts need to be resolved after the next upmerge).
| Category | Libraries Front End com_content Unit Tests | ⇒ | Administration Language & Strings Front End com_content Installation Libraries Unit Tests |
| Labels |
Added:
Language Change
|
||
| Category | Libraries Front End com_content Unit Tests Administration Language & Strings Installation | ⇒ | Front End com_content Libraries |
| Labels |
Removed:
Unit/System Tests
Language Change
|
||
I’ve updated the implementation in Categories.php following the review feedback.
Changes made:
$db->getTableColumns($this->_table).publish_up / publish_down) is now applied only when those fields exist.PHPCS issues have also been resolved and CI should now pass.
Please let me know if this aligns with the expected direction or if further adjustments are needed.
PHPCS issues have also been resolved and CI should now pass.
@RudraHingu001 Definitely not, see my latest suggestion and the current state of the CI checks. The problem is that I have to approve the GitHub actions of the CI checks before they run, so you can't see them after you have committed a change until I have approved them to start. The reason might be that you are a new contributor in this repository, or it is because some permission settings in your fork.
Maybe you should adjust your editor (or IDE) so it shows you white space (tabulators and spaces) when editing, that would avoid many code style issues.
I'm not happy with this, we can't knowingly not support a core feature (column aliases) in the core...
Updated the implementation to address the review comments.
getColumnAlias()Please let me know if anything further needs adjustment or if the remaining thread can be resolved.
Hi @HLeithner, @richard67 —
I’ve updated the implementation to address the column alias concern by resolving publish date fields through the MVC table factory and getColumnAlias().
Could you please take another look when you have time and let me know if this aligns with the expected approach, or if further adjustments are needed?
Thanks again for the guidance!
I've implemented the MVC factory approach as discussed:
Changes:
getColumnAlias()Could you please review when you have time? Happy to make any additional adjustments needed.
The 6.1-beta1 deadline is approaching - let me know if there's anything else I should address!
I have tested this item ✅ successfully on 57f76ab
I tested it successfully.
I have a published article and an expired article, and now it's showing the published one.
As expected.
Now that I disable the only article, it disappears, which is what we need.
Thanks for this PR.
Glad we all worked it out together and found a solution.
This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/46653.