# Liked: Manton Reece... Micro.blog is officially underway! I was a relatively late backer so don't expect my invite until the end of the week.
Sending likes and replies using custom fields
Historically, we would visit someone else's site to leave a comment or click a like button. Sometimes these interactions would be held within their own site's data but, frequently, they would be stored remotely - think Facebook Likes or Disqus comments.
In keeping with owning your content, part of the #indieweb ethos is to perform these actions on your own site but pass them back so they show in both locations. The original, however, is held by yourself.
The Post Kinds plugin for WordPress is designed to add support for "responding to and interacting with other sites" by implementing "kinds of posts" - specific post types with a particular purpose. So I thought I'd give it a try.
The plugin didn't work in the way I'd imagined, however, and caused issues with my theme due to the way it maps its own post types to those already in WordPress.
While new templates can be designed for how it integrates, all I really wanted it for was likes and replies so the effort required to get everything back as if should be seemed a bit counter-productive.
Back to the drawing board.
A different way
Once webmentions are enabled the actual markup required to turn a link to another page into a like or reply is actually pretty simple - specific classes are added to identify their purpose:
- Reply =
class="u-in-reply-to"
- Like =
class="u-like-of"
This would be easy enough to add to the post HTML but, as I avoid the WordPress back end as much as possible, I wanted an easier way.
What if I could automatically add this without a plugin?
As I post from my phone I starting thinking how I could pass a URL to WordPress along with the post; I was instantly reminded of the trick I used to tell it about the path to microcast episodes:
Custom fields.
A like is usually a short post so perfect for Drafts and Workflow - custom fields can be populated directly from the 'Post to WordPress' action.
Replies are more likely to be longer posts but Ulysses doesn't, natively, allow for the same behaviour. I would just have to add the custom field after posting as a draft.
Now that the link data could be included with the post how could it be added with the relevant markup to trigger webmentions?
Functions
I had already used code in functions.php to alter posts (the creation of hashtag links, for example) but this was purely a run-time change altering how the content was displayed, not stored:
add_filter( 'the_content', 'linked_hashtags' );
To trigger webmentions the links need to be included in the actual body of the post so modifying the_content
wouldn't work. Luckily, WordPress includes a way to do this in content_save_pre
which lets you modify a post's content before being saved to the database.
In order to build the webmention links I needed to get the page title as well as the link. The function file_get_contents()
reads the contents of a file (in this case a web page) into a string and I used an example found on the web to extract the page title from that:
$str = file_get_contents($replyurl);
$str = trim(preg_replace('/\s+/', ' ', $str));
preg_match("/\(.*)\<\/title\>/i",$str,$replytitle);
Putting it together
With all the pieces in place, all that remained was to put everything together running a function to build the links when saving the post:
add_filter( 'content_save_pre', 'mentiontypes' );
Pulling the URL from the custom field is done using get_post_meta()
specifying the post ID and field name. The required string is built and added to the front of the post content before being returned back to the post as the new body.
Because content_save_pre
runs whenever a post is saved editing would cause the link to be re-added on each occasion. To prevent this I opted to delete the custom field using delete_post_meta()
after the link is first inserted to avoid duplication.
The full code is included below. Let me know if you can think of any improvements.
Update: Jeremy Cherfas pointed out that some consider file_get_contents()
to be insecure so advised using wp_remote_get()
instead. The code below has been updated to reflect this change.
function mentiontypes ( $content ) {
$id = get_the_ID();
$types = array ( 'Reply', 'Liked' );
foreach ( $types as $type) {
$mentionurl = (get_post_meta($id, $type, true));
if ( $mentionurl !="" ) {
$url = wp_remote_get($mentionurl);
$str = wp_remote_retrieve_body($url);
$str = trim(preg_replace('/\s+/', ' ', $str));
preg_match("/\(.*)\<\/title\>/i",$str,$mentontitle);
if ( $type == 'Reply' ) {
$mentionstr = 'In reply to:
';
} else {
$mentionstr = ' ...Liked: ' . $mentiontitle[1] . '...
';
}
$content = $mentionstr . $content;
delete_post_meta( $id, $type, $mentionurl );
}
}
return $content;
}
add_filter( 'content_save_pre', 'mentiontypes' );
Comments
# Considering moving my code for replies and likes into a WordPress plugin. I could then look at allowing customisation of the inserted text.
Sending likes and replies using custom fields in WordPress
A short description of how to support Indieweb likes and replies in WordPress using custom fields.
Another simple option for those who like bookmarklets: IndieWeb Press This
This Article was mentioned on unrelenting.technology
The security of any code should be of the utmost importance but, if creating a plugin that might be distributed to other people’s sites, it should be paramount. It’s one thing messing up your own site but another entirely breaking someone else’s when they’ve put their trust in what you’ve written. As we established last time, this series covers the process of improving my “Likes and Replies” WordPress plugin. This is a relatively simple piece of code that doesn’t do much (yet) but it’s still good to ensure it’s as secure as it can be and get into good habits. First steps It is best practice to prevent direct access to plugin files meaning they can only be used within the context of a WordPress installation. This is done by adding the following to the start of any PHP files:
if (!defined('ABSPATH')) exit; // Don't run if accessed directly
ABSPATH is the absolute path to the WordPress installation directory and is defined by WordPress itself. If this is not available to the plugin it is not being run within the context of an installation. We are relying on user input in the form of a URL to add likes or replies so should take steps to ensure that this is properly encoded and valid. We can useesc_url()
to do this which removes invalid or dangerous characters. Getting the address entered into the custom field then becomes:$mentionurl = esc_url(get_post_meta($id, $type, true));
I had already made a change to the code replacingfile_get_contents()
withwp_remote_get()
as the former was considered insecure. A good start With a more complex plugin additional protection may be required, like sanitising inputs which I, no doubt, will have to do later if I am able to meet my goals. This is a good start to the learning process but I now need to work on my priorities for what to tackle next.Share this:
Twitter Facebook
<a href="https://colinwalker.blog/2017/05/05/getting-plugged-in-part-two-security/">→ May 5th, 2017</a>