This is just some test code. What it does is remove devels use of phptemplate_preprocess since it should not be used inside modules.

Instead, it creates a custom function of "devel_preprocess" and it puts it at the very end of the list. This enables it to monitor *all* template logs. Not just the ones set from modules.

It's a dirty hack but it works. If the direction looks good then I hope someone can clean it up. I'm not familiar enough with all the hooks to know where it should be placed. For now you have to manually click the "clear cache" link to have the registry rebuilt.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dvessel’s picture

Here's another dirty hack job. I saw your notes on trying to catch theme functions not associated with templates.

It doesn't do anything but intercept and run all theme functions through "devel_catch_theme_function()".

It contains the patch I just posted before also.

dvessel’s picture

I was informed that HOOK_exit would be the best place for this. Unfortunately, I don't have the time to learn how it works + add the UI to turn it on/off.

This would be great for themers, especially the hack to intercept all the theme function so it can display which are being used for a page.

moshe weitzman@drupal.org’s picture

we can't alter the theme registry on every request (and at the end of each request?). hook_exit does not sound right to me. furthermore, will this pass in template suggestions like Views2 will do where you pass in an array of template names that are searched in order?

dvessel’s picture

Yeah, I'm not certain. Is there somewhere it can run after a form submission? Have it trigger a new function with that registry rebuild code and while clearing the cache.

And I don't know how Views2 works. This is all it does..

Here's a partial entry for the "page" hook inside the registry that gets used when theme('page') is invoked. The rendering is done with a .tpl.php file so it contains preprocess functions that can supply template suggestions. Regular "functions" will never run these.

  ...
  ["preprocess functions"]=>
  array(5) {
    [0]=>
    string(24) "template_preprocess_page"
    [1]=>
    string(29) "phptemplate_engine_preprocess"
/////////////////////////////////////////////////////////////////
// devel registers this. Anything after it, it's not aware of. //
    [2]=>
    string(22) "phptemplate_preprocess"
/////////////////////////////////////////////////////////////////
    [3]=>
    string(27) "phptemplate_preprocess_page"
  }

So, if a theme registers more preprocess functions that supply more template suggestions, Devel will not be aware of them since _theme_build_registry() will add them after the engine.

The patch changes it to this..

  ...
  ["preprocess functions"]=>
  array(5) {
    [0]=>
    string(24) "template_preprocess_page"
    [1]=>
    string(29) "phptemplate_engine_preprocess"
    [2]=>
    string(22) "phptemplate_preprocess_page"
///////////////////////////////////////////////////
// Force as last preprocessor. This way it knows //
// about the final state of all variables.       //
    [3]=>
    string(27) "devel_preprocess"
///////////////////////////////////////////////////
  }

The second patch completely replaces the function that's normally run and only affect theme functions not rendered through templates. This has nothing to do with the original issue I brought up.

Original entry for theme_comment_block..

["comment_block"]=>
array(5) {
  ["arguments"]=>
  array(0) {
  }
  ["type"]=>
  string(6) "module"
  ["theme path"]=>
  string(15) "modules/comment"
  ["function"]=>
  string(19) "theme_comment_block"
  ["preprocess functions"]=>
  array(0) {
  }
}

And after the patch, we can intercept it and do whatever..

["comment_block"]=>
array(6) {
  ["arguments"]=>
  array(0) {
  }
//////////////////////////////
// Swap for devel pointers. //
  ["type"]=>
  string(6) "module"
  ["theme path"]=>
  string(23) "sites/all/modules/devel"
//- call to theme('comment_block') runs this instead..
  ["function"]=>
  string(26) "devel_catch_theme_function"
//////////////////////////////
  ["preprocess functions"]=>
  array(0) {
  }
//////////////////////////////////////////
// Save original information to be used //
// inside devel_catch_theme_function(). //
  ["devel"]=>
  array(5) {
    ["arguments"]=>
    array(0) {
    }
    ["type"]=>
    string(6) "module"
    ["theme path"]=>
    string(15) "modules/comment"
    ["function"]=>
    string(19) "theme_comment_block"
    ["preprocess functions"]=>
    array(0) {
    }
  }
//////////////////////////////////////////
}

Sorry if this is obvious to you. Just trying to be clear.

moshe weitzman@drupal.org’s picture

i am understanding better now ... the catch function is quite clever. it is is a bit more intrusive than devel usually gets (intercepting all theme calls) but maybe it is harmless. i don't want code in here that would be bad in a production context. this is meant to be used on live sites too. maybe others can comment here.

dvessel’s picture

I don't think it would be harmful. Just need to ensure that the registry gets cleared when devel is disabled - if it doesn't already.

But imagine if All the theme functions used on a page could be listed in a block. With some jQuery, click a link and highlight all the elements that are using that function. Click another link to go to api.drupal.org. Would make theming so much more understandable.

moshe weitzman@drupal.org’s picture

both good suggestions. this is getting very interesting. i will fiddle and commit.

merlinofchaos’s picture

My suggestion, btw, is in hook_exit, to load the theme registry; check a setting in it to see if devel has already modified it; if so, leave it be.

If not, go through and modify every theme to pass through devel, and write the registry back.

Whenever modules are enabled/disabled, the theme registry is automatically cleared, so you don't need to worry about that.

moshe weitzman@drupal.org’s picture

Title: reserve phptemplate_preprocessor for themes and theme engines. » Link the template log items to their corresponding divs in page body

this has been committed. i'd really appreciate some jquery person to add some code that turns each template in template log into a hyperlink. upon clicking, the corresponding div in the page body is highlighted.

dvessel’s picture

Status: Needs work » Needs review
FileSize
16.94 KB

This patch goes a lot further by intercepting all themeable functions. It knows about all the template files considered for a loaded page and the active one in use. This also works with wildcard functions, list of preprocess functions and variables.

It no longer adds a preprocessor since it's no longer needed. There's tons of code duplicated from theme() and that was the only way I found it to work.

I tried to minimize the clutter. It will not repeat each hook. Instead it's displayed once and the relevant data under it. It filters or aggregates all the meta info that were run for every iteration for a hook.

All that's needed is some jQuery to do a sibling selector which shouldn't be difficult.

dvessel’s picture

FileSize
117.17 KB

And a preview. :)

dvessel’s picture

Small css correction.

dvessel’s picture

FileSize
101.01 KB

A few more tweaks and bug fixes.. a preview.

dvessel’s picture

FileSize
18.81 KB

Wildcard functions now work. Tested with Merlin's wildcard patch test files. Noticed some timer code in there so I added that in. It only tests theme functions. Anything else will not be counted.

It now knows if template suggestions actually exist or if they were just suggestions.

moshe weitzman’s picture

what would be lose if we refuse to keep a copy of all of theme()? i don't think i can stomach that in devel.module .. thankd for the screenshots. very helpful. soon you will need to write boxes and arrows on them so we know what each item means.

dvessel’s picture

Status: Needs review » Needs work

Yeah, it is a bit too much. Of course I realize now that it's not needed. I don't think we'll loose anything important. I forgot about debug_backtrace() that can help gather some data. At first I saw how it could work, got excited and just went in that direction. :) No big deal, I consider it another learning exercise.

But what do you think of the output? I'd like to recreate that format. Having a HUGE list would be hard to navigate and understand.

With the current output, I was thinking of having a link from the theme function names to trigger jQuery to highlight every dom element using that function. The same goes for the preprocessor functions and actual template files.

I'll work on it a bit slower this time. Maybe within the week.

dvessel’s picture

Oo, it just occurred to me. It may be possible to generate hierarchy of all the theme functions with debug_traceback(). Would be super useful on visualize and getting a mental map of how the page was generated.

Maybe in another revision.

moshe weitzman’s picture

i think thats the right idea for a UI. It would be annoying though to have template log at bottom of page and then all links just keep popping you to the top. so maybe we have a single template log link on the page and when clicked it shows a hidden div at top that has the template log along with the links which highlight content. hope that makes sense.

dvessel’s picture

Moshe, there is something pretty big we would loose. The ability to push the markers into the dom for templated functions. Since their rendering is done way down inside theme(), there's no way to push anything before it renders. Everything else is doable.

dvessel’s picture

Doh, I think that can be worked around also. Need to coax the global $theme_engine inside theme() to point to devel and back. A tiny bit of code to catch the output by pointing the render function inside devel, injecting the dom marker then output as usual. Hope that makes sense. This is a lot of trickery but I'll look into it further.

moshe weitzman’s picture

the template log would still output in same place in the HTML. it would just be hidden and when exposed, so css would move it to a comfortable spot.

dvessel’s picture

I'm talking about all the empty div markers sprinkled all over the dom so it can be used with Jquery. Not the template log.

Templated functions run a very different course making them hard to push in the markers.

http://api.drupal.org/api/function/theme/6

dvessel’s picture

FileSize
21.09 KB

Here's a very, very rough patch to get jQuery to select the DOM from clicking on a log entry. I haven't touched jQuery in a while and I'm not so great with it to begin with.

As for the registry and the theme() function. Only a tiny bit is copied over. What it does now is create a duplicate for each entry in the registry. The original points to devel_catch_theme_function but then theme() is called again from the catch function but it points to the duplicate entry with the original data. So, in a way it bounces back between the two.

That part works well and I'll post something a bit cleaner without jQuery. Hopefully someone can jump on that.

dvessel’s picture

FileSize
110.74 KB

Click on the 'toggle' link and the log slides down from the top..

dvessel’s picture

FileSize
110.45 KB

Click one of the entries, the log hides and highlights the DOM..

It kinda works. I think the DOM markers need to be placed at two points so it can reliable select between two ends.

moshe weitzman’s picture

Steven's field spotter module has some jquery and UI which highlights certain DOM elements. would be good to copy that. see http://drupal.org/project/field_spotter

dvessel’s picture

Yeah, I'll look into that. Looks very simple. I love it!

moshe weitzman@drupal.org’s picture

dvessel - any chance you can get back to this? would be sweet.

dvessel’s picture

Sorry Moshe, I've been busy. I'll get back to this ASAP.

moshe weitzman’s picture

@dvessel - i think we can also clean up how we inject our logging function into the theme registry. we have an alter operation now during registry building.

moshe weitzman’s picture

Title: Link the template log items to their corresponding divs in page body » Informational popup for all theme functions on the page
Assigned: Unassigned » moshe weitzman
Category: bug » feature
Status: Needs work » Active

I've pushed this much farther and checked it all into HEAD. We now have fancy hover on every themeable element on the page. I also put all the variables and so on into the Drupal javascript settings framework so the hover is going to be very information rich. jjeff is helping with the design of the popup right now. I'll share some screenshots when this is a bit more polished. Beware, great stuff is coming soon.

moshe weitzman’s picture

Component: Code » devel_themer
Status: Active » Fixed

this is kicking much ass. i'll make screencast when it is ready for all. meanwhile, this issue can close.

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.