CMS Made Simple Core


[#11552] Core::StylesheetPostRender hook run twice

Created By: Mathieu Muths (airelibre) (airelibre)
Date Submitted: Tue Aug 29 09:36:26 -0400 2017

Assigned To:
CMSMS Version:
Severity: Minor
Resolution: Fixed
State: Closed
Core::StylesheetPostRender hook run twice
Detailed Description:

I'm trying to make the CSSPreprocessor module work in cmsms but even if
the "do_hook" function is called only once, the "add_hook"line 215 in
class.HookManager.php is called, and the foreach at the end loops 2 times.

It worked fine before this modification:

The hook is done in {cms_stylesheet} line 269, and the CSSPreprocessor modules
adds the hook in its constructor



Date: 2017-08-29 18:48
Posted By: Robert Campbell (calguy1000)

The HookManager also sends events.  Sending events is done by adding another
hook handler with a closure.
So because 'StylesheetPostRender' is an event there will always be at least one

Your adding a hook creates a second one.
Date: 2017-08-29 19:27
Posted By: Robert Campbell (calguy1000)

do_hook is being called twice.    Once for each stylesheet, before they are
The bug  is not in the Hookmanager it is in cms_stylesheet

Date: 2017-08-29 19:30
Posted By: Robert Campbell (calguy1000)

Actually,   in my test the hook is called twice legitimately because two css
files are generated.
Date: 2017-08-30 04:30
Posted By: Mathieu Muths (airelibre) (airelibre)

Thanks for testing.

In my case, I've 2 stylesheets in the DesignManager but I only generate 1 .css
file / 1 <link> tag (which is OK)

If I look at cms_stylesheet, the do_hook is called just before the file is
written in /tmp/cache, and after all the stylesheets have been combined - not
before the combination

So in my case, do_hook is called once, but class.HookManager.php  :: do_hook 
the "add_hook" line 215 is executed which makes the foreach line 234 run twice

I'll make more tests to better undersrtand the logic and see where and if this
is a bug
Date: 2017-08-30 04:55
Posted By: Mathieu Muths (airelibre) (airelibre)

I going deeper - The problem is not that the foreach is run twice, but that the
core event handler seems to not return the CSS content passed in params

I continue
Date: 2017-08-30 05:27
Posted By: Mathieu Muths (airelibre) (airelibre)

I think I got it

\Events::SendEvent does not return any value, but the foreach uses
call_user_func_array with a return value.

In fact, in my case :
1. the SendEvent is run with the correct content params
2. it does not return a value
3. the null return value is affected to $value which is then given to the next
hook, and this causes the problem (the css is not given in params)

So, if the aim of the hook (like events) is to handle passed-by-reference
variables only, I would suggest removing the return value of call_user_func in :

foreach( self::$_hooks[$name]->handlers as $obj ) {
                if( !is_array( $value ) ) $value = [ $value ];
                if( empty($value) ) {
                } else {

Or use do_hook_accumulate in {cms_stylesheet} ?
Date: 2017-09-08 12:50
Posted By: Robert Campbell (calguy1000)

This I fixed.
the closure that sends the events now returns the input parameters.

Updated: 2018-03-10 09:48
state: Open => Closed

Updated: 2017-09-23 10:52
resolution_id: 9 => 7

Updated: 2017-08-29 18:48
resolution_id: => 9