Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: function

  • Unique vs Common

    Unique vs Common

    Someone asked me if I could explain why sometimes I tell people to name their functions uniquely and sometimes I don’t.

    I get how this is confusing, even though it makes perfect sense to me. Here’s how to remember:

    • What’s yours is unique to your plugin
    • What’s common is unique to what’s common

    Okay, maybe that didn’t help. Let’s try a practical example!

    I have a plugin called ‘Genericon’d’ which includes the Genericons library inside. In that plugin, I have the following enqueues:

            wp_enqueue_style( 'genericons', plugins_url( 'genericons/genericons/genericons.css', __FILE__ , '', self::$gen_ver ) );
            wp_enqueue_style( 'genericond', plugins_url( 'css/genericond.css', __FILE__ , '', self::$gen_ver ) );
    

    The first one is for Genericons, the library. There I use the common name of genericons which means if anyone else also enqueues Genericons with this name, one of ours will win depending on load order. For my personal plugin CSS, I use the name genericond (notice that D?) as it matches the name of my plugin and, therefore, is less likely to conflict with someone else’s plugin.

    Conflict is the name of the game here. I actually want genericons to conflict. Well, not conflict. I want it to be recognized as a shared library, so WordPress only loads it once. If I had named it genericond-genericons then, in the event someone has Jetpack or a theme like TwentyFifteen which both include Genericons, they would load the entire library twice! And I would suck. On the other hand, if we all share the library name, WordPress will check, see it’s loaded, and carry on.

    Name what’s yours in a way unique to your plugin or theme.

    Name what’s shared in a way that’s unique, but also stupid obvious and easy to share.

    Font-Awesome? Use font-awesome for your enqueues.

    As for functions and class names, even if you put in a check for ‘if this doesn’t exist…’ the logic works the same. If it’s yours and yours alone and only exists in this code, name it unique to your plugin/theme. If it’s a shared library, like the aws-sdk, name the class in the standard way and wrap it in an ‘if this doesn’t already exist…’ so that if it does exist, it only gets called once.

    Standard names for shared libraries.

    Unique names for your personal codes.

    And bonus! If you keep your names to a standard, while being unique, someone may call your functions too.

    By the way, anything global like DEFINE( 'FOO', true ); should always be unique. Those are globals. Everyone uses them. I’ve made that mistake too.

  • New Smilies?

    New Smilies?

    While the arguments for and against are pretty hot and heavy (see the trac ticket for more), it’s no secret I’m pro-new smilies. The old ones are too small, too pixelated, and too (pardon the phrase) web 1.0. They look old and out of date on my site.

    Here they are at normal size:

    Old Smilies, normal sized

    And here’s double:

    The smilies at twice size

    These are both gifs, to illustrate the size issue. Notice how they’re fuzzy?

    I want to make one thing clear, pun intended. None of my issues have to do with Retina. I don’t like ‘small’ anything. The smilies are too small, much like the font on many people’s websites, the pixelization is hard for me to identify. In fact, while I’m using the new smilies here, you’ll notice they’re bigger. Sure, cause I tossed this in my CSS:

    #wp_grins img, img.wp-smiley {
        height: 25px;
    }
    

    And that’s all it took to make them something I felt was readable. But the beauty, and why I like the new SVG images, is that I can make them larger like that, without losing readability.

    Thankfully, due to the curmudgeony efforts of the new smilies’ biggest naysayer, Otto, we have a filter! I’ve talked about this before, in how I handled both SVG and PNG as smilies for IE. I have a couple options here. I could write some code myself, or I could use New WordPress.com Smileys (which is on GitHub for reasons, the code is fine!).

    I like the plugin a lot. I like it so much, I refactored my SSL Grins plugin to use them with the fancy pants new span code (instead of images). But… Well, I already had this done by the time his plugin came out, and I like how I accounted for things differently. The only real difference though is he uses spans, and I just swap out the images:

    <?php
    /*
    Plugin Name: Custom Smilies
    Plugin URI:  https://ipstenu.org
    Description: I like the new smilies, shut up Otto.
    Version: 1.0
    Author: Mika Epstein
    Author URI: https://ipstenu.org/
    */
    
    // Move Smilies
    add_filter('smilies_src','helf_smilies_src', 1, 10);
    function helf_smilies_src($img_src, $img, $siteurl) {
        if ( strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 8' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 7' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'Android' ) ) {
            $img = 'ie/'.$img;
        }
        else {
             $img = str_replace("png", "svg", $img); // Remove PNG
        }
        return $siteurl.'/code/images/smilies/'.$img;
    }
    
    // This is in a paren for my sanity....
    {
        global $wpsmiliestrans;
    
        if ( !get_option( 'use_smilies' ) )
            return;
        
        if ( !isset( $wpsmiliestrans ) ) {
            $wpsmiliestrans = array(
            ':mrgreen:' => 'icon_mrgreen.png',
            ':neutral:' => 'icon_neutral.png',
         // removing b/c new versions
            ':twisted:' => 'icon_evil.png',
              ':arrow:' => 'icon_arrow.png',
              ':shock:' => 'icon_eek.png',
              ':smile:' => 'icon_smile.png',
                ':???:' => 'icon_confused.png',
               ':cool:' => 'icon_cool.png',
               ':evil:' => 'icon_evil.png',
               ':grin:' => 'icon_biggrin.png',
               ':idea:' => 'icon_idea.png',
               ':oops:' => 'icon_redface.png',
               ':razz:' => 'icon_razz.png',
               ':roll:' => 'icon_rolleyes.png',
               ':wink:' => 'icon_wink.png',
                ':cry:' => 'icon_cry.png',
                ':eek:' => 'icon_surprised.png',
                ':lol:' => 'icon_lol.png',
                ':mad:' => 'icon_mad.png',
                ':sad:' => 'icon_sad.png',
                  '8-)' => 'icon_cool.png',
                  '8-O' => 'icon_eek.png',
                  ':-(' => 'icon_sad.png',
                  ':-)' => 'icon_smile.png',
                  ':-?' => 'icon_confused.png',
                  ':-D' => 'icon_biggrin.png',
                  ':-P' => 'icon_razz.png',
                  ':-o' => 'icon_surprised.png',
                  ':-x' => 'icon_mad.png',
                  ':-|' => 'icon_neutral.png',
                  ';-)' => 'icon_wink.png',
            // This one transformation breaks regular text with frequency.
            //     '8)' => 'icon_cool.png',
                   '8O' => 'icon_eek.png',
                   ':(' => 'icon_sad.png',
                   ':)' => 'icon_smile.png',
                   ':?' => 'icon_confused.png',
                   ':D' => 'icon_biggrin.png',
                   ':P' => 'icon_razz.png',
                   ':o' => 'icon_surprised.png',
                   ':x' => 'icon_mad.png',
                   ':|' => 'icon_neutral.png',
                   ';)' => 'icon_wink.png',
                  ':!:' => 'icon_exclaim.png',
                  ':?:' => 'icon_question.png',
            // New for me
                  '>:(' => 'icon_mad.png',
                  'o_O' => 'icon_surprised.png',
                  'O_o' => 'icon_eek.png',
                  '^^‘' => 'icon_redface.png',
                  ':‘(' => 'icon_cry.png',
                  ':’(' => 'icon_cry.png',
       ':whiterussian:' => 'icon_whiterussian.png',
                  '|_|' => 'icon_whiterussian.png',
                   ':/' => 'icon_uneasy.png',
                  ':-/' => 'icon_uneasy.png',
          ':developer:' => 'icon_developer.png',
            ':burrito:' => 'icon_burrito.png',
            ':martini:' => 'icon_martini.png',
                  '>-I' => 'icon_martini.png',
              ':blush:' => 'icon_redface.png',
              ':heart:' => 'icon_heart.png',
                //'&amp;lt;3' => 'icon_heart.png',
               ':bear:' => 'icon_bear.png',
               ':star:' => 'icon_star.png',
                  '(w)' => 'icon_wordpress.png',
                  '(W)' => 'icon_wordpress.png',        
            );
        }
        
        if (count($wpsmiliestrans) == 0) {
            return;
        }
    }
    

    But why don’t they all show up in my comments section? Where’s the martini!? I also upgraded my plugin SSL Grins with an ‘easter egg’ of code that hides anything in this array of smiled_hide. This works on both my version of the smilies plugin and Avryl’s. and looks like this:

    $smiled_hide = array("bear", "wordpress", "martini", "developer", "whiterussian", "burrito","icon_bear.gif", "icon_wordpress.gif", "icon_martini.gif", "icon_developer.gif", "icon_whiterussian.gif", "icon_burrito.gif", "icon_bear.png", "icon_wordpress.png", "icon_martini.png", "icon_developer.png", "icon_whiterussian.png", "icon_burrito.png", "icon_bear.svg", "icon_wordpress.svg", "icon_martini.svg", "icon_developer.svg", "icon_whiterussian.svg", "icon_burrito.svg");
    

    Now this is possibly the jankiest, stupidest, code I’ve written in a while. I’d rather just have the words be there, and filter “If any of the values in this array is a partial match to the name of the smilie we’re looking at right now, don’t show it.” But I’m not clever enough with arrays and preg matching at this point, so I did that ugly list, and used this:

    if (!in_array($grin, $smiled) && !in_array($grin, $smiled_hide) ) {...}
    

    So at this point, pull requests are welcome because I’d love to clean that up!

  • Genesis: Static Nav Bar

    Genesis: Static Nav Bar

    One of my sites got a facelift, and mid-stream I thought “This site would be the perfect place to have one of those floating nav bars.” You know, like how Twitter has this?

    sticky bar example

    Well guess what? It was easy! Presuming you already have a Primary Navigation Menu (like the one I have here with the Genericons), it’s two steps. Of note, you don’t have to do this in your functions.php, but since this will be a part of your theme, it probably belongs there. I tested, and it works in an mu-plugin as well. I should also point out that there are some official directions in the My.StudioPress.com site, but I didn’t use them. I like making it hard.

    Step One: Put the nav menu above your header

    This one was super easy, it’s even in one of the official Genesis Snippits under Navigation Menus. Put this in your functions.php file:

    //* Reposition the primary navigation menu
    remove_action( 'genesis_after_header', 'genesis_do_nav' );
    add_action( 'genesis_before_header', 'genesis_do_nav' );
    

    That puts the primary navigation menu above the header. If you want to use the secondary menu, it would be genesis_do_subnav but you can sort that out.

    Step Two: Make it stick

    This is pure CSS, so into your style.css goes:

    .nav-primary {
        position:fixed;
        z-index:99;
        top: 0;
        width: 100%
    }
    

    At first I didn’t add in the top: 0; but I found out that without it, a fixed position meant my header was suddenly under the navbar all the time. Oops. So I moved that to on, after spending an hour trying to math out the permutations with margins, and ended up with my navbar under the WordPress toolbar! Don’t worry, CSS to the rescue!

    body.admin-bar .nav-primary {
        top: 28px!important;
    }
    body.admin-bar .site-container {
        margin: 30px 0 0 0;
    }
    

    This simply says that for the body class of admin-bar, bump everything down by 28 pixels.

    Step Three: Return to Top

    I know, I know, I said two steps. This one is optional. I made a menu item called ‘Top’ with a link of #top and a CSS label of ‘top’ and it looks like this:

    Top Menu

    Now since I called this menu ‘primary’ and I’m using Genericons, I made this my CSS (keep in mind .nav-primary would also work):

    .menu-primary top {
        float: right;
    }
    
    .menu-primary li.top a {
        font-size: 0;
    }
    
    .menu-primary li.top a::before  {
        vertical-align: middle;
        padding: 0 5px 0 0;
        font-family: 'Genericons';
        content: '\f435';
    }
    

    This gives me a happy little top arrow that, when clicked on, takes people to the top. If you want to mess with colors, remember that to be specific for just the before calls, it’s a:hover:before (the pseudo-element is last).

  • WP Comments ReplyTwo

    WP Comments ReplyTwo

    WPTavern has this cool thing where, without threaded comments, you still have a reply link, AND it creates an automatic link back to the original comment.

    Let me rewind. If you have threaded comments, then you get a ‘reply’ link on the bottom of a comment, and it lets you make a threaded reply. Yay! There are problems with this, though, as after a while, if you get nested deep enough, you can’t reply under anymore, and have to go up to click reply on the previous post and on and on.

    Threaded PipeBack eons ago, WPTavern solved this with a function, and like all great sites documented it! The problem? The documentation was busted. Now, yes, I did ping Jeff about this and asked him how it went, but in the meantime, I was impatient and looked up a plugin that almost fit my bill.

    Enter @ Reply (aka Reply To), which add in a reply link to all comments! Plus is gives you ‘Twitter like’ @replies, so when you comment, it starts “@foo:” automatically. This is just like what WPTavern has, perfect! Except… not quite.

    My problems became two:

    1. I want all comments to have a ‘reply’ link.
    2. I don’t want the hover over image.

    And I solved this with two code chunks: a plugin and a theme.

    See, by default WP stops showing you the ‘reply’ link when you can’t nest anymore. To change that, you have to edit how your theme calls comments. Or rather, you have to change the comment_reply_link() call.

    The Theme Code

    I’m already customizing my comments in Genesis so this was surprisingly simple.

    What was this:

    &lt;div class=&quot;comment-reply&quot;&gt;
        &lt;?php comment_reply_link( array_merge( $args, array( 'depth' =&gt; $depth, 'max_depth' =&gt; $args['max_depth'] ) ) ); ?&gt;
        &lt;/div&gt;
    

    Becomes this:

    &lt;div class=&quot;comment-reply&quot;&gt;
        &lt;?php comment_reply_link( array_merge( $args, array( 'depth' =&gt; 1, 'max_depth' =&gt; 2 ) ) ); ?&gt;
    &lt;/div&gt;
    

    Basically we’re lying to WP and saying we always show the link. I got that idea from this stackexchange post, and as I understand it, we’re tricking WP by saying that every post is depth of 1, and has a max of 2, instead of letting it figure it out on it’s own. This is probably inelegant, but I couldn’t find another way to have the reply link always on.

    The Plugin Code

    nested-commentsThis was easier, in that I took the existing code, cleaned it up and removed the reply image, and that was pretty much it. Downside is that this does not work on every site. Notably, it doesn’t work unless threaded comments are turned on. When they’re not, it does a double-refresh.

    That said, this is probably never going to be a plugin for the masses, so I’m content with having it work this way for me. Even if I only thread one comment at a time, it would let me group them together and get the @-reply. It’s already rather popular on the site I intended it for, and people like it.

    So here’s the code:

    class AtReplyTwoHELF {
        public function __construct() {
            add_action( 'init', array( &amp;$this, 'init' ) );
        }
    
        public function init() {
    		if (!is_admin()) {
    			 add_action('comment_form', array( $this, 'r2_reply_js'));
    			 add_filter('comment_reply_link', array( $this,'r2_reply'));
    		}
    	}
    
    	public function r2_reply_js() {
    	?&gt;
    		&lt;script type=&quot;text/javascript&quot;&gt;
    			//&lt;![CDATA[
    			function r2_replyTwo(commentID, author) {
    				var inReplyTo = '@&lt;a href=&quot;' + commentID + '&quot;&gt;' + author + '&lt;\/a&gt;: ';
    				var myField;
    				if (document.getElementById('comment') &amp;&amp; document.getElementById('comment').type == 'textarea') {
    					myField = document.getElementById('comment');
    				} else {
    					return false;
    				}
    				if (document.selection) {
    					myField.focus();
    					sel = document.selection.createRange();
    					sel.text = inReplyTo;
    					myField.focus();
    				}
    				else if (myField.selectionStart || myField.selectionStart == '0') {
    					var startPos = myField.selectionStart;
    					var endPos = myField.selectionEnd;
    					var cursorPos = endPos;
    					myField.value = myField.value.substring(0, startPos) + inReplyTo + myField.value.substring(endPos, myField.value.length);
    					cursorPos += inReplyTo.length;
    					myField.focus();
    					myField.selectionStart = cursorPos;
    					myField.selectionEnd = cursorPos;
    				}
    				else {
    					myField.value += inReplyTo;
    					myField.focus();
    				}
    			}
    			//]]&gt;
    		&lt;/script&gt;
    	&lt;?php
    	}
    
    	public function r2_reply($reply_link) {
    		 $comment_ID = '#comment-' . get_comment_ID();
    		 $comment_author = esc_html(get_comment_author());
    		 $r2_reply_link = 'onclick=\'return r2_replyTwo(&quot;' . $comment_ID . '&quot;, &quot;' . $comment_author . '&quot;),';
    		 return str_replace(&quot;onclick='return&quot;, &quot;$r2_reply_link&quot;, $reply_link);
    	}
    }
    
    new AtReplyTwoHELF();
    

    Most of the javascript stuff is copy/pasta for me (just left of witchcraft), and I left it barebones (no configurations) on purpose. Simple is as simple does.

    Suggestions and tweaks welcome!

  • I Don’t Understand CloudFlare

    I Don’t Understand CloudFlare

    If you know the answer to all this, I’d love to hear it, because I can’t figure this out. What’s the real point of CloudFlare?

    Fairly recently I was reading Tony Perez’s post about CloudFlare vs Incapsula vs ModSecurity. As regular readers may know, I am frenemies with Mod_Security. I often want to kill it with fire, but I never disable it entirely because it protects my site from hackers. By using Mod_Security I limit my chances of having Bobby Tables kill my site.

    Using Mod_Security gives you some protection from simple SQL injections, but also XSS attacks. You can integrate it with things like Project Honeypot. As they put it:

    ModSecurity™ is an open source, free web application firewall (WAF) Apache module. With over 70% of all attacks now carried out over the web application level, organizations need all the help they can get in making their systems secure. WAFs are deployed to establish an external security layer that increases security, detects and prevents attacks before they reach web applications. It provides protection from a range of attacks against web applications and allows for HTTP traffic monitoring and real-time analysis with little or no changes to existing infrastructure.

    And you know what? It really does all that.

    So what’s CloudFlare? It’s an intermediary between your site and the world which caches your site, compresses data, and gives people the fastest version of your site. In the event your site is down, they’ll serve cached versions. They even give you a pretty picture.

    CloudFlare

    The first time I heard about this, I arched my eyebrows in surprise and confusion. I’m going to make my site faster by putting more layers between the reader and my content? That means instead of just relying on my server and host to be fast, serve compressed pages, keep the lights on, keep a speedy connection to the Intertubes, and do all the things that needs to happen for the magic pipe between my website and you guys, I’m doing all that and trusting someone new to help me do it better. Interesting, Captain. How are they doing this?

    squire3 CloudFlare has a few tricks to do this: CDN (content loads faster if it’s stored local to the people visiting the site), content optimization (minimizes and compresses page content), security (protecting you from DDOS and SQL injection), and analytics.

    Except when I look at that list I think that I already use mod_pagespeed to minimize and compress my content, mod_security to protect me (also Config Server Firewall for the DDoS stuff), and analytics is done by my server or Google. For me, that means the only thing they’re offering that I don’t have is a CDN. I read up on CloudFlare’s CDN, and they tout not having the weight of 15 years legacy crap. That’s a tricky edge to dance on, since they also don’t have the experience of those 15 years, or the network. In fact, looking at their network map, they have nothing in South America. Guess what the number two location is for people visting my sites? Brazil.

    And this, my children, is why you study your stats to understand who is visiting your site, where from, why, and with what browsers. Right away I can see that CloudFlare, while interesting, doesn’t seem to have any benefit for me. If I decide that I want a CDN, it’ll probably cost me around $30 more a month, minimum, for my sites and what they have on them today. Oh but wait, you say, CloudFlare is free?

    Yeaaaah. I don’t trust free services very much. A free app, once I download it and put it on my server, I keep. A free service is hosted on someone else’s server, at their whimsy, and is supported as they see fit. Yes, this means I don’t trust Facebook or Twitter. A free service is interesting only in that it lets me try it before I buy it, and for that, I approve of how CloudFlare does it. But the problem is today I went to a website and saw this:

    cloudflareddos

    What did I do? I didn’t visit this website. They can brag about the whole 30ms response time all they want, but if I went to a website and hit a barrier like that, I stop because it’s getting in the way of my surfing. That was my initial quandary about CloudFlare after all. How can it provide all these awesome things without getting in the way? And it can’t for everyone. At first I thought it was because I was going through bit.ly and it worried I was a spammer (okay, fair enough), so I tried manually, and it was the same problem. I just went to the page normally now, and it’s been well more than “5 seconds” and the site still hasn’t loaded.

    I fundamentally dislike anything that causes my users to do ‘more’ to get to my content. I think that it’s more harmful than a slow site, and it’s more harmful than letting these bad eggs visit my site. The right place to block a naughty person is when they’re doing something naughty. If my IP is a range of DDoS attackers, that’s one thing. You shouldn’t be detecting as the page loads, delaying me almost 30 seconds, and then loading the page. This delay is supposedly for my protection (me the site runner, not the visitor). Okay then, what are they protecting me from?

    Part of CloudFlare’s service is something called a Web Application Firewall (WAF), which is fancy-speak for saying their computer looks at what people are coming to your site to do, what data they’re sending, and tries to figure out if they’re nice visitors (which it should let through) or naughty hackers (which it should block).(From WP Shine Cloudflare: Early Reports Question Effectiveness as Website Security Tool)

    WAF came up before, with Mod_security. And at this moment, I go to a picture. Here’s what Tony parsed from the data:

    Screen Shot 2013-03-20 at 10.10.03 AM

    He asked on Google+ what we took from that article, and my reply was “That the months I spent mastering mod_security was totally worth it.” If you don’t trust Tony’s numbers, you can read the full report on slideshare for yourself. Tony has the same feelings about Captcha as I do, by the way, though less strongly. I despise it more than I hate hotlinkers, and I hate hotlinking. Captchas are the worst barrier between content and consumer that was ever invented. They don’t work, they’re not accessibility friendly, and they are rarely implemented well. Hotlinking may be theft, but Captchas are shouting “No soup for you!”

    Which brings me to my point.

    What is CloudFlare doing? In plain english, can someone explain to me how it would benefit me? Ignoring the CDN aspect, the only WAF part I can see benefiting me is that CloudFlare (and Incapsula for that matter) essentially crowdsource the list of people who are ‘bad’ and shouldn’t access my site. Which is cool, and that I certainly like. It’s sort of like a Project Honeypot for baddies (and by the way, that would be a nice feature). Having the world bring in the list of bad people, as well as their patterns, and sharing that back out is a great way to keep everyone up to date quickly and seamlessly.

    I really just can’t see why I’d ever want to use CloudFlare. It would certainly be a cheap and easy way to put some possible gain on my site, but in the long run I feel that managing these things myself (or hiring someone to do it) would be a better business solution. It saves me from the dread blackbox spam killer, which means I always know what’s going on. Now I know not everyone is capable of handling all this themselves, but from what I’ve seen, most webhosts already have mod_security running. So lets drop the WAF argument from the table, and we come down to the best thing CloudFlare’s doing is acting as a CDN and compressing content. That’s not good enough for me. At that point, you may as well use Google’s PageSpeed Service

    I’m sure there are great reasons for using CloudFlare, but I just can’t see it.

    Quick ETA… Talking to a coworker, it occurred to us that I may just not be their audience. I’m too big already and I took care of most of what they do. I can look at this and think “If I just have a small site and I want to speed it up on a shared server where I have no root nothings” then it looks way more reasonable. But I’m not.

  • Instagram oEmbed

    Instagram oEmbed

    This isn’t hard, so it’s just a nice example of how to handle instagram.

    wp_oembed_add_provider('#http://(www\.)?instagram\.com/.*#i', 'http://api.instagram.com/oembed?url=', true);
    

    Per usual, I have a file called oembeds.php in my mu-plugins folder, where I toss all these. This will work with and without www in the URL. I will warn you, Instagram’s embed is ugly! Here’s http://instagram.com/p/QU1OfbHBTe/

    http://instagram.com/p/QU1OfbHBTe/

    See? No formatting, nothing to tell you it’s bloody Instagram.

    Meanwhile, here’s the tweet it came from:

    Much nicer, eh? Of course, Instagram is weird, in that they don’t let you browse images.