Category Archives: wordpress

Getting the WordPress Lifestream plugin to work on my blog

I’ve been thinking about including a digest of Twitter, Delicious bookmarks, Google Reader shared items, and other social activity in my weekly review. This lets me include the information in my archive, and it gives people more opportunities to bump into things I found interesting.

It took a bit of hacking, but I eventually got the Lifestream plugin for WordPress to work, with the help of another webpage and some source code diving. Here’s the code that powers this lifestream page:

<?php $options = array('limit' => 50); $events = $lifestream->get_events($options); foreach ($events as $event) { echo '<li>'; $label_inst = $event->get_label_instance($options); if ($event->feed->options['icon_url']) { echo '<img src="' . $event->feed->options['icon_url'] . '" alt="(' . $event->feed->options['feed_label'] . ') \ "> '; } echo '<a href="' . $event->data[0]['link'] . '">' . $event->data[0]['title'] . '</a> (' . date('D, M j, Y', $event->data[0]['date']) . ')'; echo '</li>'; } ?>

$event->render had been giving me problems, so I specified my own output format. It didn’t automatically pick up icon URLs, so I specified the URLs myself. (Bug: the settings get lost if you re-configure the feed.) The plugin seems to be broken out of the box, but there are enough pieces in there for a geek to make things work.

Because I don’t want to use up two of my one-post-a-day slots on weekly reviews, I’m leaving it as a web page that I can review and manually copy into my weekly review post instead of automatically publishing something.

You can see it in action in last week’s review.

Work in progress. Hope this helps!

Holy cow, that was a lot of mail. So sorry!

I was checking out a few things on my blog today, and I came across my WordPress Post Notification administration page. “Hmm,” I said. “I seem to have misconfigured this.” No e-mail had been sent out since August 2009. I figured out that the configuration directory didn’t have write permissions, enabled it, and went on with the rest of my day.

In the evening, I checked my personal mail on my iPod Touch. Inbox…

323 unread messages. That wasn’t right. I read the e-mail subjects. Holy cow, my blog had sent out every single one of my posts in the past half-year.

Granted, the only people on the list had double-opted-in, but still. I’d be annoyed if that many messages showed up in my inbox too, instead of one at a time.

Sorry!

First step: Control the damage. I moved post-notification out of the way, automatically disabling the plugin.

Second: Figure out the impact. 50 e-mail addresses left. Two nasty-notes.

Third: Gingerly re-enable the plugin after removing the locking directory.

Fourth: E-mail everyone an apology.

Fifth: Write about what happened. Tradeoff: Personal embarrassment versus possibility of saving other people from doing this kind of stuff. Worth it.

Looking at the bright side (because there always is a bright side)… At least I’m learning this now instead of later. And with my blog instead of a customer site. And with a smaller list instead of a megafan community. And… umm… it’s e-mail instead of text messages. Which has happened before. I was writing a Perl script that sent messages, and I had a bug, and there was an infinite loop, and poof! there went the balance on my prepaid card.

Anyway…

I’m sorry.

WordPress admin screen tweaks

A few months ago, I decided to experiment with publishing (mostly) one post a day, scheduling posts to go out at 8 AM. That’s been working well for me, although I now have a backlog of 22 scheduled posts (as of March 11), and I keep reshuffling my queue because I want to post some things sooner.

I started using the Manage Posts page a lot. I checked the dates in the queue and used quick-edit to move posts around. I double-checked missed posts (grr). I looked up posts that got scheduled at 8 PM instead of 8 AM.

And then I decided to code in a whole bunch of things that would make life a little bit easier for me. =) I got rid of columns I didn’t use, increased the number of posts per page, added a few custom columns, and styled things differently. Kaizen: relentless improvement!

Just in case I find this useful in the future, or someone else wants to do something similar:

<?php
/**
 * @package Sacha_Chua
 * @author Sacha Chua
 * @version 0.1
 * Feel free to use this under the GNU General Public License v3 
 * or the Creative Commons Attribution License
 *
 * This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
Plugin Name: Sacha Chua's fixes
Plugin URI: http://sachachua.com/#
Description: Tweaks to make my life easier
Author: Sacha Chua
Version: 0.1
Author URI: http://sachachua.com/
*/

add_filter('manage_posts_columns', 'sacha_manage_posts_columns');
add_action('manage_posts_custom_column', 'sacha_manage_posts_custom_column');
add_action('admin_head', 'sacha_admin_head');
add_filter('edit_posts_per_page', 'sacha_edit_posts_per_page');
define('POSTS_PER_PAGE', 50);

/**
 * Increase posts per page to at least POSTS_PER_PAGE
 */
function sacha_edit_posts_per_page($page) {
  return ($page < POSTS_PER_PAGE) ? POSTS_PER_PAGE : $page;
}
/**
 * Resize the columns
 */
function sacha_admin_head() { ?>
  <style type="text/css">
  .column-time { width: 150px; }
  .column-categories { width: 300px }
  .column-status { width: 100px }
  .scheduled { color: green } 
  </style>
<?php }
/**
 * Remove the tags column
 */
function sacha_manage_posts_columns($defaults) {
  unset($defaults['tags']);
  unset($defaults['author']);
  unset($defaults['date']);
  $defaults['status'] = __('Status');
  $defaults['time'] = __('Date');
  return $defaults;
}

/**
 * Show the time if it's not 8 AM, and show the status and date
 */
function sacha_manage_posts_custom_column($column_name) {
  global $post;
  switch ($column_name) {
    case 'status':
      if ( '0000-00-00 00:00:00' == $post->post_date) {
        _e('Unpublished');
      } elseif ('publish' == $post->post_status) {
        echo '<div class="published">' . __('Published') . '</div>';
      } elseif ('future' == $post->post_status) {
        $time_diff = time() - get_post_time('G', true, $post);
        if ( $time_diff > 0 ) {
          echo '<strong class="attention">' . __('Missed schedule') . '</strong>';
        }
        else {
          echo '<div class="scheduled">' . __('Scheduled') . '</div>';
        }
      } else {
        _e('Last Modified');
      }
      break;
    case 'time':
      if ( '0000-00-00 00:00:00' != $post->post_date) {
        $t_time = get_the_time(__('g:i A'));
        if ($t_time == '8:00 AM') {
          $t_time = '';
        }
        $t_date = get_the_time(__('Y/m/d'));
        print $t_date . ' ' . $t_time;
      }
  }
}
?>

Next step might be to make a plugin that automatically handles scheduling for me. Or even rearranging my queue… Hmm… =)

WordPress tweak: Proper navigation for date.php

I can’t be the only person who’s ever wanted proper navigation on WordPress date.php archive pages. By this, I mean that if you’re browsing, say, http://sachachua.com/wp/2009 and you’re on the first page, there should be a way for you to get to 2008.

So I spent a couple of hours hacking that in. This even skips non-existent years/months/days. Tweak and enjoy.

Minor notes: It jumps to the first page of the other year/month/day, so the results aren’t strictly chronological. Going to 2008 from 2009 will show you the blog posts from January 1 instead of the last posts of 2008. Since I display a huge list of posts and I only use one page, that’s fine with me.

<?php
  $y = mysql2date('Y', $wp_query->posts[0]->post_date);
  $m = mysql2date('m', $wp_query->posts[0]->post_date);
  $d = mysql2date('d', $wp_query->posts[0]->post_date);
  $display = mktime(0, 0, 0, $m, $d, $y);
  if (is_year()) {
    $format = 'Y';
    $prev_display = mktime(23, 59, 59, 12, 31, $y - 1);
    $next_display = mktime(0, 0, 0, 1, 1, $y + 1);
    $url_format = 'Y';
  } elseif (is_month()) {
    $prev_display = mktime(23, 59, 59, $m, 0, $y);
    $next_display = mktime(0, 0, 0, $m + 1, 1, $y);
    $format = 'F Y';
    $url_format = 'Y/n';
  } elseif (is_day()) {
    $prev_display = mktime(23, 59, 59, $m, $d - 1, $y);
    $next_display = mktime(0, 0, 0, $m, $d + 1, $y);
    $format = 'F j, Y';
    $url_format = 'Y/n/j';
  }
  $paged = get_query_var('paged');
  if ($paged < 2) { // No previous pages; navigate by date instead
    $past = $wpdb->get_row("SELECT UNIX_TIMESTAMP(MAX(post_date)) AS post_date
FROM $tableposts WHERE post_date <= FROM_UNIXTIME($prev_display) AND post_status='publish'");
    if ($past->post_date) {
      $prev_text = '&laquo; ' . date($format, $past->post_date);
      $prev_link = get_bloginfo('url') . '/'
        . date($url_format, $past->post_date);
    }
  }
  if ($paged >= $wp_query->max_num_pages) { // No next pages
    $future = $wpdb->get_row("SELECT UNIX_TIMESTAMP(MIN(post_date)) AS post_date
FROM $tableposts WHERE post_date >= FROM_UNIXTIME($next_display) AND post_status='publish'");
    if ($future->post_date) {
      $next_text = date($format, $future->post_date) . ' &raquo;';
      $next_link = get_bloginfo('url') . '/'
        . date($url_format, $future->post_date);
    }
  }
  $title = date($format, $display);
  ?>
  <div class="navigation">
    <div class="left">
      <?php if ($prev_text) { ?>
        <a href="<?php print $prev_link ?>"><?php print $prev_text ?></a>
      <?php } else { ?>
        <?php previous_posts_link('&laquo; Older posts'); ?>
      <?php } ?>
    </div>
    <div class="right">
      <?php if ($next_text) { ?>
        <a href="<?php print $next_link ?>"><?php print $next_text ?></a>
      <?php } else { ?>
        <?php next_posts_link('Newer posts &raquo;'); ?>
      <?php } ?>
    </div>
    <div style="clear: both"></div>
  </div>
  <h1><?php print $title ?></h1>

WordPress: Older posts, newer posts

I always get confused by “Previous page” and “Next page” on WordPress blogs. After only a little struggling, I finally got my navigation sorted out so that you can page through it using “Older posts” and “Newer posts”.

I added the following to my style.css:


.navigation { font-weight: bold; font-size: larger }
.navigation .right { float: right }
.navigation .left { float: left }

Then I added this to my theme’s index.php:

<div class="navigation">
  <div class="left">
    <?php next_posts_link('&laquo; Older posts'); ?>
  </div><div class="right">
    <?php previous_posts_link('Newer posts &raquo;'); ?>
  </div>
</div>

Result: yay!

image

Thinking about Planner/EmacsWiki versus WordPress

Was it really only less than two years ago that I shifted from my venerable Planner-based wiki/blog to my WordPress-powered one after experimenting with syndicating my entries into WordPress?

I miss writing in wiki markup on Emacs and knowing that publishing would Just Work. I miss being able to dynamically expand entries from my address book in a way that automatically links to people’s blogs. (Or Twitter accounts, if I were going to do this now.) ScribeFire is a pain on my Eee (needs more horizontal screen space), and I have a hard time marking up the occasional bit of HTML in weblogger.el. Windows Live Writer is pretty slick (particularly with the SnagIt Screen Capture plugin and the Amazon Book Linker), but I can live without it. Or maybe I can resurrect that WordPress Emacs client Ashish mentioned.

Let me think about the differences in experiences.

  • I wanted to support comments, but I didn’t want to spend a lot of time hacking on some custom commenting system. This was a big issue for me. I found some commenting scripts, but dealing with spam was a pain, so I switched to WordPress. If I switched back to Emacs for my blog, I’d probably use something like Disqus to handle the conversation, and just find some way of backing up the comments regularly.
  • I wanted to make it easy to navigate posts. I modified Planner to generate a more browsable blog index, but it’s still not as slick as what you’d see with WordPress. On this WordPress blog, I like offering people random blog posts (good for me too – great way to rediscover old posts and make serendipitous connections!), related posts, and posts on the same day. I can do posts on the same day in Planner with a custom hook, but the others would require some hacking. Also, Planner is very much day-based, while WordPress lists N posts per page and has good category lists.
  • I wanted to make it easy to edit posts. In my Emacs-based system, I published to RSS when I saved a note in the Remember window. I had a hack that made it possible to propagate changes from an already-published post to my WordPress blog, but it wasn’t completely reliable.
  • Scheduling posts is handy, too. I hadn’t gotten around to figuring out how to build a post scheduler for Emacs. I suppose if I wasn’t picky about the time it went out, I could simply write posts on different days and then publish notes conditionally, plus have some kind of hook to notice if any of the current page’s posts should be published in the RSS feed, plus some way to handle previous days, plus maybe a server-friendly way to do this for the times when I’m not going to be online every day. Right.

That said, I miss automatically sharing some details of what I’m working on (with details deleted before publishing so that they’re available offline), publicly crossing off tasks, and other cool things.

Planner’s model for task planning isn’t quite compatible with Org’s model, and I’ve been using Org + Toodledo more these days.

What am I really looking for here?

  • A quick, reliable way to post from a text editor, so that I can do it from the Eee. Hmm, the WP Postie plugin will probably do the trick.
  • Easy way to share/review tasks: Toodledo export of week’s tasks?
  • And maybe a custom plugin for weekly displays, org agendas, that sort of thing.

Hmm….