I’ve just put live a test environment for the svg-sanitizer. Give it a go and let me know what you think: http://svg.enshrined.co.uk/
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!
So I’ve just updated my blog to use the new p2-breathe theme and the O2 plugin by Automattic and I must say, I like it.
I’m hoping it’ll encourage me to blog some more, but I’m sure we’ll see!
Edit: It’s very nice when you post!
I’ve been working with a lot of WordPress plugins recently and have come across a bug that had me stumped for a while, therefore, I thought it’d be worth sharing it here.
After installing and activating a plugin that created new database tables, I realised that the tables had not been installed. I contacted the plugin support who suggested re-installing WordPress. Reluctantly I did this but it didn’t help at all, I therefore decided I’d dig into the issue and see if I could track it down.
A bit of work and a few
var_dump()‘s later I found that there as an error with the database creation SQL (below)
CREATE TABLE IF NOT EXISTS wp_domain_mapping ( id BIGINT NOT NULL AUTO_INCREMENT, blog_id BIGINT NOT NULL, domain VARCHAR(255) NOT NULL, active TINYINT DEFAULT 1, PRIMARY KEY (id), KEY blog_id (blog_id, domain, active) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
I ran the query manually and realised it was returning the error
Specified key was too long; max key length is 1000 bytes. I’d never seen this error before, so I dug into it a little more, this page informed me that InnoDB has a maximum key size of 1000 bytes, unless the
innodb_large_prefix flag is set in MySQL in which case the maximum size is 3072 bytes.
That said, I found the following document where I could check the storage requirements of each field type. From this, I can tell that the
blog_id is 8 bytes, the
active is 1 byte and as
UTF8 needs 3 bytes per character, the
domain field is
255 * 3 bytes or 765 bytes. This gives us a total key length of 774 bytes.
It was then that I realised that I wasn’t using standard
utf8mb4, which WordPress has set as it’s default character set as of 4.2. utf8mb4 requires 4 bytes per character and therefore the domain field calculation was wrong and was actually
255 * 4 bytes or 1,020 bytes in length. This is now an issue as our key is bigger than the size allowed by InnoDB hence the issue creating the tables.
Now as far as I can see, there is only one real way of getting around this and it’s the method WordPress has chosen, reducing the field length from 255 chars to something less, 247 in this case.
Now I know about this it shouldn’t be much of an issue, but I wonder how many plugin developers aren’t going to realise this has changed and are going to run into this. I foresee it being a major pain for a few months.
Anyway, onwards and upwards now!
Cheers for now!
Recently I’ve been tasked with integrating a few API’s into WordPress sites. Whilst this doesn’t seem too hard, I found it hard to find solid documentation on the best practices in this scenario.
In this post I will explain how I decided to go about these integrations, focussing mainly on my class loading inside WordPress.
Themes in WordPress all seem to be very procedural. This is fine for a little theme, but as soon as you start making a few changes, that
functions.php file becomes unwieldy pretty quick. I’ve seen people split up their functions files into separate files, each holding functions for a certain part of the site. That’s not bad, but then you’ve got to make sure you
include them all into your
functions.php file which looks horrendous!
By structuring your code properly, you can move your function calls into classes, these classes can then be autoloaded using PHP’s spl_autoload_register function. Autoloading means no more including files, as long as your register function knows where to look for the code, it will include is for you. Doesn’t that sound good?
How it’s done
Rather than write my own autoloader, I opted to use the Class Example autoloader, defined by the php-fig, which is available here. I add this file, as
autoloader.php to my theme root, this is then included into the top of the
In the demo below, I have a folder called
Services that holds all of my API classes, these classes are then in turn contained within the
services namespace. On line
16 I am passing this namespace into the autoloader and then telling it the location of these classes. Remember, as they are in the theme directory, we need to prefix the folder with the theme directory location, hence the use of the
You can call the
addNamespace method as many times as you like with different namespaces and directories, if your classes are split up a little more.
Now we’ve registered our autoloader we can call classes as and when we need them without having to worry about including the file each time, whether that be from the
functions.php file or from inside a template, it doesn’t really matter as they’re always available. You will however have to call the class with it’s full namespace or make use of the use statement in PHP to import that namespace.
If you’d like to know more about namespacing and autoloading classes, there are some great resources below:
We use Elliot Condon’s Advanced Custom Fields extensively in WordPress at work and I must say, it’s one of my favourite WordPress plugins ever made. That said, sometimes people ask for things that I just can’t work out how to do with the native plugin.
Today a client asked me to allow them to set their own zoom distance on their maps. We’re using the great ACF map field for all the maps so I thought, “Hey, that’s fine, I’ll just go and enable that option”, only to find that there isn’t an option for this. I did some digging around on Google and stumbled across a support thread that asks exactly what I wanted to know.
Whilst there was an answer in the thread, it required me to change the plugin files, something I plain up refuse to do. The last thing I want is for somebody to update their plugins at some time in the future and the whole thing to fall apart. No, I had to find a way of doing this without hacking into any other files.
I came up with the idea that I’ll use a separate field and the client can set their zoom level in there. Whilst that worked fine for me as I know the zoom levels, it wouldn’t be too great for the client, who wants to just be able to zoom in on the map and have that set. After reading through the code samples in the aforementioned support thread, it hit me that I should be able to bind to the
zoom_change event in the Google Maps API and then output the value into the second field for use on the front end.
Upon first try, I ran into issues with
window.load() but I still had the same issue. Somehow I had to delay the function until the Google API had loaded.
I ended up doing this by using a
setInterval() on a 500ms interval to call a function that checks if
typeof google !== 'undefined'. If this returned true, I could then cancel the interval and bind to the maps API. The second problem I ran into, was that I wasn’t sure how to access the ACF maps object. After looking around the ACF plugin file, I worked out that it’s set in
js/input.js under the
acf.fields.google_map.map object. I added this to my maps callback and found out that it wasn’t yet defined. This was then added to the previous variable check function and hey presto, it worked. Now it was just a case of linking the fields up, the easy bit.
Below are the files that I used.
adminMaps.js handles the heavy lifting and setting of the fields whereas the snippet from my
functions.php just makes sure that the JS file is only loaded on post.php in the admin area.
To use this, all you’ll have to change is the selector for the second field, on lines 10 and 18 of
adminMaps.js, it’s currently set to
#acf-field-zoom_level the ID of my field.
You can also access the full Gist here.
P.S. As a bonus, line 13 of the JS file will disable the scroll to zoom in the admin area!
I used Codepen to mock up this demo, the code you can see below!
One of the major issues I ran into was the fact that I needed to fix the amount of slides as to calculate the percentages used in the keyframes animation. I’d have liked to overcome this, by passing a variable to either the keyframe declaration, or by creating a custom keyframe animation per slider inside the slider mixin. As far as I can see, neither of these options are currently implemented so I’m a bit out of luck there, if you can think of another way in the meantime, drop me an email, or drop a comment on this post!