?
avatar boomsya
boomsya
28 Mar 2018

J1.5-J3.8.6

  1. Enable cache plugin
  2. Enable cache in site settings for 15min
  3. clear all cache
  4. create some article (hits = 0)
  5. goto site and click on article and we see: hit = 1 and page with content cached to folder cache/com_content and cache/page
  6. goto main page site and click on article again. hit=1 on display and hit=1 in database table content :((((((

this problem continue from J1.5 for this time. My clients say to me "please hide this counter - it is not working. Google say what users click 200 times on article, but joomla say what it is just 10. Full shit".
ater this i try to calculate multiplier and add to components\com_content\models\article.php in function hit() code:

$table->load($pk);
$hitcounter = rand(4,5);//counter lie 1/(4..5)
$table->hit($pk, $hitcounter);
avatar boomsya boomsya - open - 28 Mar 2018
avatar joomla-cms-bot joomla-cms-bot - change - 28 Mar 2018
Labels Added: ?
avatar joomla-cms-bot joomla-cms-bot - labeled - 28 Mar 2018
avatar franz-wohlkoenig franz-wohlkoenig - change - 28 Mar 2018
Category com_cache
avatar ggppdk
ggppdk - comment - 28 Mar 2018

It is not only a bug (ok it is design choice as explained below)
it is a feature

if you have a large articles DB table and also your website is of high traffic

then you avoid having an update query to a large DB table ... which is more (or less) costly depening on on your DB server version and configuration

and squeezing out most speed and having less CPU cycles is the purpose of the cache plugin

avatar mbabker
mbabker - comment - 28 Mar 2018

This would be expected with the page cache plugin enabled. The plugin checks at the onAfterInitialise event if it can serve a response and will do so if able, which means component code won't run. If you're not using the page cache plugin and just have the global caching enabled, at least with com_content, then the hit counter will be incremented.

If you want to use Joomla's hit counter then you can't use the page cache plugin.

Closing as not a bug but a deliberate system design decision.

avatar mbabker mbabker - change - 28 Mar 2018
Status New Closed
Closed_Date 0000-00-00 00:00:00 2018-03-28 11:38:24
Closed_By mbabker
avatar mbabker mbabker - close - 28 Mar 2018
avatar boomsya
boomsya - comment - 28 Mar 2018

omg. i have no words. facepalm.
If updating 1 row 1 cell id DB it is heavy load work - so i think it is dead end. And it is not a feature! Features works, but not in this case. This is bug.

so why Joomla updates/clean/inserts guests sessions table every time when page loaded? it is not a heavy load work for DB? for what Joomla store guests sessions? many years work with Joomla i dont saw any site which needed to store guests sessions for mythical tasks/using.

avatar mbabker
mbabker - comment - 28 Mar 2018

It's not that the hit counter functionality in and of itself is "heavy load work". The code to do it does not get executed when the page cache plugin is in use and the plugin is able to serve a response from the cache. The hit counter functionality is a component specific thing generally triggered when a component controller's display task is executed. In the case of the page cache plugin serving a cached response, that code will never execute.

avatar brianteeman
brianteeman - comment - 28 Mar 2018

When you think about it then it is obvious.

avatar boomsya
boomsya - comment - 28 Mar 2018

okay, hits cant update on the fly when page cached. Everyone understands this. But DB must know what content views need to increase +1 and after 5-10-40 min cache will expire and page will show fresh counter equal Google analytics. So cache plugin and components needs expand some functional in that way.

So second problem with page cache plugin is tokens in components. Every component store tokens anywhere: in JS, in html forms/tags and when page cached - first using of token is OK, and second,third, ... using from other people will make functionality equal zero useful because it is not his token displayed. This problem needs to expand functionality of cache plugin like this:

$token	= JUtility::getToken();
$search = '#<input type="hidden" name="[0-9a-f]{32}" value="1" />#';
$replacement = '<input type="hidden" name="'.$token.'" value="1" />';
$data = preg_replace( $search, $replacement, $data );

$search = '#var jax_token_var = \'[0-9a-f]{32}\';#';
$replacement = 'var jax_token_var = \''.$token.'\';';
$data = preg_replace( $search, $replacement, $data );

$search = '#var mtoken="[0-9a-f]{32}";#';
$replacement = 'var mtoken="'.$token.'";';
$data = preg_replace( $search, $replacement, $data );

JResponse::setBody($data);

it is not ok. No standarts or solutions to control tokens will makes chaos on the site when cache enabled. Real sadly sutiation globally. I do not want to argue and prove for devs. But global modifications in core needed at now or yesterday :(
sorry if i say this all with emotions. Because this is every time , everyday pain

avatar ggppdk
ggppdk - comment - 28 Mar 2018

so why Joomla updates/clean/inserts guests sessions table every time when page loaded? it is not a heavy load work for DB?

it is nn % less updates (or insert) and further content (articles) table in some websites are really large (compared to the size of a session table that is properly cleaned), updating the articles table becomes more costly, so it makes a considerable difference

If you really need this, create a small Joomla system plugin, examine the HTTP request to get the article or category being viewed, and check if cache plugin is enabled and update the hits column in DB

avatar mbabker
mbabker - comment - 28 Mar 2018

Core can't account for, nor should it even attempt to, replace tokens for every possible use case that every possible extension might use. The code in Cache::getWorkarounds() handles the input field piece just fine, though it should be updated to account for the changes made in #14952.

okay, hits cant update on the fly when page cached. Everyone understands this. But DB must know what content views need to increase +1 and after 5-10-40 min cache will expire and page will show fresh counter equal Google analytics. So cache plugin and components needs expand some functional in that way.

There is just no practical way to do this. The cache plugin sends a response at the onAfterInitialise plugin event if it is able to do so, and exits the application. This means the request will never hit the core router (especially important if SEF URLs are in use to decipher what task in what component actually needs to be executed), or the component code, or anything after that. At that stage in the request, there is not enough data to even attempt to bump the hit increment counter unless SEF routing is disabled (and even that would be a long shot at best because most plugins aren't going to be aware of how components might process the query request variables).

If you are already using a third party analytics service (i.e. Google Analytics), rely on it for your hit counting and ignore the data in Joomla (and disable showing it where possible). In this configuration, the Joomla data can never be correct.

avatar boomsya
boomsya - comment - 28 Mar 2018

mans, thanks what you spend some time for me. I hope in parallel reality Joomla have enough functionality for my tasks :)

avatar SharkyKZ
SharkyKZ - comment - 30 Mar 2018

The hit issue could be solved by saving request data in cached page. Get input in getWorkarounds(), set it in setWorkarounds(). This makes correct request data available for the plugin. @mbabker any thoughts on this? Could this cause any issues?

avatar mbabker
mbabker - comment - 30 Mar 2018

Even if you did that, you run into a new set of problems. You can't make hit counting a plugin running at onAfterInitialise running before the cache plugin for the reasons said above. The cache plugin exits the application, so you couldn't have it run after the cache plugin. com_content specific code shouldn't be put into the cache plugin, so then you run into putting more event triggers into the plugin (and I really feel like it's anti-pattern to have event listeners dispatch events).

avatar SharkyKZ
SharkyKZ - comment - 30 Mar 2018

Hit functionality is not specific to com_content though. It's used across several core components, as well as some 3rd party components. So this could be handled similarly to how Language Filter handles component associations:

// Load component associations.

avatar mbabker
mbabker - comment - 30 Mar 2018

It works in the Language Filter plugin because the associations system creates an arbitrary assumption that a component supporting associations will have a static helper class in a given path. There is no kind of marker for components supporting a hit counter and personally I think it would be majorly overkill to introduce a ComponentHelperHitcounter at /components/com_component/helpers/hitcounter.php just for this functionality.

avatar SharkyKZ
SharkyKZ - comment - 4 Apr 2018

What about the model? Would it be wrong to assume that hit() in any given model is used specifically for this?

avatar mbabker
mbabker - comment - 4 Apr 2018

Lacking an interface defining the method and its purpose, yes. getItem and getItems are pretty common model methods, neither of which have an abstract or interface declaration, and at least in the case of getItem the method signature (and inherently how you define what item you want) is inconsistent as some implementations have a $pk argument and some don't, requiring to set the PK via model state.

Add a Comment

Login with GitHub to post a comment