Skip to content

Instantly share code, notes, and snippets.

@zacscott
Last active March 11, 2017 01:23
Show Gist options
  • Save zacscott/ec58555e5f3dc9ab651260a07e12b938 to your computer and use it in GitHub Desktop.
Save zacscott/ec58555e5f3dc9ab651260a07e12b938 to your computer and use it in GitHub Desktop.
Simple one file router for WordPress (can be used as a mu-plugin)
<?php
/*
* Plugin Name: Routes for WordPress
* Description: Routes class provider plugin
* Version: 2.0
* Author: Zachary Scott
*/
namespace zacscott;
/**
* Utility to build custom routes within WordPress. Routes are defined as
* regular expressions and pass defined arguments to the callback function.
*
* Example of setting up a route:
*
* Routes::add( array(
* 'regex' => '^myroute/([0-9]+)/?$',
* 'callback' => array( $this, 'my_route_callback' )
* ) );
*
* The callback would then look like the following:
*
* function my_route_callback( $id ) {
* // Do things here
* }
*
* @version 2.0
* @author Zachary Scott <zac@zacscott.net>
*/
class Routes {
// the registered routes
private static $routes = array( );
// whether the setup() method has been called yet
private static $is_setup = false;
/**
* Registers a new route.
*
* @param $regex string The regular expression to match the route path. Can contain groups which are passed as
* params to the callback.
* @param $callback function Callback for when the route is triggered
*/
public static function add( $args ) {
assert( ! empty( $args ) );
self::setup();
// Set defaults so stuff does not break
$args = array_merge( array(
'regex' => '',
'callback' => array(),
'title' => '',
), $args );
// Add to the list of routes
if ( ! empty( $args['regex'] ) && ! empty( $args[ 'callback' ] ) ) {
self::$routes[] = $args;
}
}
// Sets up the routing system
static function setup() {
// Only setup once
if ( self::$is_setup ) {
return;
}
// Register the setup class
add_filter( 'do_parse_request', array( __CLASS__, 'handle_routes' ), 1, 3 );
}
// Handles routing on 'do_parse_request'
static function handle_routes( $continue, $wp, $extra_query_vars ) {
// Get the request path / URI
$request_path = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
$request_path = trim( $request_path, '/' );
$request_path = strtok( $request_path, '?' );
// Regsiter each of the routes
foreach ( self::$routes as $route ) {
$regex = $route['regex'];
$callback = $route['callback'];
// Regex the request path
$matches = array();
$match = preg_match( '{' . $regex .'}', $request_path, $matches );
// Dispatch route if a hit
if ( ! empty( $matches ) ) {
// Set title if one was provided
$route_title = $route['title'];
add_filter( 'wp_title', function( $title, $sep, $seplocation ) use ( $route_title ) {
$title = $route_title;
$site_title = get_bloginfo( 'name' );
// Grab the separate from Yoast if defined
if ( function_exists( 'wpseo_replace_vars' ) ) {
$sep = wpseo_replace_vars( '%%sep%%', array() );
}
// Build the title string, basedo nthe separator
if ( $seplocation == 'right' ) {
$title = "{$title} {$sep} {$site_title}";
} else {
$title = "{$site_title} {$sep} {$title}";
}
return $title;
}, 10, 3 );
array_shift( $matches );
call_user_func_array( $callback, $matches );
exit;
}
}
// No matching route found, fallback to WordPress
return $continue;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment