[wp-hackers] Avoiding Side-effects in Filters & Actions

Mike Schinkel mikeschinkel at newclarity.net
Thu Apr 2 17:10:28 GMT 2009


"Peter Westwood" <peter.westwood at ftwr.co.uk> wrote;
> I'm not sure where you want the context or what type of 
> context you want but you can use the is_ template tags 
> with plugin code not just themes. Things like is_tag(), 
> is_ page() etc

Yeah, I already use those when I need them. But they are not very granular and sometimes granularity is essential. There are many examples and but let's start with one, maybe there is a canonical approach to this that I've not discovered yet.

First example is a need to get a page's identity in code. The first use-case is a client wants "messaging" modules on their site where a "placement" is defined for a given time period by the page on which is it located and the location on the page (i.e. "products-page_bottom-right".)  To implement this I wrote a generic "messaging" plugin that took the "page name" from context and a hard-coded location on the page and did a database lookup for the current messaging module.  The problem was I wasn't able to come up with a consistent way to identify the page name other than sniffing the URL and creating a function I used that did an ugly "if-then" construct.

One of the reasons that page names are difficult is that some pages represent a record in wp_posts whereas others represent a query (all posts for April 2009, all posts tagged with "London", all posts in the "News" category, etc.), others represent an author, others an attachment, others a search page, and so on. And worse, some plugins define their own context but don't have a standard best-practice way to expose that content (i.e. a gallery plugin might have current image and an calendar events plugin might have current event.) There is no one place you can go (that I am aware of) to get the "page id" that is known to be unique and that is reasonably non-cryptic except the URL which itself doesn't always specific the type of page without more information.

Another aspect is the content on the part of the page. For example, I might have a page that has a criteria based list of posts that has widgets that also contain list of posts. There's no concrete way to say "In this part of the page add *this* to the WHERE clause on on this other part of the page do not." Instead you have to search for artifacts to test, and often those artifacts don't behave as you first assume causing bugs that aren't traced down until after you've deployed for the client.

On some sites there was also the need to establish "sections" for analytic tracking. While this is somewhat subjective and site specific, in many ways it follows the if-else  statement in template-loader (note these are *not* the same as the corresponding is_*() function because the if-else also tests for a valid template):

404
search
taxonomy
home
attachment
single
page
category
tag
author
data
archive
comments_popup
paged_template
template_index

In addition to these, the paged_template could be subdivided to include sections based on pages with no parent (i.e. top level menu items.)  And these sections would need to  be overridable, probably with a filter.

Now maybe my most recent project pushed WordPress harder people push WordPress and that I ran into these "edge cases" far more often than others?  Whatever the case, I had to write lots of if-then statements with a lot of trial and error to "map" URLs to "pages names" and to "inspect" various global variables and call various functions, all of which time to discover and time to figure out it it was really appropriate. This logic is being performed in core, but I don't have direct access to it. I'd be happy to send my 600 line "mapper" file from my most recent project to any individual that wants to see more concretely what I mean.

So what would I propose? I could start building a WP_Context singleton class with a goal of having it become the object to inspect when you need the current context in WordPress. I'd start with the methods get_page_id() and get_section_id() and evolve it as needed. I can do this on my own however I would occasionally need access in core to setting its values where I currently don't have access, for example in template-loader.php. And if it became robust enough and generally useful, you could role it into core.  Would that work?

-Mike Schinkel
Custom Wordpress Plugins
http://mikeschinkel.com/custom-wordpress-plugins



More information about the wp-hackers mailing list