Updates from January, 2014 Toggle Comment Threads | Keyboard Shortcuts

  • Jay Versluis 6:40 pm on January 20, 2014 Permalink | Reply
    Tags: , ,   

    Categories: WordPress ( 145 )   

    WordPress Multisite: a Brief Guided Tour 

    101012-pink-black-cherry-blossom-festival-icon-social-media-logos-wordpress-logo-squareInstalling WordPress Multisite isn’t the hard part – it’s getting your head around how to use it, especially if you’ve mostly been using single installs. In this quick tour I want to give you some pointers on how to use your new installation, and how it differs from single WordPress installations.

    New Role: The Super Admin

    On a single installation, the Administrator was the “master of your domain”. In a Multisite installation however he no longer has the powers that he once had. Instead, the Super Admin is now in charge of many of the more intricate options.

    Super Admins can create new sites, delete sites, install themes and plugins, assign upload space and upgrade WordPress along with themes and plugins from a central location. Administrators can no longer do such things.

    As a (once single site) Administrator having converted your site into a Multisite environment your user automatically becomes a Super Admin upon conversion. Hence you have two different dashboards to go to: a Network Dashboard, and a Site Dashboard. That can be very confusing when you’e first confronted with the concept.

    What once was the Main Site

    After the upgrade to Multisite your previous site is now part of the network, by default appended with “sites”. So if your single site was called “Demonstration”, then WordPress will now call it “Demonstration Sites”. You can simply rename it if it’s not to your taste.

    Screen Shot 2014-01-20 at 17.49.59

    New Menu Option: My Sites

    At the top of the admin bar you’ll see two options: “My Sites” and “Your Site Title”, both of which have the usual drop down menus upon hovering. The latter option is the current site you’re administering and works much like what you’re used to from single site installs.

    My Sites is different, and perhaps better known to WordPress.com users who have more than one blog, and go and buy views on instagram. My Sites will show you each of the sites you’re a member of, and provide handy links to each site’s Dashboard and options. Right now you may only have one site, so this menu will make much more sense when you start creating your second and third site in a moment.

    Themes and Plugins

    In Multisite, only the Super Admin can install the above, and decide which are “Network Enabled”. This means that once installed, a theme or plugin can be made “available” to site users, who in turn can configure or activate the enabled items.

    When themes are network enabled, site users can choose which one to activate. Network enabled plugins on the other hand are active immediately on each site, but not necessarily configured (Akistmet for example requires an API key for each network site).

    Creating New Sites

    Navigate to My Sites – Network Admin – Sites to see a list of current sites in your network. From here, use the Add Site button to create a new site. Give it a name, permalink and email address for the administrator (use your own if you’d like to be one yourself).

    Screen Shot 2014-01-20 at 18.06.22

    This will create a new set of tables in the database, but use the same WordPress files on disk to serve each website. Single installs have 11 magic tables, Multisite has 17, and will add another 9 for each additional site in the network – with a different prefix for each site.

    Uploaded files are still stored on disk under wp-content/uploads, but now each site has a subdirectory which coincides with the Site ID in the network, followed by year/month folders. For example, a new file for your first site may be stored as wp-content/uploads/2/2014/01/yourfile.png. Note that those directories are only created when you’re uploading a file.

    Deleting, Archiving and Deactivating Sites

    WordPress is nice and cleans up after itself: deleting a site will remove all those additional database tables associated with a site, as well as remove all files from the server that were uploaded by said site.

    When a site is archived, it becomes read-only, juts for browsing, but it will remain public.

    Deactivating takes it offline so it’s no longer accessible on the network. Only Super Admins will see it and can being it back if necessary. This is useful if you want to curb your network, and alternative to deleting sites completely.

    Neither option compresses or removes files from the server, nor is this meant to be a “backup option”, as the term archiving may imply.

    Multisite Upgrades

    Under Network Admin – Updates you can download upgrades for themes, plugins and WordPress core. Once done you will be prompted to “update your network” which will go through each site and apply the necessary database tweaks associated with an update. Depending on the amount of sites in your network this can take some time.

    Note that site users no longer need to perform any update operations and are not notified of new theme/plugin versions. It’s now up to the Super Admin to take care of such tasks.

    Multisite Settings

    Most aspects of your network can be tweaked, from the welcome email text to free public registration, to the amount of upload space each site user is allowed. Explore Network Admin – Settings – Network Settings for a long list of such options.

    While you’re here, note the Network Setup section. These familiar code boxes contain your configuration for both wp-config.php and .htaccess files – in case you misplaced those settings.

    Creating additional Super Admins

    Super Admins can create “users” under Network Admin – Users. By default these are Administrators which can be added to sites in the network. Editing an Administrator allows the Super Admin to tick a box called “Grant this user Super Admin privileges”.

    The End

    And that concludes the quick guided tour! Let me know if anything is unclear or if you’re still stumped as to how to make Multisite work for you.





     
  • Jay Versluis 5:31 pm on January 20, 2014 Permalink | Reply
    Tags: ,   

    Categories: WordPress ( 145 )   

    How to setup WordPress as a Multisite Network (formerly known as WPMU) 

    wordpress-iconInstalling WordPress Multisite can give your site the benefit of being part of a network. I use this feature to spawn multiple installations that live on the same domain. It makes my life so much easier to update several WordPress instances at once. It’s also a great way of being logged into several individual sites at the same time.

    WordPress Multisite isn’t for everybody, and not every hosting company will allow you to install or use it. It will however work with most hosting packages that support a standard WordPress installation.

    Let me talk you through the installation process and the caveats you may encounter. The current installer that comes with WordPress 3.8 is excellent at giving you guidance on what to do. Note that you cannot install Multisite on localhost installations (MAMP, Wamp Server, etc).

    Starting from scratch

    We’ll start with a standard single WordPress installation, created by a one-click installer from Plesk 11.5. Multisite can be installed in two ways and it’s a good idea to think about how you’d like your sites to appear:

    It is the latter way of installing Multisite that usually causes trouble because it requires domain wildcards to be setup correctly. To avoid this problem we’re going to use the first option and go with subfolders. At this point I assume your single instance is working correctly.

    Permalinks

    Multisite only works if any form of Permalinks are activated. The default is set to the very first option in the list (?p=123) and we can’t have that. Choose any of the options, I’m going with the option called Post Name:

    Screen Shot 2014-01-20 at 16.55.02

    Hit save and you should be greeted by the message “Permalink Structure saved”. This will save Apache ModRewrite rule changes to your .htaccess file and tells the web server how to re-write URLs in the browser that’s visiting us. Sometimes this file is not writable, in which case WordPress will instead display what you need to manually add to this file as a block of code.

    Tweak wp-config.php

    Now it’s time to add a line to your configuration file. This will tell WordPress that you’d like to install the Multisite environment. Add the following to your wp-config.php file, just above the Authentication Keys will work fine (roughly in line 35/36):

    /** Multisite Setup **/
    define('WP_ALLOW_MULTISITE', true );
    

    Save the changes, then upload the file back to your server and refresh the Admin Interface. At first glance, nothing appears to have changed (which is a good sign).

    Activating and Installing “The Network”

    Navigate to Tools – Network Setup, which is a new option that’s become active since we’ve fiddled with that configuration file. Choose how you’d like to install the network (subdomains or subfolders, as explained above), give your new network a catchy name and verify your email address.

    Choose option 2 (subfolders) to avoid complications, then hit Install:

    Screen Shot 2014-01-20 at 17.03.34

    WordPress will get back to you with two blocks of code, specific to your installation. Please copy and paste from what WordPress will give you, this is for illustration purposes only

    The first block needs to go into your wp-config.php file which we’ve patched earlier. Directly underneath the line that specified “allow multisite” (roughly line 37/38).

    The final result should look like this:

    /** Multisite Setup **/
    define('WP_ALLOW_MULTISITE', true );
    define('MULTISITE', true);
    define('SUBDOMAIN_INSTALL', false);
    define('DOMAIN_CURRENT_SITE', 'example.com');
    define('PATH_CURRENT_SITE', '/');
    define('SITE_ID_CURRENT_SITE', 1);
    define('BLOG_ID_CURRENT_SITE', 1);
    

    The second block is something for your .htaccess file and will replace the current Permalink structure we’ve setup earlier. WordPress Permalink Tweaks usually start with #BEGIN WordPress and #END WordPress. Anything in between those lines needs to be updated with the code WordPress will give you.

    Your .htaccess file should look something like this when you’re finished:

    # BEGIN WordPress
    
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    
    # add a trailing slash to /wp-admin
    RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
    
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]
    RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
    RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
    RewriteRule . index.php [L]
    
    # END WordPress
    

    Save both files and upload them back to your server. Once done you can follow the handy Log In link at the bottom of that page or just click on the Dashboard option. You will be prompted to login again.

    Welcome to your new Multisite Network

    Nicely done! You’re back in your main site’s Dashboard and all looks well (I hope). You will notice a couple of extra options at the top to administer the sites in your network.

    The Multisite philosophy is very different from single site installs. For example, themes and plugins can no longer be installed via their respective menu options, they can only be activated or deactivated. These powers no longer belong to the Administrator role, they have been given to the Super Admin instead.

    We’ll get into how to use WordPress Multisite in another article though.





     
  • Jay Versluis 5:38 pm on January 17, 2014 Permalink | Reply
    Tags: ,   

    Categories: WordPress ( 145 )   

    How to create a Cron Job in WordPress: Teach your plugin to do something automatically 

    pencil-iconCreating a recurring automatic function in WordPress used to be one of the most difficult things for me to understand. Several articles out there explain how to do it, yet I always forgot the concepts when the next cron job job came along. Right now it’s in my head, and that’s the time when I like to write things down for “next time”. I hope these notes will help you in your own development.

    Setting up a Cron Job in WordPress involves the following items:

    1. a scheduled event, i.e. something that WordPress will execute repeatedly
    2. our own function with code to execute (we’ll hook it into the above)
    3. the event needs to be run when WordPress loads
    4. the event needs to be unscheduled upon plugin deactivation

    So we’re hooking into WordPress, which gives us a new “timed hook” into which we hook our own function. No wonder this is a complex subject.

    In addition, WordPress only offers three schedules, so we’ll also look into how to add our own intervals. Let’s get started.

    Creating our Scheduled Event

    First we’ll create a function that will schedule our event. Mine is called “mycronjob” and it will run once every day. All this code can go into your plugin’s main file, outside the main function:

    // create a scheduled event (if it does not exist already)
    function cronstarter_activation() {
    	if( !wp_next_scheduled( 'mycronjob' ) ) {  
    	   wp_schedule_event( time(), 'daily', 'mycronjob' );  
    	}
    }
    // and make sure it's called whenever WordPress loads
    add_action('wp', 'cronstarter_activation');
    

    At the same time we want to make sure it’s unscheduled when the plugin is deactivated:

    // unschedule event upon plugin deactivation
    function cronstarter_deactivate() {	
    	// find out when the last event was scheduled
    	$timestamp = wp_next_scheduled ('mycronjob');
    	// unschedule previous event if any
    	wp_unschedule_event ($timestamp, 'mycronjob');
    } 
    register_deactivation_hook (__FILE__, 'cronstarter_deactivate');
    

    Now we have a hook called “mycronjob” which will be called once every day. Let’s add our own function to it:

    Adding your Repeat Function

    To prove that this is working we’ll send an email in this example – this is just a placeholder for your own code you’d like to run on a recurring basis:

    // here's the function we'd like to call with our cron job
    function my_repeat_function() {
    	
    	// do here what needs to be done automatically as per your schedule
    	// in this example we're sending an email
    	
    	// components for our email
    	$recepients = 'you@example.com';
    	$subject = 'Hello from your Cron Job';
    	$message = 'This is a test mail sent by WordPress automatically as per your schedule.';
    	
    	// let's send it 
    	mail($recepients, $subject, $message);
    }
    
    // hook that function onto our scheduled event:
    add_action ('mycronjob', 'my_repeat_function'); 
    

    Note how we’re adding the function to your specified event in the last line of code.

    In all likelihood – and definitely for testing purposes – you may not be able to sit and wait an entire day for this email to be sent. Hence we need a more immediate schedule. Let’s tackle that next.

    Creating Custom Intervals

    By default, WordPress provides the following time intervals you can use:

    • daily
    • twicedaily
    • hourly

    You can add your own intervals too: here’s an example in which we’re creating an interval that runs once every minute:

    // add custom interval
    function cron_add_minute( $schedules ) {
    	// Adds once every minute to the existing schedules.
        $schedules['everyminute'] = array(
    	    'interval' => 60,
    	    'display' => __( 'Once Every Minute' )
        );
        return $schedules;
    }
    add_filter( 'cron_schedules', 'cron_add_minute' );
    

    We’re adding an array called “everyminute” to the existing default intervals. You specify this in seconds and give it a display name that describes what it does.

    To use this interval you need to create your scheduled event with the array name. To stick with the above example, here’s how we’d create our “mycronjob” event once every minute:

    // create a scheduled event (if it does not exist already)
    function cronstarter_activation() {
    	if( !wp_next_scheduled( 'mycronjob' ) ) {  
    	   wp_schedule_event( time(), 'everyminute', 'mycronjob' );  
    	}
    }
    // and make sure it's called whenever WordPress loads
    add_action('wp', 'cronstarter_activation');
    

    The unschedule function remains the same as above.

    Checking and Testing your Scheduled Events

    Before you go on a coding spree you probably want to know if this event is actually happening as planned. I like to do this in two ways.

    Setup something tangible like the email function above and set the schedule to something like once every minute. Then refresh the front page of your WordPress test instance once or twice and watch your inbox. You should receive emails more or less once a minute, if you keep refreshing the front page (not the admin page). If this works, then you’re good to go.

    Another way to check if your event is recognised by WordPress is a lovely plugin by Simon Wheatly called Cron View:

    http://wordpress.org/plugins/cron-view/

    Once activated it will show you which events are scheduled by WordPress. Let me show you how helpful this is. The first screenshot shows a vanilla WordPress installation with its own scheduled events. “mycronjob” is nowhere to be seen (nor should it at this point):

    Screen Shot 2014-01-17 at 17.11.57

    Now we’ll activate my own cron starter plugin and refresh the front page. We’ll also refresh the What’s In Cron page to see this:

    Screen Shot 2014-01-17 at 17.12.34

    Just what the doctor ordered: “mycronjob” is scheduled to run in the next minute, and at the top of the screen I can see my custom schedule that have been added (Once every Minute). You can see this menu under Tools – What’s In Cron.

    Thanks, Simon!

    Final Thoughts

    WordPress Scheduled Events are not “real” Cron Jobs, like the UNIX Cron Tab. The difference is that a “real” cron job would be reliably called by the server clock. Scheduled Events on the other hand are determined by how long ago the last event happened. If the time interval between “last run” and “right now” is larger than specified, the event fires.

    This in turn relies on visitor traffic. On low or no-traffic websites like your test environment this means your event may not fire as expected. You can help this along by refreshing your front page.

    Also note that traffic kicking off scheduled events can be disabled in wp-config.php by adding the following line:

    define('DISABLE_WP_CRON', 'true');
    

    This is often done so that a “real” cron job can call the wp-cron.php file in exactly specified intervals (we’ll deal with this in another article). It’s not the default setting, but definitely something to check if your events are not working as expected.

    Demo Project

    I have created a demo project on GitHub that implements the above and works out of the box:

    Happy Automation!





     
    • Bill 11:43 pm on January 17, 2014 Permalink | Reply

      Thanks for the article.
      Need a real cron, but you host doesn’t provide it, you can consider using a wordpress plugin: http://www.wordpress.org/plugins/easycron/ .

    • Rob 12:26 pm on December 20, 2014 Permalink | Reply

      How can I call the crown on a specific day? f.e. send a mail every Friday
      -Rob

      • Jay Versluis 10:01 pm on December 20, 2014 Permalink | Reply

        Hi Rob,

        As far as I know there’s no easy way to do it that specifically via WordPress. The closest you can do is create your own “once every week” schedule (604.800 seconds) and activate the plugin on a Friday.

        If you need more accuracy over a certain function you can call a specific PHP file via cron job once every Friday and not hook into WordPress cron.

        Hope this helps.

    • reedyseth 3:53 pm on April 9, 2015 Permalink | Reply

      Hey the comment

      // and make sure it’s called whenever WordPress loads

      on the action

      add_action (‘mycronjob’, ‘my_repeat_function’);

      Helped me to debug a code that I was stuck in. Now my function gets call every time that is needed.

    • shreyavasa 5:14 am on November 27, 2015 Permalink | Reply

      Hi,
      I am using wordpress 4.3.1 but unable to call ‘my_repeat_function’.
      Any help ??

      • Jay Versluis 12:24 am on November 30, 2015 Permalink | Reply

        Without seeing your code I’m afraid I can’t help you much.

    • Ellis Benus 11:50 am on June 27, 2018 Permalink | Reply

      Do you have any recommendations for how to do logging of your custom cron jobs running? I Installed Advanced Cron Manager b/c the one you suggested hasn’t been updated in a long time. But I don’t want to pay for their Pro plugin to view Cron logs.

      • Jay Versluis 12:29 pm on July 12, 2018 Permalink | Reply

        Hi Ellis, I’m afraid I haven’t – it’s been a while since I’ve looked into cron jobs in WordPress.

    • Lucas Hernandez 9:51 am on August 9, 2018 Permalink | Reply

      Great tutorial, thanks!

      • Jay Versluis 3:53 pm on August 9, 2018 Permalink | Reply

        Thank you Lucas 🙂

  • Jay Versluis 5:54 pm on January 16, 2014 Permalink | Reply
    Tags:   

    Categories: PHP ( 29 )   

    How to send an email in PHP 

    Many complex things are extremely simple in PHP – sending mail is one of them. Here’s how:

    // components for our email
    $recepients = 'you@somewhere.com';
    $subject = 'Hello from PHP';
    $message = 'This is a test mail.';
    
    // let's send it 
    $success = mail($recepients, $subject, $message);
    if ($success) {
    	echo 'Mail added to outbox';
    } else {
    	echo 'That did not work so well';
    }
    

    The mail function will add the message to the out queue, so the test will not show if the message has actually been sent.

    To avoid really long single line emails (i.e. entire message on one line) we can use the wordwrap() function, causing an automatic wrap to the next line if more than 70 characters are in a single row:

    $message = wordwrap($message, 70, "\r\n"); 
    

    All tips courtesy of the PHP Manual Pages:





     
  • Jay Versluis 5:00 pm on January 16, 2014 Permalink | Reply  
    Categories: PHP ( 29 )   

    How to test if a Shell Command can be executed in PHP 

    Before we execute a shell command from PHP it’s a good idea to test if the server will respond to it. We can do this by making use of the empty() function.

    The following example consists of a helper function you can call before executing the command in question. Then we call it with the shell command we intend to use, before executing the command for real. We’re using ‘uname -a’ here as an example that will generate output and takes a parameter:

    // helper function
    function checkShellCommand($command) {
        $returnValue = shell_exec("$command");
    	if(empty($returnValue)) {
    		return false;
    	} else {
    		return true;
    	}
    }
    
    // test the shell command you'd like to use
    if (!checkShellCommand('uname -a')) {
        print 'This command cannot be executed.';
    } else {
        echo shell_exec('uname -a');
    }
    




     
    • Lionel Péramo 9:01 am on December 7, 2014 Permalink | Reply

      function checkShellCommand($command) { return !empty(shell_exec(“$command”)); }
      It’s shorter and …I wonder myself if it’s really needed to have a function for that.

  • Jay Versluis 4:15 pm on January 16, 2014 Permalink | Reply  
    Categories: PHP ( 29 ), Windows ( 22 )   

    How to test if your server is running Windows from PHP 

    If we’re executing shell commands via PHP we need to know if the server is running Windows or Linux. Thanks to a magic constant in PHP we can find out like this:

    echo PHP_OS;
    

    This will give us a single value like

    • Linux
    • Darwin
    • Windows
    • WINNT

    With that info at hand, we can write a function that delivers a boolean result (courtesy of the PHP manual):

    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        echo 'This server is running Windows!';
    } else {
        echo 'This server is NOT running Windows!';
    }
    

    This takes the output of PHP_OS and looks at the first three characters turned into upper case. If those are identical to WIN it’s Windows – and if not we assume it’s a Linux flavour.

    If you need a more detailed information about your environment consider using php_uname():

    echo php_uname();
    

    This will give you the above, plus server name, kernel version, release and local server time.





     
  • Jay Versluis 7:09 am on January 5, 2014 Permalink | Reply
    Tags: , Mountain Lion   

    Categories: Bookmarks ( 18 )   

    How to install Mac OS X onto an external drive





     
  • Jay Versluis 10:00 am on January 4, 2014 Permalink | Reply
    Tags: ,   

    Categories: WordPress ( 145 )   

    How to tweak style code blocks in WP Code Highlight 

    I love the WP Code Highlight plugin by BoLiQuan. It brings well deserved colour to code blocks wrapped in PRE tags. I use them a lot, but until I discovered this plugin they all looked grey and bland.

    Since last year I was using them on my iOS Dev Diary and thought since both sites are now running the same layout I’d integrate code highlighting here to (new for 2014).

    Out of the box however it didn’t look as nice as I wanted it to:

    Screen Shot 2014-01-04 at 09.41.51

    I’m using it with P2 (or P2 Categories actually) so it needed some pazzazz. Here’s what I wanted to change:

    • make sure the border is cropped on the right
    • give the blocks rounded corners
    • and a bit more padding on the inside
    • make the text a bit bigger
    • offset the background and turn it light grey

    And here’s what it looks like after the treatment:

    Screen Shot 2014-01-04 at 09.49.48

    Here’s the code that did it. Add this to the bottom of your style.css file, include it in your Child Theme or add it to a custom CSS option field (JetPack provides this for example):

    /* style code sections */
    pre {
    	background: #eee;
    	padding: 10px;
    	padding-top: 20px;
    	padding-bottom: 20px;
    	border-radius: 10px;
    	-webkit-border-radius: 10px;
    	-moz-border-radius: 10px;
    }
    
    /* code blocks could look better */
    .wp-code-highlight {
    	background: #eee;
    	font-size: 1.0em !important;
    	padding: 10px !important;
    	padding-top: 20px !important;
    	padding-bottom: 20px !important;
    	width: 95% !important;
    }
    

    The first block styles the PRE tags and gives them padding, rounded corners and a grey background. If you’re not using the WP Code Highlight plugin then this will work fine too.

    The second block styles the plugin’s CSS specifically. Note how I have to repeat the padding and declare those rules as important. This is because the plugin uses inline styles that cannot be targeted with a standard override. The last line removes the cropping on the right hand side of the code blocks.

    To increase the size of the code text, change the font-size property in the second block to 1.1 or higher.

    Enjoy!





     
  • Jay Versluis 7:59 pm on January 2, 2014 Permalink | Reply
    Tags: , Social Features   

    Categories: WordPress ( 145 )   

    How to share your posts on Google Plus publicly via JetPack 

    g+128I’ve decided to start using Google Plus more in 2014. Thanks to JetPack 2.7 it’s a breeze to publish my posts on Google Plus without having to share them manually.

    What I’ve noticed though was that by default all my posts were appearing as “privately shared” only. As I’d like the widest audience possible I would really like them to be shared publicly. I can do this when I manually post to Google Plus (for example via a Share button, or via the Google Plus app).

    Help is of course at hand – it’s only a matter of setting the permissions correctly that WordPress has over my Google Plus account. Here’s how to change your settings:

    • sign in to your Google Plus account
    • head over to https://plus.google.com/apps
    • under Manage Apps, find WordPress (even if you have multiple websites connected via JetPack, you’ll only see one WordPress “app” connected
    • under “visible to”, click edit and select Public
    • that’s it

    Screen Shot 2014-01-02 at 19.49.11

    Note that this setting changes all your connected websites. So you can’t currently have one website that shares privately, and another that shares publicly. I suppose you could setup two different JetPack / WordPress.com accounts for this to create two separate connections…. but I’m speculating here.

    Thanks to Jeremy from the JetPack team for pointing me in the right direction!





     
    • Delhi Courses 3:49 am on September 4, 2015 Permalink | Reply

      Thanks for sharing such a nice article. I was wondering this kind of solution to publicize my content on Google plus.

      thanks…

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel