Hi.
I need to use $node->build_mode in page.tpl.php to check wether to print some other stuff. I noticed that this works in an odd way when using CCK blocks. Here's how to reproduce the problem:
Install CCK and CCK Blocks on fresh D6. Do not add fields yet. Create a simlpe test page (node). Add this to Garland's page.tpl.php:
<?php print $node->build_mode; ?>
It will print "0" where you added the code when viewing your page. Now add a simple text field to your page node-type and enable "Provide block for this field". Go to admin/build/block and place your block somwhere. Go back to your page and it will now print "cck_blocks" where you added the line.
Currently I'm using this as a workaround:
<?php if ($node->build_mode === 0 || $node->build_mode == 'cck_blocks') { some code } ?>
Any ideas why this is happening?
Comments
Comment #1
einkahumor commentedI should probably add that this happens even if the newly created field is empty.
Comment #2
damien_vancouver commentedHi Einkahumor,
This part of the cck_blocks code is from before my time with the module, but I did some investigation and it looks like cck_blocks is properly using build_mode like it's intended. The reason you are seeing it as 0 sometimes is because core uses 0 for BUILD_MODE_NORMAL. See http://lists.drupal.org/pipermail/development/2009-May/032955.html for a discussion of why this is not a good thing.. the main reason being that an empty string in PHP will also evaluate to 0 if you use "==" rather than "===" for your comparisons.
In hindsight, BUILD_MODE_NORMAL should have been defined as a string or something that doesn't == 0. Most contrib modules use a string for their build modes, and you declare which ones you're going to assign in hook_content_build_modes(). Cck blocks only defines one build mode, cck_blocks:
This hook comes from contrib CCK in Drupal 6, and is not documented anywhere that I can really find other than here in some of the Display Suite community docs: http://drupal.org/node/697320#hook_content_build_modes
In any case though, it appears CCK blocks is using it correctly. I'm not sure why your $node object in Garland is showing you the build_mode of the cck_block. I would explore what else is in that $node object (maybe enable devel module and dpm($node); where you are doing your printing) and see if you can figure out why it's not what you're expecting to find. You may have to dig deeper into how Garland theme is providing $variables['node'] to your page.tpl.php, or find a different way to do what you are trying to do (ie. branch your logic off something other than $node->build_mode if that property will always show the last block built, which is likely what's happening I think).
I've set this to closed (works as designed) for now, but feel free to reopen if you can spot something cck_blocks is doing incorrectly or can identify a bug we can fix on this end.
Comment #3
einkahumor commentedHi Damien. Thank you very much for your quick reply.
Do you mean that $node->build_mode is supposed to print "cck_blocks" in page.tpl.php? I thought $node was supposed to only be available in page.tpl.php if you were on a node page and then only for that specific node.
Using
<?php if ($node->build_mode === 0 || $node->build_mode == 'cck_blocks') { some code } ?>I'm printing a bunch of other stuff dependent on other logic. All that stuff is printed correctly and works great. Using dsm($node) (in page.tpl.php) I can see nothing wrong except that build_mode is "cck_blocks" where it should be 0.I know that 0 is normal build mode, that's why I'm using "===". This does not only happen in Garland, I just used Garland and a fresh Drupal install to check if this was possibly caused by some other modules I was using in my Dev environment for my current project. For that project I'm using a Zen 2.1 sub-theme and the exact same thing happens there.
If I'm viewing /node/1 I should definitely see 0 for $node->build_mode in page.tpl.php, right?
Thanks btw for this awesome module, I love using it with node reference.
Comment #4
damien_vancouver commentedYes, I think that is supposed to be what happens.. cck_blocks only runs when outputting its block and it builds the node view in the cck_blocks build mode so that you can set the display settings differently for how a field shows in a cck_block vs. in the main content region. I'm no expert on this unfortunately, I would guess that you are just seeing the last $node that Drupal processed in page.tpl.php. If the last block that was built was a cck_blocks block, then that is maybe why build_mode == 'cck_blocks' is what is left behind.
$node itself in page.tpl.php can be set/overridden using your theme (or the base theme's) theme_preprocess_page I think. Each of your theme_preprocess functions gets a $variables passed in as an array, and then each element in that array gets set as a $variable in the template. (e.g. $variables['node'] becomes $node in page.tpl.php).
Zen's page.tpl.php says this about $node:
So that to me sort of sounds like it's saying that is "whatever $node object is lying around associated with this page". Looking at the cck_bloocks source, I'm guessing the culprit is one of these three lines, though looking at those functions in the API I don't see any of them setting a build_mode, but they do call child functions:
I don't see why any of those functions would be changing $node, but why don't you try the following two hacks to see if one of them fixes things for you. We should try setting that $node to a copy of $node that isn't the main one being used. (the downside to this is it's inefficient.. if this fixes it for you we should try and figure out how to not make it happen rather than use this approach).
So, try changing line 72 ($node = menu_get_object()) to:
That should give you a totally separate $node from the one going through the theme system.. so then it would stand to reason it would no longer have a $build_mode == 'cck_blocks'. But anyway, I'm not really sure what cck_blocks could do differently to avoid that, while still having its own build mode. Is there some other logic you could use to determine you are on a node view page? Like checking the path, or maybe doing a $node = menu_get_object() of your own and looking at that $node?
Just some ideas.. let me know what happens when you try that node_load trick!
Comment #5
einkahumor commentedThanks for the tips. Changing the code on line 71 like you said changes $node->build_mode back to === 0. I also tried putting $node = menu_get_object() in front of my build mode logic but that changed nothing.
I could probably find some other way to determine if I should output my code but nothing comes immediately to mind and my aforementioned workaround in the op works for now anyway. I just don't think I should have to work around it but it's not like I have a better solution up my sleeve.
I guess this confirms that cck_blocks does break &node->build_mode in page.tpl.php and that this is a bug, unless it's caused by something in core or cck. Unfortunately I have no idea how to fix that but you should probably not close this issue until it's fixed.
Setting priority to minor since people are not very likely to come across this problem.
Thank you very much for your help.