Integrating WordPress into Laravel

The Problem

Recently whilst working on an outsourced project at We Are DWM we had a Laravel app and a WordPress site running side by side. The client had wanted the same design across both “sites” and for it to appear as seamless as possible.

This really gave us two options:

  1. Maintain two separate sets of CSS and templates, one for WordPress and another for Laravel, or
  2. Find a way to merge the two without compromising their integrity.

Option 1 is probably the simplest option, but would more than likely lead to a huge number of issues later down the line, with one set of styles being updated but not the others, etc. Therefore I decided to research option 2 some more and run with it.

The Solution

Seeing as WordPress is bootstrapped through the wp-load.php file, as long as we can load this file we should have access to our WordPress functions. That sounds easy enough, just require the wp-load.php file in your routes I hear you say? But I only need WordPress for a certain subset of routes, specifically the user facing ones. This is how I did it:

Set up your routes

Setting up the routes was my first task, in order to hook into these routes later, I added a custom attribute to my route group, called “name”:

Route::group(['name' => 'frontend'], function (){

    Route::get(...);

});

Load WordPress using a Service Provider

I then created a service provider that I could use to load my wp-load.php file using php artisan make:provider WordPressServiceProvider.

Note: I did not add this provider to my providers array in the config/app.php file.

Here’s the content of that file:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use URL;

class WordPressServiceProvider extends ServiceProvider
{

    /**
     * Path to our WP installation
     *
     * @var string
     */
    protected $bootstrapFilePath = '../path/to/wp/and/wp-load.php';

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
    	/**
    	 * Here we can enqueue any extra scripts or styles we may need. 
    	 * I loaded my frontend specific styles and scripts that were of no use to the WP site
    	 */
        wp_enqueue_style('frontend-styles', URL::asset('css/frontend.css'), ['dependencies'], false);
        wp_enqueue_script('frontend-scripts', URL::asset('js/frontend.js'), ['dependencies'], false, true);
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        if(\File::exists($this->bootstrapFilePath)) {
            require_once($this->bootstrapFilePath);
        }
    }
}

Put it all together with some Middleware

Finally, in order to load my service provider at the required time, I need to tell it when that is. I decided that a simple piece of middleware would be the best option for this. Using the following command I created the middleware below php artisan make:middleware WordPressLoader.

<?php

namespace App\Http\Middleware;

use Closure;

class WordPressLoader
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $actions = $request->route()->getAction();
 
        // Make sure out custom name attribute is set and equals frontend
        if(isset($actions['name']) && $actions['name'] == 'frontend') {
            // Register our service provider
            app()->register(\App\Providers\WordpressServiceProvider::class);
        }

        return $next($request);
    }
}

The above code registers our new service provider with Laravel if the custom route attribute “name” exists and it equals “frontend”. If these conditions don’t match, we just skip over this and continue with the rest of our middleware.

Note: Don’t forget to add this middleware to your $middlewareGroups array in Http/Kernel.php

Using WordPress

Now that you have WordPress loaded when you need it, you can use any of the standard WP functions within your Blade templates, such as wp_head() and wp_nav_menu(). Neat, eh?

How to allow SVG uploads in WordPress

Don’t.

Nope, stop.

You developers/bloggers who keep passing the below code around as a valid way of allowing SVG uploads in WordPress are killing me inside.

function cc_mime_types($mimes) {
    $mimes['svg'] = 'image/svg+xml';
    return $mimes;
}
add_filter('upload_mimes', 'cc_mime_types');

Yes, this will allow you to upload SVGs in WordPress, it will also allow someone to upload an XML Bomb or an SVG with an XXE attack or god forbid a lovely XSS attack. You see, too many developers are allowing SVG uploads without thinking about what that means. Seriously, why do you think WordPress hasn’t added SVG uploads into core yet? Not because they want to make life difficult but because they understand the security risks that are imposed by allowing an SVG to be uploaded.

There is currently, as far as I’m aware, no well tested PHP library for SVG sanitisation. There have been a few attempts but as far as I can tell, they’ve all been far too lenient on allowing potentially dangerous attributes through. To me, this means they either are too trusting, or don’t fully understand the potential payloads that can be embedded within an SVG.

The library I’ve been working on has taken the opposite stance. By default, be overly aggressive when stripping attributes and elements and then allow people to add their own whitelist if they need to. This, I think is the only feasible way of properly sanitising an SVG.

As for WordPress and SVGs, please stop using the above code. It makes me cringe every time I see it, especially when I think that this is actually in use on production sites. Fine, play with SVGs locally but to put this on a public facing server? Well, you’re a braver person than me.

Please people, use SVGs in your front end builds, use it as backgrounds, images, inline, whatever, but please stop allowing people to upload un-sanitised SVGs to the system. There’s no difference between allowing an SVG upload to allowing a PHP upload. For those of you that think that allowing a PHP upload is OK, because there’s obviously a fair few of you please stop developing. Seriously.

/rant

Why I hate the WordPress signup page

I’ve been working with WordPress multisite a lot recently and whilst all in all it’s not too bad, there is one thing that really pisses me off about it, wp-signup.php. No matter how many times I try and get my head round the contents of this file, I still struggle.

It just seems like this file is a complete cluster-fuck of functions, html and css. On top of that, I feel there are insufficient hooks and filters to allow you to customise it properly without hacking the file to pieces.

I’ve had to style up a few signup pages recently for a project of ours and it was that much of a pain in the ass, I ended up using Gravity Forms to create a custom signup page that was 100 times better looking and easier to style.

Now, I’m not saying that wp-signup.php is useless, it does it’s job and it seems to do it well, my only gripe is that it’s so unstructured and hard to customise. That’s something that can be fixed though and it’s my hope that someone will address this in time for WordPress 4.4. I think I may have a crack at it this week and see what happens, we’ll see though.

PHP South Coast 2015

I attended my first ever PHP conference yesterday, PHP South Coast. I must say, I had a great time, not only were people very welcoming, but the talks were also extremely good. The talks I attended are as follows:

Stand out talks for me were by Cal, Jeroen, Phil and Harrie, although all were thoroughly enjoyable. I wish I had some pictures to share but unfortunately I was paying too much attention to the actual content of the talks to remember to take some, you will be able to see some at #phpsc15 I’m sure.

Cal’s opening keynote was extremely powerful and emotive. He spoke about the need for a community and how communities, like living organisms, can thrive and fail based upon small changes. Getting involved in the PHP community is something that I’ve always wanted to do, going as far as trying to set up PHPCornwall. Due to lack of time, I’ve never got that into it but this talk has really given me the push I need to get bits sorted. PHPCornwall will be a thing soon, I promise!

Jeroen’s talk on Teaming up Backbone.js and the new WordPress API really got me thinking about what we can actually do with WordPress. I’ve already used the WP-API for a few things but always to power websites. The thought of powering a native application with it had only recently been mentioned to me but after seeing this talk it makes perfect sense. WordPress is an extremely powerful system and teamed up with the WP-API it seems that there’s no reason we can’t use it as a pre-built data store for other things we need!

Phil’s talk on API Pain Points was another good overview of what he goes over in his book Build API’s You Won’t Hate. This book was a saviour to me when building an internal API recently and I encourage anyone who has to build an API to read it. Whilst the talk didn’t really cover any new material if you’ve read the book, it was good to see the man himself in action. My only regret was not grabbing him at some point to say thank you. There’s always next time I suppose!

Harrie’s talk on Database version control without pain was probably one I was most interested in before the conference as it’s always been a massive annoyance for me. Harrie started off talking about his search for the silver bullet in DB Version Control, only to find out that there isn’t one and that the methodology you use is down to what you and your team feel most comfortable using. Whilst disappointing to know it’ll still be a pain, he showed some great tools for helping with the management and some methodologies I had never come across before. It was a very thought provoking talk.

Maybe I’ll write up a bit more about this at a later date but for now I’m going to go and do some more playing with the WP-API!

Sanitize SVGs in WordPress

So my plugin Safe SVG has just been accepted into the WordPress plugin directory. Whilst mainly a proof of concept, I’m hoping that this plugin will help convince the core team that SVGs, with the right sanitization should become part of core.

My major argument for allowing SVGs in core with sanitization is that there are currently 128 other SVG upload plugins in the plugin directory (source), plus the likes of the posts on blogs like CSS Tricks such as this one that all show you how to allow SVG uploads in WordPress, but don’t address or sometimes even mention the massive security risks that come with allowing users to upload SVGs.

SVGs should be considered as standalone XML applications, there are a huge number of vulnerabilities that can be attacked. For example, some of the easiest to implement are XXE attacks and the Billion Laughs attack. Safe SVG nullifies these attacks by removing the DOCTYPE from the SVG file, something so simple yet overlooked by most other plugins.

Safe SVG also protects against XSS attacks embedded within the XML file by defining a strict whitelist of elements and attributes allowed within the SVG, anything not on these whitelists are removed. Whilst this may break some Javascript powered SVG animations, I feel that is a small price to pay for peace of mind when it comes to your users security.

Probably the best way to learn more about Safe SVG is to go and download it from the WordPress plugin directory and take a look through the code, alternatively you can see the library it’s built upon on Github. If you find a bypass or have any suggestions on how to improve this plugin or the underlying library, please don’t hesitate to contact me and let me know your thoughts.

Safe SVG for WordPress

After a lot of testing of svg-sanitizer I’ve finally decided to make a WordPress plugin for it. This is more of a PoC to show that it can be done.

Once installed, the plugin will hook into the uploads and automatically sanitize any SVGs that you upload.

I’ll update this post when it’s on the WordPress directory but for now, here’s the download:

Click here to download

SVG Sanitization

A couple of days ago I was browsing through the WordPress core Trac looking for something to get involved in and stumbled upon the following issue: https://core.trac.wordpress.org/ticket/24251

The lack of ability to upload SVGs into WordPress has always been a slight annoyance to me so I decided to see what I could do about it. After reading through the thread, I realised that what PHP was really missing, was a decent SVG sanitizer.

I read around a few articles and read through the source at: https://github.com/cure53/DOMPurify to get some ideas of how it’s done by the professionals. I started off by mapping out what was needed:

  • An element whitelist
  • An attribute whitelist
  • A way to remove those not in the whitelist

The two whitelists I borrowed from DOMPurify, after all it’s built by people with more knowledge than me. I then put a basic PHP library together that allowed me to pass in a dirty SVG string and receive out an SVG string with all the non-whitelisted elements and attributes removed.

The strangest thing I came across whilst building this was the fact that DOMNodeList doesn’t work like an array. If you iterate from 0 to 10 and delete node 5, everything drops down 1 place, so when you move to node 6, that’s actually node 7, odd. This can be easily fixed of course by iterating backwards from 10 to 0.

Anyway, I have a basic POC up on Github (https://github.com/darylldoyle/svg-sanitizer) that I’m hopefully going to push a bit further in the next week or so. Lets hope all goes well!