Experiments in WordPress routing 05

Theme, headers and footers.

PHP 5.2 compatibility

Until now I’ve stuck to PHP 5.2 syntax for this experiments but that enlarges the code base too much; the klein52 library is PHP 5.2 compatible in any case and I will use, from now on, PHP 5.3+ syntax in my code.
Should I use this approach for a distribution plugin I’d fall back to PHP 5.2.

Match any route

From previous experiments I know I can let WordPress handle the request should a route not match the requested path.
I’d like to find out now if I can access the current theme template and functions while handling the request.
A look at the filter calls output tells me the after_setup_theme hook has fired at this point Filters and actions called before do_parse_request which means that the theme functions.php file has been included and functions like get_header and get_footer should work.
The code below, when called in the context of the Twenty Fifteen theme, will in fact behave properly.

/**
 * Plugin Name: theAverageDev Routes
 * Plugin URI: http://theAverageDev.com
 * Description: Routing for WordPress
 * Version: 1.0
 * Author: theAverageDev
 * Author URI: http://theAverageDev.com
 * License: GPL 2.0
 */

require 'vendor/autoload_52.php';

/**
 * Support methods
 */
function _dispatch() {
    $found = dispatch( null, null, null, true );
    if ( $found ) {
        die( $found );
    }
}

/**
 * Parse request
 */
add_filter( 'do_parse_request', 'tad_routes_do_parse_request', 1, 3 );
function tad_routes_do_parse_request( $continue, WP $wp, $extra_query_vars ) {

    respond( '/hello/[a:name]', function ( $request ) {
        get_header();
        ?>
        <div id="primary" class="content-area">
            <main id="main" class="site-main" role="main">
                <article class="hentry">
                    <header class="entry-header">
                        <h2 class="entry-title">Hi <?= $request->name ?></h2></header>
                    <div class="entry-content">
                        <p>Lorem ipsum dolor sit amet</p>
                    </div>
                </article>
            </main>
        </div>
        <?php
        get_footer();
    } );

    dispatch_or_continue();

    return $continue;
}

Once the markup is aligned to what the theme uses the route output will be able to call in WordPress specific theme functions.
This is a big selling point for this solution: had I to completely re-invent the wheel on this front it would be a game stopper. Hi route output

WordPress templating system requires functions like get_header and get_footer to be called in each view template and that’s how the template inheritance problem is solved.
The klein52 library inherits the same behaviour the klein.php library implements and allows the definition of catch-all routes that will match any path.
This allows, keeping the result the same, to call the header and footer functions in those routes and have them output before and after each content area.

/**
 * Plugin Name: theAverageDev Routes
 * Plugin URI: http://theAverageDev.com
 * Description: Routing for WordPress
 * Version: 1.0
 * Author: theAverageDev
 * Author URI: http://theAverageDev.com
 * License: GPL 2.0
 */

require 'vendor/autoload_52.php';

/**
 * Support methods
 */
function _dispatch() {
    $found = dispatch( null, null, null, true );
    if ( $found ) {
        die( $found );
    }
}

/**
 * Parse request
 */
add_filter( 'do_parse_request', 'tad_routes_do_parse_request', 1, 3 );
function tad_routes_do_parse_request( $continue, WP $wp, $extra_query_vars ) {
    respond( '*', function () {
        get_header();
    } );

    respond( '/hello/[a:name]', function ( $request ) {
        ?>
        <div id="primary" class="content-area">
            <main id="main" class="site-main" role="main">
                <article class="hentry">
                    <header class="entry-header">
                        <h2 class="entry-title">Hi <?= $request->name ?></h2></header>
                    <div class="entry-content">
                        <p>Lorem ipsum dolor sit amet</p>
                    </div>
                </article>
            </main>
        </div>
        <?php
    } );

    respond( '*', function () {
        get_footer();
    } );

    dispatch_or_continue();

    return $continue;
}

The problem with this approach is that the * route will always match and the markup contained in the header and footer will always be loaded even if no defined routes match the requested path.
WordPress will make sure the header and footer are loaded only once in the page flow so using catch-all routes to load the header and the footer will compromise following markup should no matching routes be found.
In short terms this means the approach is fine if WordPress is never going to handle requests but will probably break, according to the used theme, in a different case.
This post code is on on GitHub.

Next

I will test the possibilities and limits of this approach for multisite installations.