Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Heartbeat API

    Heartbeat API

    For the longest time I didn’t really get the heartbeat API. I get the very basics of it, but it took me a while to understand what it was really doing.

    We’re used to interacting with our websites in a very one-directional way. I click a link, I go to a page. Heartbeat API is a bi-directional communication, which can best be translated as ‘shit happens without you having to click.’ The browser and the server are happily chatting to each other all the time, without me having to do anything.

    If you’ve ever used Google Docs or MS Word or Apple Pages and noticed you don’t have to press ‘save’ all the time, that’s the idea of a Heartbeat API. It does the background things for you. That thing you should do (save often). In WordPress, the most obvious thing that Heartbeat does is it saves your posts as revisions.

    That doesn’t stop neurotics like me from pressing ‘save’ all the time.

    Of course, this can get a little expensive, checking all the time, so the Heartbeat API is smart. It only checks every 15 seconds by default (you can change this), and it only checks when you’re on a page doing something. If you just leave a page open, it slows down and, after an hour, turns off.

    But besides saving, the Heartbeat API can share information between the systems. For example, it can ping out to Jetpack and check if it’s up and everything’s working, or if you have to reconnect your LinkedIn settings. And since it’s javascript based, it doesn’t reload the page.

    You can use it to alert logged in users to new content. Imagine a post that suddenly had an overlay of ‘This post has been updated…’ Doing that requires two parts:

    1. Hook into the send call and add your data
    2. Hook into the receive call and show the data

    Pippin has a great heartbeat API example but he also warns people:

    I’ve managed to bring down server servers by using the Heartbeat API on the frontend.

    If you trigger things to be called too often, you can totally crash a server.

    The Heartbeat API is a step towards making our sites really responsive and modular. Instead of statically checking via PHP if someone’s logged in and changing display based on that, Heartbeat can dynamically change on the fly. This would allow caching systems like Varnish or static-file caches like WP Super Cache, to save the cache and speed up your site while still being dynamic. It lessens the weight on wp_ajax_ and makes things work with caches, rather than bypass them.

    And that will make our sites beat faster for everyone.

  • Mailbag: Would You Review…

    Mailbag: Would You Review…

    From ‘anon’ in Orange County:

    Why did you review plugins at WCOC but you said no when I asked you to review mine?

    That’s not actually exactly what he said. I’ve cleaned up the English.

    At WordCamp Orange Country, I was given the rare opportunity to put value judgements on plugins. I never get to do this. I review plugins on WordPress.org every day (pretty much). I test them and evaluate them and send back comments. I look for bugs and security and guideline issues.

    What I never get to do is tell people how I feel about their plugins. So when WCOC asked me to judge the Plugin-a-palooza contest ala American Idol, I replied “Oh I’m Simon Cowell. I’m in.” And when Ryan Seacrest — I mean Chris Lema asked me why I agreed to do it, I said it was because I never got to be myself when I reviewed plugins. I never got to just review and tell people how I felt.

    They should have known. Right?

    The plugin that won was not the one I liked the best. The one I liked the best was small, it was simple (if a little complex with the code). It did one thing and it did it very well. It wasn’t perfect by any means, but it worked. That plugin came in second.

    The plugin that won, I wanted to like. In fact, I said that. I said “I really wanted to like this plugin.” And everyone went ‘oooooh’ (or possibly ‘boooo’). Chris jumped to my defense and pointed out I had warned them. So I detailed out why I didn’t like the plugin, from the UX perspective, and from the functionality. Some of why I didn’t like it weren’t it’s fault at all. It was trying to fix an imperfect system in a sensible way.

    And I was asked, in the session, if it mattered to me if the flaws in the plugin were the fault of core, the APIs, or the plugin.

    No.

    Look. When you make a plugin, you’ve made it knowing the world around you and knowing what’s already broken (or non-optimal). So when you’ve made decisions on how you handle things, I firmly feel that you should be graceful and reliable and fail intelligently. And I don’t think they did. I think they solved the main problem, but in doing so created a host of others.

    When someone asks me to review their code (theme or plugin) it’s like being asked if the pants make their butt look big. They want to hear “This is great.” I believe coding is as much art as math (and yes, I see the beauty in math), so it’s also a very critical and personal thing to be told that I don’t like this thing you’ve created. It hurts!

    But for the folks in plugin-a-palooza, they knew what they were getting into. Maybe they didn’t know it was with me, but they knew. They knew they’d be judged on merits and flaws. Most people who email me asking for those reviews don’t know that. They think maybe they’ll get a security review or a comment about how things could be better.

    What they’re going to get is how I feel about their work. Did the art speak to me? Did I get confused when I used it? Did I enjoy it? Do I think it did what it set out to do? Do I think it fixes the issues it claims to address?

    Most people really aren’t ready for the real answers. And as much as it’s nice to be able to be me for a while, I’m still always chained by the reality that my reviews come from someone who’s involved in the WordPress community. Just imagine my ‘testimonials.’

    So in the interests of not starting fights, not giving myself headaches, and not making everyone grumpy, I will decline to review your code today.

  • CloudFlare Code Muncher

    CloudFlare Code Muncher

    CloudFlare’s email protection butchered my code examples.

    Just putting that out there.

    What Happened?

    I went, perhaps ironically, to a post about changing your git repo URLs after activating CloudFlare, and was confused. See, I knew the code was something like me@mydomain.com:/path/to/repo but when I visited the page, it was all gibberish like this:

    /* <![CDATA[ */!function(){try{var t="currentScript"in document?document.currentScript:function(){for(var t=document.getElementsByTagName("script"),e=t.length;e--;)if(t[e].getAttribute("cf-hash"))return t[e]}();if(t&&t.previousSibling){var e,r,n,i,c=t.previousSibling,a=c.getAttribute("data-cfemail");if(a){for(e="",r=parseInt(a.substr(0,2),16),n=2;a.length-n;n+=2)i=parseInt(a.substr(n,2),16)^r,e+=String.fromCharCode(i);e=document.createTextNode(e),c.parentNode.replaceChild(e,c)}}}catch(u){}}();/* ]]> */
    

    I quickly edited the post and saw the content there was just fine. The only content that was getting munged was code output. It was very confusing so I googled and found a surprising answer.

    What Was Wrong?

    Turns out it was “Email Address Obfuscation” — a feature in CloudFlare that munges your email address to protect it from being scraped. In and of itself, that is ultra cool.

    I could wrap everything like this:

    <!--email_off-->
    
    <!--/email_off-->
    

    Or I could filter all the shortcodes… Or I could turn off “Email Address Obfuscation”

    I went with turning off the setting because it was faster, and it’s not like people cant deduce my email address. But if I was going to set it up, the fastest would actually be to filter all shortcodes, and that proved problematic.

    Why All?

    One of the problems is that I use Syntax Highlighter Evolved to handle my code chunks, and one of the things that plugin does is let me use a shortcode based on the programing language. That means the most efficient way would be to say “If this is a shortcode, wrap it in the email-off tags to tell it to shut up.”

    Can You Code It?

    This is theoretical and not fully tested. Use at your own risk.

    With embeds, you can do things like this:

    add_filter('embed_oembed_html', 'halfelf_embed_oembed_html', 99, 4);
    function halfelf_embed_oembed_html($html, $url, $attr, $post_id) {
      return '<!--email_off-->' . $html . '<!--/email_off-->';
    }
    

    But sadly there isn’t a wrap around like that for shortcodes, which means we have to do some serious filtering. There’s a global array called $shortcode_tags that lists all shortcodes (as you register them, so shall they be added), so I’m going to take that and replace their callback functions with my own. Then in my callback, I’ll keep their callback but at the same time I’ll wrap around it:

    function cloudflare_email_off_for_shortcodes() {
        global $shortcode_tags;
    
        $shortcode_tags[ $tag ] = 'cloudflare_email_off_html';
    }
    add_action( 'init', 'cloudflare_email_off_for_shortcodes', 99 );
    
    function cloudflare_email_off_html( $attr, $content = null, $tag ) {
        global $shortcode_tags;
    
        return '<!--email_off-->' . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . '<!--/email_off-->';
    }
    

    But that struck me as a little expensive when I considered how rarely I put email addresses in things in the first place.

  • Design for Multisite or DIE

    Design for Multisite or DIE

    I don’t mean you need to design all your code to have special Multisite features. I mean that if you’re not writing code to work on multisite, you’re probably doing a lot of things non-optimally and not fully WordPressy. When you write your code with Multisite in mind, you’re actually writing it with the basic tenants of WordPress itself. It forces you to think about how WordPress is used, how it might be used, and how you can be flexible and extendable.

    Let’s throw out the idea of network options and activation for a moment and consider the ways we can write our code to make it work for Multisite and the world. The truth is that if you’re coding ‘for Multisite’ in many ways your coding for WordPress in the best way possible.

    Calling Files

    There’s a time and a place for ABSPATH but it’s as a last resort. There’s a time and a place for get_bloginfo('url') but it’s not to call .'/wp-admin/admin.php either. Did you know admin_url() will get the url to the admin area using the right protocol (http or https) for you? And it works for Multisite. Instead of hardcoding your paths or assuming everyone has WordPress installed in the root of their website (they don’t), use the functions and template calls WordPress has created.

    Oh and stop supporting the old WordPress 2.x ways of determining folders. It’s 2015. We’re good.

    Saving Files

    Saving data to the disk means everyone can read it. Duh, right? Well, where do you save uploaded files? You use wp_upload_dir of course. That works on Multisite just fine. Instead, if you hardcode in /wp-content/uploads/myplugin/ then you’re saving things for everyone. If you’re not using the WordPress options to grab the upload directory, then your code won’t work on Multisite and everyone will be sad.

    This extends to where you save your cache files. Did you know there’s a plugin that saves the cache to the plugin folder itself? Besides the fact that the cache didn’t have a way to flush and grew to 700megs over the year the person used it, that cache was for all the sites in the network. All. Saving the cache to a unique location (I suggest /wp-content/pluginname-cache/siteID) prevents cross contamination of cache.

    Saving Options

    If you write a plugin that, to save its data, it creates a new DB table and saves it there, that can be okay. But if your plugin on update then drops that table and recreates it… That was not pulled at random, by the way, I was reviewing a plugin that did that. Instead he should have been using the function update_option() to create (and update) the options. And yes, it knows.

    But that’s an extreme, I admit. What isn’t an extreme is people creating their own tables. It happens a lot. And when they do, they often forget that we have $wpdb->prefix which means they force create wp_mypluginname instead of $wpdb->prefix . "mypluginname" … guess which one’s smart enough to know it’s on Multisite?

    (If you want to make a network table use $wpdb->base_prefix and use update site option for network wide options, yes, we know the naming conventions are weird.)

    Theme Customizer

    Not everyone can edit theme files. Not everyone can make child themes. On a Multisite, the only person who can do that is the Super Admin. Site Admins have no access to edit files or upload themes. Worse, if you make a change to a theme, everyone who uses that theme gets the change. What happens when a site wants a special header and your theme doesn’t allow those to be edited via the customizer? The customizer is there for a reason. Use it. At the very least make things hookable to allow plugins to do simple things like change footers. Please. Please. That’s one of the things that themes get wrong constantly.

    What Else?

    What do you think would be improved if people ‘coded for Multisite’?

  • Mailbag: Network Shared Media

    Mailbag: Network Shared Media

    Doug asks:

    On the WP Forums (at https://wordpress.org/support/topic/multisite-with-one-media-library) you posted this comment:

    Ipstenu (Mika Epstein) Half-Elf Support Rogue, Volunteer Forum Mod & Plugin Referee Posted 1 year ago # http://wordpress.org/plugins/network-shared-media/ Keep in mind, this is generally something that kills your site’s performance.

    Unfortunately, the thread is closed so I can’t ask you to elaborate through the forum. So can you elaborate via email reply on exactly where or how the “performance is killed” as a result of installing & activating the `Network Shared Media` plug-in? Thank you, -Doug

    The problem is that WordPress Multisite was built to be multiple separate sites. You used one install of WordPress, one install of all your themes and plugins, and one ‘user base,’ but outside of that, the sites are all separate. Which plugin is active is different, which theme is used is different, and most importantly your data is segregated.

    Your data includes your media.

    The concept of ‘sharing media’ is a great one. If you have a network, you would want to have a way to share all common media in a way that every site can call it and insert it. But the way most plugins (including the one mentioned above) go about it is by doing sql queries:

    $blogs = $wpdb->get_results( $wpdb->prepare("SELECT blog_id, domain, path FROM $wpdb->blogs WHERE site_id = %d AND public = '1' AND archived = '0' AND spam = '0' AND deleted = '0' ORDER BY registered DESC", $wpdb->siteid), ARRAY_A );
    

    The code, in and of itself, isn’t bad, but that’s just to get a list of sites on the network. Then you have to check if each user has access to upload files to the site. Then you have to use switch_to_blog to go to each site and load the images.

    What happens if you have a lot of sites and a lot of images?

    Your site is slow.

    We’ve made a lot of improvements on that end, but extensive DB queries when you have to cross paths like that can be ‘expensive’ on a computational level. Not to mention those large DB queries can cause headaches if you use database caching. All that data has to be generated and cached on every load. That too will slow your server down.

    Now this won’t always make your site slow, but if you use it and you end up with a slow site, I’m not surprised.

    The next logical question, of course, is do I have suggestions or alternatives? I don’t. I actually do suggest people use that plugin if they need shared media. Or I suggest they don’t use Multisite.

  • Editing Content In Ghost Rocks

    Editing Content In Ghost Rocks

    You may have noticed based on tweets that I’ve been using Ghost daily (mostly) for a little while now, trying to get a feel for it vs WordPress.

    You know what? With the exception of wanting to kill people while I was installing it, I really, really, like it for simple blogging.

    The editor is a delight, plain and simple. It’s fast. Super fast. There’s nothing dragging it down man. Which ironically is where it loses.

    You see, there’s no extendability. It’s like the Old Days of WP, where I have to edit a theme to make widgets. Oh and no apps right now.

    Not to mention the drama of installing. It sucks for self hosted. This continues down to installing themes (sucks) and apps (non-existent). You have to reboot the Ghost ‘node’ after every change too. This is not tenable for most people and highlights the need for apps. Oh. Yeah. Apps are a thing that Ghost needs, stat.

    Right now, they’ve added in a way to add code to your header and footer without needing to edit themes, which means I was able to put in my Google Analytics code easily.

    Ghost is Ghost. WordPress is WordPress. For what I do, WP is right. For plain, simple, blogging, Ghost is good except for the Markdown aspect. I’ve got the hang on it, but it’s been nine years and I doubt it’s ever going to be ‘the thing.’ HTML wins for many reasons.

    So what do I want from Ghost into WordPress? That damn editor! Seriously.

    Ghost's super slick editor

    The content on the left and preview on the right is great. It live updates and I can see what things look like in the Visual editor while having full code control like the HTML editor. In addition, there’s no place to put in the tags or featured images or anything other than content. Until I click on that gear.

    The editor page when you click on the gear shows all the post meta

    That is slick. And it works great on mobile too. Compared to the fade out and off center DFW editor in WP, which is pretty great, it’s awesome.

    Of course I looked at the available plugins for WordPress

    Gust Plugin – This looked great, but it doesn’t work on Multisite. On WP 4.2 it threw this:

    Fatal error: Cannot redeclare get_avatar_url()
    (previously declared in
    /wp-includes/link-template.php:3414) in
    /wp-content/plugins/gust/gust.php on line 202
    

    Then there’s Splitdown – Not updated in a year and also errors:

    Parse error: syntax error, unexpected T_STATIC,
    expecting &amp;#039;)&amp;#039; in
    /wp-content/plugins/Splitdown-master/Splitdown.php
    on line 19
    

    Finally we get to PrettyPress – This isn’t a ‘Ghost’ plugin exactly but it makes a second ‘editor’ you can flip into. No save button there, but as an editor it’s rather nice.

    At this point, I’m resigned to not having that kind of slick editor in WordPress. I do think it’s a nicer direction than ‘distraction free’ as it’s actually fewer distractions. All I see is my content and a preview.