I was catching up on some of the specifics of the new default theme that shipped with WordPress 4.7, Twenty Seventeen.
When I saw this:
function mychild_sections() {
return 6;
}
add_filter( 'twentyseventeen_front_page_sections', 'mychild_sections' );
We’ve all seen it a thousand times. There’s a filter that just needs a basic value, but since add_filter
requires a callback function, we have to go out of our way to define one.
Annoying. Especially when you want to just return something basic, like an integer.
Have you ever done this before?
add_filter( 'twentyseventeen_front_page_sections', 6 );
No? Liar.
We’ve all done this by accident. Why? Because it’s intuitive! It’s a developer API that makes total sense when passing through simple values. Well, like it or not, WordPress wants a callback function – always.
Alright, so I thought I’d experiment a little with the callStatic magic method in PHP and see if I could create a pattern to expand on the helper functions that are already in WordPress for the sole purpose of being used as filter callbacks.
And if you didn’t know about those yet, well, you’re welcome:
__return_true()
__return_false()
__return_null()
__return_zero()
__return_empty_string()
__return_empty_array()
So, I created a class called Returner
where you can define the type and value you want to return directly in the method name itself:
add_filter( 'twentyseventeen_front_page_sections', 'Returner::int__6' );
Pretty cool!
Alright, time for the caveats.
You can’t use Returner
unless you have PHP 5.3+, and if you have 5.3 then you might as well be using a closure, and if you’re using a closure… well, it’s only like 6 additional characters:
add_filter( 'twentyseventeen_front_page_sections', function() { return 6; } );
In the end, I don’t think my magical class is very practical, but it was still a fun experiment. I especially think the method for doing indexed array output was clever, though real-world application for that is probably pretty rare. Ha! Go figure.
Enjoy.
<?php
/**
* This class is designed to return a basic value by parsing the dynamic
* static method name you call to determine its type and value.
*
* It's useful for filtering values in WordPress quickly without having
* to create a callback function. Think of this as a continuation of the
* callback helpers already in WordPress: __return_true(), et al.
*
* EXAMPLES
* add_filter( 'twentyseventeen_front_page_sections', 'Returner::int__4' );
* add_filter( 'site_icon_sizes', 'Returner::array__256__128__64' );
* add_filter( 'post_class', 'Returner::featured' );
*
* @author Frankie Jarrett
* @license https://www.gnu.org/licenses/gpl-2.0.html GPL-2.0
*/
class Returner {
/**
* Magic value returner method.
*
* @access public
* @static
*
* @param string $name
* @param array $args (unused)
*
* @return mixed
*/
public static function __callStatic( $name, $args ) {
/**
* Return an integer.
*
* Returner::int__6() ==> 6
*/
if ( 0 === strpos( $name, 'int__' ) ) {
return (int) self::value( $name );
}
/**
* Return a negative integer.
*
* Returner::nint__6() ==> -6
*/
if ( 0 === strpos( $name, 'nint__' ) ) {
return (int) self::value( $name ) * -1;
}
/**
* Return a floating point number.
*
* Returner::float__1_234() ==> 1.234
*/
if ( 0 === strpos( $name, 'float__' ) ) {
return (float) str_replace( '_', '.', self::value( $name ) );
}
/**
* Return a negative floating point number.
*
* Returner::nfloat__1_234() ==> -1.234
*/
if ( 0 === strpos( $name, 'nfloat__' ) ) {
return (float) str_replace( '_', '.', self::value( $name ) ) * -1;
}
/**
* Return a one-dimensional indexed array.
*
* Returner::array__foo__bar_baz() ==> [ 'foo', 'bar baz' ]
* Returner::array__1__foo__3() ==> [ 1, 'foo', 3 ]
* Returner::array__foo__FALSE__bar ==> [ 'foo', false, 'baz' ]
*/
if ( 0 === strpos( $name, 'array__' ) ) {
$array = [];
foreach ( explode( '__', self::value( $name ) ) as $value ) {
if ( 'TRUE' === $value ) {
$array[] = true;
continue;
}
if ( 'FALSE' === $value ) {
$array[] = false;
continue;
}
$value = trim( str_replace( '_', ' ', $value ) );
$array[] = is_numeric( $value ) ? (int) $value : $value;
}
return $array;
}
/**
* Return a string.
*
* Returner::foo_bar_baz() ==> 'foo bar baz'
*/
return trim( str_replace( '_', ' ', $name ) );
}
/**
* Return the value portion of a method name.
*
* @access public
* @static
*
* @param string $name
*
* @return string
*/
public static function value( $name ) {
return preg_replace( '/^[a-z]+__/', '', $name );
}
}
Another option would be to make use of
create_function()
: https://gist.github.com/westonruter/35105d1e3d29a9964d9063894add3b40But yeah, +1 closures ASAP! 🙂
Interesting – definitely could use something like this.
My own (rough) experiment (PHP 5.2 supported):
https://gist.github.com/mzalewski/4038b5d350a192624de8d2e01be563eb
Returner::array__foo__FALSE__bar ==> [ ‘foo’, false, ‘baz’ ]
I suppose, that’ bar’ won’t become ‘baz’ here.
Brackets are also missing. Should be:
Returner::array__foo__FALSE__bar() ==> [ ‘foo’, false, ‘bar’ ]