Blocks - Chicken or Egg? Package or Root?

Permalink 2 users found helpful
Which comes first when loading block resources? It appears, in most cases, that it's the package which takes precedence. This means you can't override [most of] a package's block resources for customization.

I started off wanting to do something quite simple. I wanted to customize the calendar block, so I copied the entire bock from the calendar package to the root "blocks" directory. That doesn't work. The block's controller is loaded from the package directory. There seems to be no way around this (without modifying core files).

Then I decided I would try something more simple – modifying the view, so I edited the view-related files. In the calendar add-on, these are view.php, view_week.php, view_month.php, and view_agenda.php. The latter three are actually included from the main view.php via the inc() function. My changes were not taking effect, so I investigated and learned that the inc() function (actually, the getBlockPath() function called from the inc() function) gives the package precedence and loads the files from there. So I changed the inc() call to a regular include. That worked...well, sorta. The month and 5-week views were working, but the agenda view was not, so I investigated.

The agenda view makes an AJAX call to "tools/events_service.php" inside the block's directory to retrieve some JSON data. C5 would not use the overridden tools file in the root blocks directory but again gave priority to the package and loaded it from there. HOWEVER, that tools file loads the calendar block with a call like this...

Loader::block('calendar');


That call attempts to load the block controller from the ROOT block directory; but since the controller had previously been loaded from the package's directory, it resulted in a "Fatal Error: Cannot redeclare class CalendarBlockController." (The AJAX call doesn't perform any sanity check on the returned data, so it just failed silently, and this took some time to sort out.)

At any rate, I don't know what the intended behavior is, but it seems that overriding a view certainly shouldn't cause a tools/AJAX error.

Additionally, it would be nice to be able to override package blocks. Numerous places in the C5 codebase always look to the package first, so maybe we're not supposed to be able to do that. If so, I'd be curious to know why, but more importantly, to know what the proper approach is for modifying package blocks (and what we should or shouldn't be able to modify).

Comments/discussion welcome,

-Steve

Shotster
 
synlag replied on at Permalink Reply
synlag
yeah, thx steve.
this should somewhere nailed down to the package recommendations. I think it's an issue to refund if a package can't be overriden correctly.

-Ron
andrew replied on at Permalink Reply
andrew
We are trying to fix the areas where the package is looked to first. That will include the BlockView::inc() function. Generally, most simple blocks that are packaged up will work by simply copying their view layers into the root blocks/ directory. But it is true that BlockView::inc() will cause problems and not load items from the correct place (should they exist there.)

In general, order of priority should go like this.

1. Is there something in the local overrides? Use it.
2. Is the thing part of a package? Use it in the package's directory.
3. Look in the root.

We've already fixed certain library, model and element calls where this was the case (and it will be released soon) and we'll add this issue to that list as well
Shotster replied on at Permalink Reply
Shotster
Thanks very much for responding and addressing these issues, Andrew, but I'm still a bit confused by your reply. I'm not sure what you mean by "the local overrides" in item 1. I thought that meant the root blocks folder, but then you mention the root in item 3, and that indicates that packages will always be looked at first (and thus a root block will never be able to override it). Or did you mean "core" for number 3?

Please clarify. Thanks.

-Steve
andrew replied on at Permalink Reply
andrew
Hah yeah, I should be clearer.

1. Local overrides = root folder, the folders that come with concrete5 and are always empty at first.
2. Any folders in the package's folder.
3. The core concrete5 folder (concrete/models, concrete/blocks, etc...)

That should be the order of precedence. This is the case for most thing when you're dealing with the core, but when things are packaged we still have some cleanup to do in this regard.
Shotster replied on at Permalink Reply
Shotster
Great, thanks! The controller() function in concrete/libraries/loader.php is of course an important one to change, but I guess you're aware of that. Anyway, looking forward to the update.

-Steve
Shotster replied on at Permalink Reply
Shotster
Post not relevant to blocks, so it was moved here...

http://www.concrete5.org/index.php?cID=72496...

-Steve
Shotster replied on at Permalink Reply
Shotster
Post not relevant to blocks, so it was moved here...

http://www.concrete5.org/index.php?cID=72496...

-Steve
ScottC replied on at Permalink Reply
ScottC
a call to urlhelper getToolsUrl will have a package specific method call(2nd arg there) and you get a link that passes through the dispatcher and everything will work there in a package specific manner, which is good for any reasonably complex package if the tool's functionality needs to be centralizied, i've personally found in that case(by design) that block stuff should be block'd and anything reasonably global should sit over in the tools folder.