Category: GitHub
Jul 8, 2021

I recently received complaints from WordPress multisite users about not being able to embed iframes for Google calendars. Upon testing, I found nothing wrong–embeds worked absolutely fine.

My users kept insisting they disappeared, though, and could prove it with screenshots.

Nothing was off about their browsers. Nothing strange was happening with plugins. They’d just create a Custom HTML block, and then paste a totally normal <iframe> embed in, like so:

<iframe src="" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" width="560" height="315" frameborder="0"></iframe>

As soon as they clicked publish and left the page, poof! Gone.

It seems this was a change in security policy in Gutenberg. I’m not sure when this change happened, but if one of your multisite users (even an administrator!) wants to place iframes or a <script> tag into a Custom HTML block, WordPress will simply delete it.

This isn’t hard to change, luckily. You just need to add a filter to wp_kses_allowed_html. The best way to do this would be with a plugin. It would look like this:

Plugin Name: Allow iframe Tags in Editor
Description: Allows use of iframe tags in Custom HTML block for non-super-admins.
Author: Joshua Woehlke

function allow_iframes( $allowedposttags ){

	$allowedposttags['iframe'] = array(
		'align' => true,
		'allow' => true,
		'allowfullscreen' => true,
		'class' => true,
		'frameborder' => true,
		'height' => true,
		'id' => true,
		'marginheight' => true,
		'marginwidth' => true,
		'name' => true,
		'scrolling' => true,
		'src' => true,
		'style' => true,
		'width' => true,
		'allowFullScreen' => true,
		'class' => true,
		'frameborder' => true,
		'height' => true,
		'mozallowfullscreen' => true,
		'src' => true,
		'title' => true,
		'webkitAllowFullScreen' => true,
		'width' => true

	return $allowedposttags;

add_filter( 'wp_kses_allowed_html', allow_iframes, 1 );


If you want <script> tags available, you’d do the same thing for $allowedposttags['script'] within that same filter.

I won’t be uploading this to the official WP plugin directory because, per the developer expectations, all code “should be made as secure as possible.” I understand this can be interpreted in different ways, but we’re literally removing a security feature WordPress chose to implement, so…

You can clone this from github into your plugins folder, or download the .zip.

Jul 24, 2015

Where I work, we use TERMINALFOUR as our main content management system. It’s a real beast of a CMS targeted at higher education, written in Java, and capable of handling very large, high-traffic sites straight out of the box. The only major hangup is that its normal publish processor for outputting HTML from user content is somewhat limited, and its JavaScript processor is not terribly well-documented and results in very murky code. To solve this issue, I created a paste-in language superset library called t4Query that abstracts what T4 is actually doing using a familiar, semantic, and short syntax.

TERMINALFOUR JavaScript layout processor superset t4Query


TERMINALFOUR has a number of “layout processors,” or environments each with their own language for generating the HTML output from a content item. For the most part, everyone uses the standard layout processor. It’s direct output HTML with a special tag that can retrieve data that the user entered into the content item’s predefined fields. Various attributes on the tag determine how the data is output in the template. It’s pretty easy once you get the hang of it, but there’s very little logic available. The extent to which the layout can react to the content is a feature called “selective output,” wherein HTML can be output depending on whether or not there’s content in a field. There is no way to output different HTML depending on the page layout, no way to implement case logic, and no way to examine the contents of a field (like a date) and then do different things depending on what it says. This can be a pretty foreign experience for a developer who’s used to doing layouts in PHP on WordPress.

To get around this, you can use one of the alternative layout processors. The one that’s included and best supported is the JavaScript processor. It’s all the fun of a PHP layout, but there is one problem: Finding your data and outputting it how you want is quite an ordeal. This may be easier if you have access to actually see the database or log to a console, but if you’re just a system admin sitting outside of IT without shell access to the server, enjoy spending the day writing for-in loops to log properties and taking guesses at what functions do as they quickly drop off into Java black boxes you can’t look into.

What it Looks Like

How all of this affects your layouts is probably best illustrated with some examples. Say you wanted to output the path to an image (for use in a lightbox, maybe). Here’s how you would do it:

BrokerUtils.processT4Tags(dbStatement, publishCache, section, content, language, isPreview, '<t4 type="content" name="Media Field" output="normal" modifiers="" formatter="path/*" />')

Good luck walking in on your first day and figuring out what that does or why it works.

Say you wanted to use an if statement to see if someone checked a checkbox. Here’s how you access that checkbox’s value:

if (!content.get('Checkbox Field').publish().isEmpty()) ...

Or perhaps you want to place a link to send an email to a particular address:

document.write('<a href="mailto:' + content.get('Email Address').publish() + '">send email</a>');

That’s not so bad, you say. But what if you wanted to sanitize the email field to ensure no stray HTML tags had appeared in it?

document.write('<a href="mailto:' + BrokerUtils.processT4Tags(dbStatement, publishCache, section, content, language, isPreview, '<t4 type=" name="Email Address" modifiers="striptags" />') + '">send email</a>');

It’s not horrible at first, but your content layout quickly becomes a garbled, unreadable mess. The code is very descriptive of what T4 actually needs to do under the hood to retrieve that data, but not ideal if you just want to open up a content layout and make a quick change.

Enter t4Query

What my designer and I needed was a library of shortcut methods that would allow us to use the power of the JavaScript processor, but be super-readable, super-familiar, and easily memorized. We needed a jQuery for TERMINALFOUR–so I made one. It works exactly how you’d expect: A selector to choose your content element, and then chainable methods to adjust how you want the output handled.

Getting an image path becomes:

$('Media Field').formatter('path/*')

Checking that checkbox becomes:

if ($('Checkbox Field').checked()) ...

Including that email address in the link becomes:

document.write('<a href="mailto:' + $('Email Address') + '">send email</a>');

And stripping those stray HTML tags out of said email address becomes:

document.write('<a href="mailto:' + $('Email Address').modifiers('striptags') + '">send email</a>');

The library works by building a t4 tag as an object when you use a selector, and then adding or removing properties as you chain modifiers onto your statement. Finally, due to the magic of custom valueOf and toString methods in the tag object it creates, it’s able to automatically know when the tag has ended and pass it through TERMINALFOUR’s broker utilities to┬áreturn the output in place. More info about how that’s done is available from this fascinating blog post about valueOf on Medium.

To use t4Query, just grab the javascript (full or minified) from the t4Query Github page, read the documentation on how to use it, and then paste it into the top of your content layout. Enjoy the power of the JavaScript processor!

Fork me on GitHub