Experiments in WordPress routing 04

Admin redirection and nonces.

As much as I’m used to it some clients simply cannot remember the /wp-admin path to the administration area of WordPress.
There are guides, tutorials and plugins that allow to modify those paths to /admin and /login making those paths easier to remember.
Can this be done with this routing system?


/**
     * 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 _json_post( $request, $response ) {
        $post_id = $request->param( 'id' );
        $post    = get_post( $post_id );
        if ( empty( $post ) ) {
            echo json_encode( array( 'Error' => 'Not a valid post ID' ) );
        } else {
            echo( json_encode( $post ) );
        }
    }

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


    /**
     * Routes
     */
    function route_posts() {
        respond( 'GET', '/[i:id]/json', '_json_post' );
    }

    function route_who_am_i() {
        $user = wp_get_current_user();
        echo $user->ID > 0 ? sprintf( 'Hi %s', $user->display_name ) : 'You are not logged in';
    }

    function route_admin() {
        wp_safe_redirect( admin_url() );
        die();
    }

    function route_login() {
        wp_safe_redirect( wp_login_url() );
        die();
    }

    /**
     * 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 ) {
        with( '/posts', 'route_posts' );
        respond( '/who-am-i', 'route_who_am_i' );
        respond( '/admin', 'route_admin' );
        respond( '/login', 'route_login' );

        _dispatch();

        return $continue;
    }

Adding the two routes took little effort and it works as intended. I’m not “hiding” the /wp-admin or the /wp-login.php paths but merely adding alternative ways to them.

Nonces

I will not delve into how nonces work but they are a security precinct taken as granted in WordPress environment and losing them would be a sore loss.
To test such a feature I’ve set up two routes, one to generate a valid nonce for the user visiting the page and the other to take care of PUT requests for post creation.
The first one is just a testing utility I need to quickly have nonces at hand: those are normally generated in forms and inputs but I want to manually submit one using a REST Client.


/**
     * 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 _json_post( $request, $response ) {
        $post_id = $request->param( 'id' );
        $post    = get_post( $post_id );
        if ( empty( $post ) ) {
            echo json_encode( array( 'Error' => 'Not a valid post ID' ) );
        } else {
            echo( json_encode( $post ) );
        }
    }


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

    /**
     * Routes
     */
    function route_create_post( $request ) {
        if ( wp_verify_nonce( $request->nonce, 'add-post' ) ) {
            if ( ! is_string( $_POST['post-title'] ) ) {
                echo "You only had one job. Enter a post title please.";
                return;
            }
            $id = wp_insert_post( array( 'post_title' => $_POST['post-title'] ) );
            if ( $id ) {
                echo json_encode( get_post( $id ) );
            } else {
                echo "Something went wrong in the random post creation.";
            }
        } else {
            echo "Not authorized to create random posts";
        }
    }

    function route_nonce() {
        echo wp_create_nonce( 'add-post' );
    }

    function route_posts() {
        respond( 'GET', '/[i:id]/json', '_json_post' );
        respond( 'POST', '/[:nonce]', 'route_create_post' );
    }

    function route_who_am_i() {
        $user = wp_get_current_user();
        echo $user->ID > 0 ? sprintf( 'Hi %s', $user->display_name ) : 'You are not logged in';
    }


    function route_admin() {
        wp_safe_redirect( admin_url() );
        die();
    }

    function route_login() {
        wp_safe_redirect( wp_login_url() );
        die();
    }

    /**
     * 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 ) {
        with( '/posts', 'route_posts' );
        respond( '/who-am-i', 'route_who_am_i' );
        respond( '/admin', 'route_admin' );
        respond( '/login', 'route_login' );
        respond( '/nonce', 'route_nonce' );
        _dispatch();

        return $continue;
    }

Visiting the /nonce path will echo a WordPress generated nonce Nonce generation and using it to hit the /posts/[nonce] path will return the json version of a just created post Creating a post After I’ve logged out of WordPress hitting the same route again will show the not authorized message as the nonce verification, made for my user, will fail. Not authorized to create posts So WordPress nonce system is a feature I can add as “working” to this approach.

This latest version of the code is on GitHub.

Next

I’m taking my time to find the limits and possibilities of this approach and will delve next into templates and theme re-usage: can I do it? To which extent?