This question is purely hypothetical. I use WordPress a lot and know the filter structure from an implementation point of view. I'm now wondering what's the best way to implement such a structure (not the way WordPress uses, but the best way).
I will give a short overview of what the WordPress filter structure is. After that, I'll list my requirements and thoughts. At last, I'll ask some questions.
WordPress' filter structure
WordPress sends nearly every data through a filter function before it outputs the data to the browser. The WordPress Codex gives information in the Plugin API and the Filter Reference.
For a plugin developer, it's quite easy to add a filter:
- Create the PHP function that filters the data.
- Hook to the filter in WordPress, by calling
add_filter()
- Put your PHP function in a plugin file, and activate it.
Let's look at these steps in some more detail:
- A filter function is a PHP function that takes one parameter, the input, and returns the output. It should not
echo
orprint
anything. The
add_filter
function (reference) looks like:add_filter ( 'hook_name', 'your_filter', [priority], [accepted_args] );
hook_name
is the action hook at which the filter should be called.
your_filter
is the name of your filter function.
priority
gives the, well, the priority of the filter (default: 10), where lower numbers are more important.
accepted_arguments
tells WordPress the filter function will take more parameters, but let's leave that out here, it's not one of my requirements.- I don't have to explain this step, I think.
Requirements
I'd like to know how to implement a filter structure like WordPress has and for the sake of an actual answerable question, I have made up a hypothetical case with some requirements.
My case is a forum, in which I have several cases in which I'd want to use filters for the content, like:
- A linkify filter to make bare URLs into nice, working hyperlinks
- A smiley filter to replace ASCII smileys like ':D' into an image
(sorry for the imgur abuse)
I think the advantages of using filters for this would be:
- Code clarity
- Filters can be easily reused
- Making it easy to implement that a user can switch a filter on and off
- Easy implementation of additional filters in the future
My thoughts
I imagine WordPress keeps a multidimensional array like $filters[$hook][$filter]
. Here is $hook
the name of the hook when the filter has to be called and $filter
an array of the filter settings, basically those that were passed to the add_filter()
function. When an action hook point is reached, WordPress can iterate through the $filters[$current_hook]
array and execute every filter.
Questions
Is this the best way to include a filter system with the requirements I listed? If so, why? If not, why not; and what would be a better system and why?
As I said I want users to be able to switch filters on and off.
I thought of adding a
enabled_filters
column to the user table in the database, which would be a bitmask of the enabled filters. That would mean every filter would have a unique identifier, but more important that there aren't very much filters possible. So this wouldn't be the way to go.I also thought of adding a table
enabled_filters
with columnsuserId
,filterName
andenabled
, to set the filters on and off with a new row. With using the filter name in every row, this would cost some data space on much users and filters, so a better but similar idea would be adding a tablefilters
withid
andfilterName
, and changing thefilterName
column of theenabled_filters
table into afilterId
column. This would also allow an additional field in thefilters
table,allow_disable
, to disable the disabling of the filter.Is this second approach a good one, or are there better options? Key requirement is that I don't want to have to modify the base system when adding a filter.
WordPress wants programmers to not print anything in a filter function, but return a new string. That means you'll have a variable
$return
in your filter function, to which you append new data all the time with$return .= '...';
. Usingecho
orprint()
could be easier for programmers, also to make it easier to port existing code (which uses print functions) to a filter function. The filter system could use theob_*
functions to capture the printed data instead of sending it to the browser. Would this be a good way to implement filters? Are there any disadvantages, like speed?The last question is about when to use filters, and when not. It seems clear to me that the listed cases (linkify and smileys) are cases where filters are well-used. For things like signatures or avatars, to stick with the forum, it's different. I've tried to figure out why it feels different, and think it's because that would limit the use of a filter to one place.
For example, avatars and profile overview filters could only be used next to a post. One of the nice things of a filter is that you can add the same filter function to a different action hook, so that you can pass both the post and the signature content through the linkify filter. Am I right here?
Is it true that one shouldn't use filters for avatars, profile overviews and signatures? What can be said about general rules when and when not to use a filter? If I were to write documentation on my system for third-party developers, what should I write down on this topic?