Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Mailbag: Chocolate Cake is a Need

    Mailbag: Chocolate Cake is a Need

    Adrian in Florida has a long one! I’m going to break it up.

    I watched your presentation about “don’t use WP MU” have decided I shouldn’t use it but wanted to ask your advice on some other things. First I want to start by pointing out re the presentation:

    • I noticed that for the Wordpress.com network sites I noticed the WP toolbar does show on the sites giving them away as network sites except for one, Gigaom (perhaps there is a way to remove it?)

    • For some of us chocolate cake is a need, not a want.

    No, the cake is a want. And I use that example for a reason. We can joke all we want about how we need the cake, but fact is this: We need food. We want treats. If we can be clear in our hearts about needs versus wants, webdev is much simpler. I don’t need coffee. I like it. I can live without it. I don’t want to and choose not to. I can blog without WordPress. I don’t want to. I choose not to. It’s very important to be clear on needs and wants and choices in life in general.

    As for turning off the .com toolbar on Gigaom, I noticed when I visit there’s a blip where it shows the space for the toolbar and then it’s gone. So that suggests it’s CSS fixing itself. But the answer is “They’re a VIP customer and probably paid out the nose for that.”

    1. I just want to learn one theme/framework to make websites with and not change. I had already paid for Elegant Themes to get Divi which is supposed to be customizable and seems to have good video tutorials, before I saw your recommendation for Studiopress. I don’t know how to tell if I should scrap Divi and pay up again for Studiopress. Would you?

    I like Studiopress a great deal. It’s secure, it’s stable, it’s updated responsibly and reasonable, and Andrea Rennick is one of my BFFs. Divi I dislike because of how they handle sessions. But whichever you use is up to you. If you want a free theme to start with, I’d pick up Theme Hybrid. Justin’s code is second to none.

    2. I want to be able to make each page in my Wordpress site show up under its own subdomain. I’ve tried a few plugs like “page links to” which doesn’t work. I saw that there are some plugins that do this for categories. Do you know a plugin that enable each page resolve to a subdomain otherwise do you recommend one of the category plugins over another?

    This stems from his URL design which is page.example.com and … I just wouldn’t. It’s a waste of time and effort and locks you into a categorization that will be insane to unroll later.

    Now as a category that’s less weird and you can try one of these plugins:

    • https://wordpress.org/plugins/subdomains/
    • https://wordpress.org/plugins/main-category-as-subdomain/
    • https://wordpress.org/plugins/wp-subdomains-revisited/

    I still wouldn’t use Multisite unless you really enjoy logging into a separate site for each post and not having an easy way to cross reference.

    3. Is there a plugin out there that allows different people to receive ad revenue for their posts? We have two different writers for one website, each should get ad revenue related to each’s own posts on the same website.

    This is actually why I bothered to answer. This is a cool question and I had no idea at all when I first read it.

    Turns out, yes you totally can have separate ads per author. If you’re using Google AdSense (you didn’t say), then try Multi Author Adense, which looks like you could set the code per author. There’s also Revenue Share which may be a little simpler.

    Good luck!

  • HTTPS and WordPress

    HTTPS and WordPress

    Really there’s a right way and a not-quite-as-right way to handle HTTPS on WordPress. It’s not that hard to do, and if your whole site is going to be HTTPS, then the easiest way is to change your home and site URLs to be https://example.com/ and put define( 'FORCE_SSL_ADMIN', true ); in your wp-config.php file. Then you should (if this is an existing site) search your database for the old HTTP url and change that to HTTPS.

    Seriously, that’s it. That tells WordPress to be HTTPS all the way and you’re done. Of course, that doesn’t actually work 100% for everyone, because there are some silly plugins and themes that do things like this:

    add_action('wp_enqueue_scripts', 'enqueue_google_maps');
    function enqueue_google_maps() {
      wp_enqueue_script('google-maps', 'http://maps.googleapis.com/maps/api/js?&sensor=false', array(), '3', true);
    }
    

    The problem there is they’ve defined the script as HTTP and if your site is HTTPS then you’re going to get mixed content messages. And the real issue here is that means your connection is only partially encrypted! That non-encrypted content is accessible to sniffers and can be modified by man-in-the-middle attackers. This, clearly, is not safe anymore. The right way to do your enqueues is with protocol relative URLs:

      wp_enqueue_script('google-maps', '//maps.googleapis.com/maps/api/js?&sensor=false', array(), '3', true);
    

    Alternately you can just use the HTTPS url, because that won’t break HTTP visits and it won’t make anything less secure.

    But. Since you really can’t go in and edit all your themes and plugins, the plugin WordPress HTTPS is the way to go. That can force everything around. I know it’s not updated in a long time, but it still works. I keep thinking I’ll fork and clean it up… Well in my free time. The point of that plugin is that it lets you force everything to HTTPS, and will rewrite things on the fly. It’s a good idea.

    Instead of using the plugin, I’ve seen a lot of people do this in their .htaccess:

    RewriteEngine On 
    RewriteCond %{SERVER_PORT} 80 
    RewriteRule ^(.*)$ https://example.com/$1 [R,L]
    

    In and of itself, this isn’t wrong. This forces everything HTTP to redirect to HTTPS. The problem is you’re still actually sending data from WordPress over HTTP first, and you’re right back to opening up to man-in-the-middle attacks because the data from WordPress goes from HTTP first and that’s, say it with me kids, insecure!

    Now that said. This should be okay for most things. The POST calls should be sent securely, and all you should see on the return end is everything after that 301 redirect, but we can’t be absolutely sure about this. My buddy Jan used mod_substitute to force HTTPS (back before he moved to nginx). His code looks like this:

    <Location />
     AddOutputFilterByType SUBSTITUTE text/html
     Substitute "s|href="http://example.com/|href="https://example.com/|"
     Substitute "s|href='http://example.com/|href='https://example.com/|"
     Substitute "s|src=\'http:|src=\'|"
     Substitute "s|src=\"http:|src=\"|"
    </Location>
    

    In doing this, he doesn’t need to worry about the HTTPS plugin I mentioned, because it forces everything with a src attribute to be protocol relative. He also doesn’t have to search/replace his content if he doesn’t want to, which makes switching back easier. If you wanted to do that. But as Jan pointed out to me, he switched to nginx because it’s easier and supports variable substitutions.

    Should you use .htaccess or nginx to force https instead of a plugin? That’s totally up to you. I use the plugin since I trust it to only mess with WordPress and not anything else I may have lying around. Also since my domains are often more than just WordPress, it’s a little easier for me to segregate their control. The flip side to this is that WordPress doesn’t redirect http traffic.

    By this I mean if you turn your whole site to HTTPS properly, you can still go to http://example.com/this-is-a-page/ and WordPress will load it as HTTP. This is and is not a bug. WordPress is (properly) trusting your server to tell it what it should be. Your server is saying “Be HTTP or HTTPS! Whatever!” Now there is a trac ticket to have FORCE_SSL really force SSL but that’ll be a while because there are a lot of complications in that change.

    So yes, for now, I would use .htaccess to add an extra later of SSL forcing, but with a bit of caution. If you’re proxying HTTPS (like you’re on a Varnish cache behind something like Pound or nginx) then you may need to use this code for your .htaccess redirect.

    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
    

    The reason for this is Apache can’t always see SSL if it’s not in charge of it (because it’s proxied or handled by a load balancer), and to teach it where it really lives. The trick there is the code I just showed you may not be right because every server’s a little different. There’s a great StackOverflow post on the problems of redirect loops while forcing https that you should read.

    Good luck, and safe HTTPSing!

  • Mailbag: Finding A Rogue WordPress Setting

    Mailbag: Finding A Rogue WordPress Setting

    After helping someone track down a weird WordPress setting, he asked the logical question:

    How did you even find that!?

    The issue was that a person was missing the menu option to edit their themes. I asked if they were also missing the menu option for editing plugins. As soon as he said yes, I knew it had to be the define to disable the plugin and theme editor:

    define( 'DISALLOW_FILE_EDIT', true );

    That literally says “No editing files!” So we looked first in the wp-config.php file for it and came up empty. Now as much as we yell at people for editing functions.php or at themes for creating a mess of settings that aren’t needed, I knew the fastest way to find it was this:

    $ grep -R 'DISALLOW_FILE_EDIT' ./wp-content/
    

    And as expected, that gave me a file: ./wp-content/plugins/ninjafirewall/lib/firewall.php

    Since we had wp-cli, I opened that file and looked for the term:

    // Disable the plugin and theme editor ?
    if (! empty($nfw_['nfw_options']['disallow_edit']) ) {
           define('DISALLOW_FILE_EDIT', true);
    }
    

    Then I ran this: wp option get nfw_options

    If you don’t have wp-cli, just pop into the database and look at the option value for nfw_options — either way you’ll see this:

    array (
      'logo' => 'https://www.example.com/wp-content/plugins/ninjafirewall/images/ninjafirewall_75.png',
      'enabled' => 1,
      [...]
      'disallow_edit' => 1,
      [...]
    )
    

    I’ve snipped out a lot of the data, but you can see that disallow_edit is set to 1.

    We had the user change that setting. Imagine that. It worked!

    The moral of the story? Don’t make settings changes without reading what they do!

  • Mailbag: Headers Already Sent

    Mailbag: Headers Already Sent

    Yasha from Russia asks for guidance!

    Hi I was searching on ways to resolve get header error in WP and saw your posts, which helped a chap with his website. I am a total beginner and having a nightmare with a divi template I am trying to upload. I have tried a ton of solutions on line and nothing worked. I would be grateful if you could provide me with some guidance. Unfortunately I am not in a position to pay you, but should our path cross I would be happy to offer you a few fine Belgian beers. Thank you in advance

    I don’t drink beer (I can’t stand fizzy drinks, I know, it’s tragic).

    I have to preface this with the honest truth. I hate Divi Templates. I’ve reached out to them under my company hat a couple times, never heard back, but I cannot stand their theme because of the first line in header.php for every single theme I’ve ever seen from them.

    <?php if ( ! isset( $_SESSION ) ) session_start(); ?>
    

    Pardon me while I rage flip a table.

    Why do I hate this? Sessions aren’t friends with caching. A session is used to store information for a user and have it accessible across all the pages of your website. Cool, right? The problem is a session is also saying “This user gets unique content and should have a unique experience.”

    Which kinda tells caching, and specifically Varnish caching, to take a long walk. WPEngine doesn’t allow you to use them because of that.

    But all that aside, how do you debug that Headers Already Sent?

    1. Turn on wp_debug
    2. Read the error
    3. Kill the plugin (or theme) causing it

    I hate to say it’s that simple, but it usually is.

    Warning: Cannot modify header information - headers already sent by (output started at /example.com/wp-content/themes/applesororanges/functions.php:60) in /example.com/wp-includes/pluggable.php on line 962
    

    That error means the problem is in the theme applesororanges and you check by swapping themes.

    When you get around to these, it’s a bit messier:

    Warning: Cannot modify header information - headers already sent by (output started at /example.com/wp-includes/functions.php:3560) in /example.com/wp-includes/pluggable.php on line 962
    

    The bit in ‘output started at…’ is a wp-includes folder! It’s unlikely core has bad code, so here you have to turn off all the plugins and switch to a default theme. There’s a reason that’s the way we debug, by the way. It’s hands down the fastest way to see if it’s you or not.

    If turning off all the plugins fixed it, great. Now turn them back on, one at a time, until you break it again.

    Remember! Sometimes it’s the combination of the plugins and theme that caused the problem, so be ready to pick a second best theme or plugin.

  • Mailbag: Delete A New Page In Multisite

    Mailbag: Delete A New Page In Multisite

    From Brige:

    If u can, could u tell me how I can get rid of a new page that created in a subfolder from multisite ? out of my admin reach now. What would be the fastest way ? Should I restore completely to get rid of all WP remnants in order not to fall into this multisite hooking error : “page not found”?

    To be honest, I’m guessing here.

    I’m going to assume that Brige means he wants to auto-delete the ‘Sample Page’ page that WordPress generates when you make a new site.

    WordPress creates a default post (id #1 – Hello World) and a page (id #2 – Sample Page) when a new WP site is created, be it Multisite or not.

    Probably the simplest way would be to hook into wpmu_new_blog() which runs for all new blogs and run this:

    wp_delete_post(2, true);

    That force deletes the post with the ID 2. And since that’s always the sample page, that should work.

  • Static Content Subdomain

    Static Content Subdomain

    I use a lot of different tools to run my websites, and over time I’ve learned what I want is to have my static content, the files that are uploaded and are images, stored separately from my apps. So while I have the basic folders on my domain (wordpress, wiki, gallery) I have a special subdomain called static.example.com for all those images and videos.

    There are a few reasons I do this. First, I like having my images separate. Second, it allows me to establish a cookie-free subdomain for images and that shuts up YSlow’s check.

    Create The Subdomain

    Do this however your host allows. Keep in mind that some don’t allow you to traverse domain folders. If your host creates your domain as /home/user/example.com and subdomains as /home/user/static.example.com you may have to fight a little more with things depending on your setup. If possible, I prefer to put the subdomain folder inside the main web root.

    If you’re using cPanel, by default you get your static subdomain installed at /home/user/public_html/static which is how I like it. This is perfectly accessible by all things but it’s also browsable at example.com/static/ and we don’t want that. Applying a little .htaccess magic will solve this.

    # CDN
    <If "%{HTTP_HOST} == 'example.com' ">
            RedirectMatch ^/static/(.*)$ http://static.example.com/$1
    </If>
    

    Now we’re ready to go!

    Move WordPress Uploads

    This used to be really easy. Go to Settings -> Media and change things. But we removed that to stop people from blowing themselves up. Now there are a couple ways about it. I jumped right over to editing the options by going to wp-admin/options.php and look for upload_path and upload_url_path.

    Setting image location options

    I change upload_path to /home/example/public_html/static/wordpress which is where I’ve moved all my images. Then upload_url_path becomes http://static.example.com/wordpress and I’m done except for fixing my old posts. It’s actually pretty neat that once I put those paths in, the Media Settings page lists them as editable.

    Fixing the old posts takes a little trick though, and you’ll have to search/replace your posts via the database:

    UPDATE wp_posts SET post_content = REPLACE(post_content,'http://example.com/wp-content/uploads/','http://static.example.com/wordpress/');
    

    Or in wp-cli:

    wp search-replace http://example.com/wordpress/wp-content/uploads http://example.com/wordpress
    

    The gotcha here is that since I use SSL for my administration, I had to set up a new certificate for the static domain. Not a big deal right now since I can set up a self-signed, or use StartSSL until Let’s Encrypt is off the ground. It is something to consider though.

    Move ZenPhoto Uploads

    I have to start by warning you that Zenphoto doesn’t like this. When you install it, it puts your images in an albums folder, in the Zenphoto gallery install. This isn’t so bad, but you actually can move it around. You have to look in your zenphoto.cfg.php file (found in zp-data). The default location for your albums is defined by this:

    $conf['album_folder'] = '/albums/';
    $conf['album_folder_class'] = 'std';
    

    Since I want it in the static location, I tell it my folder path based on ‘web root’ and that its ‘in_webpath’ (which tells ZenPhoto to look in the root and not relative), by changing that section to this:

    $conf['album_folder'] = '/static/gallery/albums/';
    $conf['album_folder_class'] = 'in_webpath';
    

    But that means my URLs for images become http://example.com/static/gallery/albums... and I wanted http://static.example.com/gallery/albums... instead. Thankfully the .htaccess rule I used at the beginning of all this covers me there. Looking into this, I understand this is the case because unlike MediaWiki or WordPress, ZenPhoto only has one ‘location’ setting. The other two have path and URL.

    MediaWiki

    This was … weird. Technically all you have to do is set up the folders and change the following values in LocalSettings.php:

    $wgUploadPath       = "/static/wiki";
    $wgUploadDirectory  = "/home/example/public_html/static/wiki/";
    

    The thing that’s weird is that the documentation says you can do this:

    $wgUploadPath       = "http://static.example.com/wiki";
    

    And when you do, the image URLs properly call from the domain name. They just won’t load. When you dig deeper, it turns out that it’s caused by the settings for responsive images. The way it puts in srcset doesn’t seem to like this. So for now I’ve disabled it and my setup is this:

    $wgUploadPath       = "http://static.example.com/wiki";
    $wgUploadDirectory  = "/home/example/public_html/static/wiki/";
    $wgResponsiveImages = false;
    

    End Result?

    All my uploaded content is on my ‘static’ subdomain, separate from everything else, which makes version control even easier. Also now if I ever decide to move things off to a CDN, I’m pretty well set up.

    The real reason I do this is that while some of my content is uploaded via the content management systems I use (WordPress, ZenPhoto, etc), the majority is not. ZenPhoto, for example, is faster to FTP up a gig of images than it is to use a PHP tool. Ditto videos. And because of them, it’s nice to have a separate location I can give access to without allowing someone full rights on all my tools.