Sivel.net  Throwing Hot Coals


WordPress One Liner to Remove Style Tags from Posts using [gallery] Shortcode

One of the biggest things that irritates me when using the [gallery] shortcode is that style tags are inserted into the post content. Why does this irritate me? Because this does not validate as XHTML 1.0. Luckily the fix is quite easy. Add the following code as a plugin or to your themes functions.php and say goodbye to the style tags in your post content.

add_filter('gallery_style', create_function('$a', 'return preg_replace("%%s", "", $a);'));

One side effect to doing this is that the CSS normally outputted to into your post content is no longer output at all. You will need to add the CSS to your themes css file, usually style.css. The following css is the default output:

The width for .gallery-item is a dynamic value determined by the columns attribute specified in the [gallery] shortcode. The default is 3 columns which makes the width 33%, floor(100/$columns).

I have also written a plugin called Gallery Shortcode Style to Head which does a forward lookup to determine if a post uses the [gallery] shortcode and if it does, prints the default CSS to the head. While the plugin works and performs its function, I still prefer a solution that has less overhead associated with it, hence the code provided in this post.

Code One Liner PHP Snippet WordPress

WordPress One Liner to Customize Author Permalink

Several people have asked me recently how to customize the author permalink from being /author/admin to something like /profile/admin. I have created a simple one line piece of code that you can drop in your themes functions.php to achieve this.

add_filter('init', create_function('$a', 'global $wp_rewrite; $wp_rewrite->author_base = "profile";'));

Drop this into your themes functions.php wrapped in <?php ?> tags, then visit the WordPress admin, go to Settings->Permalinks then off you go. By visiting the permalinks settings page it should flush the rewrite rules, but if for some reason it doesn’t go ahead and click “Save Changes”. If you want /author/ to become something other than /profile/ replace ‘profile’ in that one liner with the string of your choice.

Code One Liner PHP Snippet WordPress

Add a Class to Parent Categories Using wp_list_categories in WordPress

There was a quesiton in the WordPress IRC channel just a little while ago asking if there was a way to add a class to the li tag of parent categories generated by the wp_list_categories function.

The first idea that came to mind was using javascript, but a PHP solution will work without the requirement of running javascript on the client machine.

The solution is to read the output of wp_list_comments into a variable, split/explode the string into an array, loop through the array checking if the next element is <ul class='children'>, if the next element is the child ul then add a class to the current li and echo, otherwise just echo the element. Sounds easy right? The code is actually easier to write than describing it using words. As with all of my WordPress code snippets relating to a theme change I have used the WordPress default theme. The following code goes in sidebar.php and replaces the current wp_list_categories function.

<?php
$categories = wp_list_categories('show_count=1&title_li=<h2>Categories</h2>&echo=0');
$category_array = preg_split('/n/', $categories);
$count = count($category_array);
$i = 0;
while ( $i < $count ) {
        if ( preg_match('/<ul class=('|")children('|")/i', $category_array[$i+1]) ) {
                echo preg_replace('/<li class=('|")(.+)('|")>/i', '<li class=$1parent $2$3>', $category_array[$i]) . "n";
        } else {
                echo $category_array[$i] . "n";
        }
        $i++;
}
?>

Enjoy!

Code PHP Snippet WordPress

Adding a Link to the WordPress 2.7 Favorites Dropdown

There was some concern on the WP-Hackers list that the sidemenu action had been removed from WordPress 2.7. As the “sidemenu” (Settings, Plugins, Users) links no longer exist in 2.7 this action was removed. There is, however a suitable replacement which is the favorites dropdown.

This code snippet will show you what is required to add a link to the favorites dropdown.

<?php
function add_to_favorites( $favorites_array ) {
    $favorites_array['link-add.php'] = array('Add Link', 'manage_links');
    return $favorites_array;
}

add_filter('favorite_actions', 'add_to_favorites');
?>

I’ll break down the line where we insert an element into the array so it makes more sense:

$favorites_array['link-add.php'] = array('Add Link', 'manage_links');

We want to insert a new key into the array where the key is the href for the link. In this case I just made it ‘link-add.php’ but could be anything like ‘options.php’ or ‘admin.php?page=my-plugins-options-page’.

The value for that key is an array where the first element is the display text and the second is the minimum user role required to see that link in the favorites.

Use this responsibly. Plugin authors, please do not go adding tons of useless crap to the favorites menu, use this only when it makes sense.

Enjoy!

Code PHP Snippet WordPress

Separating Pings from Comments in WordPress 2.7

WordPress 2.7 has introduced many new features surrounding comments. Of these is AJAX commenting and threaded comments. To take advantage of the later, you must use a function wp_list_comments instead of the old way of looping through the comments array with a foreach. Weblog Tools Collection has a good how to on the old way that can be found here.

I wanted to get this hashed out before 2.7 goes live so that theme designers and anyone else can implement this in time for the release.

I’ll be referencing the default theme from 2.7 in this how to. If you are interested in adding the new commenting features to your current pre 2.7 theme see this how to by Otto.

wp_list_comments is not documented yet on the WordPress codex. But some feature that are worth mentioning are the ability to specify the comment type to display and a callback so that you can decide how to structure the output.

Let us start by taking a look at the new comments “loop”:

<?php if ( have_comments() ) : ?>
    <h3 id="comments">

<?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;

<?php the_title(); ?>&#8221;</h3>

    <ol class="commentlist">


<?php wp_list_comments(); ?>
    </ol>
    <div class="navigation">
        <div class="alignleft">

<?php previous_comments_link() ?></div>
        <div class="alignright">

<?php next_comments_link() ?></div>
    </div>


<?php else : // this is displayed if there are no comments so far ?>



<?php if ('open' == $post->comment_status) : ?>


<!-- If comments are open, but there are no comments. -->



<?php else : // comments are closed ?>


<!-- If comments are closed. -->
        <p class="nocomments">Comments are closed.</p>



<?php endif; ?>


<?php endif; ?>

As you can see it is much simpler than the old comments “loop”. The majority of everything that is happening is now done via the function wp_list_comments.

To remove pings (pingbacks and trackbacks) we only need to make a few small changes. First open up your themes single.php:

Find the following code:

<?php comments_template(); ?>

And change it to:

<?php comments_template('', true); ?>

The above change tells comments_template to create a global array $comments_by_type that we will use later on.

First open up comments.php.

Look for the following code:

<?php if ( have_comments() ) : ?>

Directly below this add:

<?php if ( ! empty($comments_by_type['comment']) ) : ?>

Change this:

<?php wp_list_comments(); ?>

To this:

<?php wp_list_comments('type=comment'); ?>

Directly below the wp_list_comments function we modified is:

</ol>

Directly below this add:

<?php endif; ?>

The if statement prevents the comments heading and ol tags from displaying if you only have trackbacks and pingbacks on this post.

Much easier so far, right?

To display the pings we need to insert the following code beneath the endif we just added:

<?php if ( ! empty($comments_by_type['pings']) ) : ?>
<h3 id="pings">Trackbacks/Pingbacks</h3>

<ol class="commentlist">


<?php wp_list_comments('type=pings'); ?>
</ol>


<?php endif; ?>

The comments “loop” should now look like this:

<?php if ( have_comments() ) : ?>


<?php if ( ! empty($comments_by_type['comment']) ) : ?>
    <h3 id="comments">

<?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;

<?php the_title(); ?>&#8221;</h3>

    <ol class="commentlist">


<?php wp_list_comments('type=comment'); ?>
    </ol>


<?php endif; ?>



<?php if ( ! empty($comments_by_type['pings']) ) : ?>
    <h3 id="pings">Trackbacks/Pingbacks</h3>

    <ol class="commentlist">


<?php wp_list_comments('type=pings'); ?>
    </ol>


<?php endif; ?>

    <div class="navigation">
        <div class="alignleft">

<?php previous_comments_link() ?></div>
        <div class="alignright">

<?php next_comments_link() ?></div>
    </div>


<?php else : // this is displayed if there are no comments so far ?>



<?php if ('open' == $post->comment_status) : ?>


<!-- If comments are open, but there are no comments. -->



<?php else : // comments are closed ?>


<!-- If comments are closed. -->
        <p class="nocomments">Comments are closed.</p>



<?php endif; ?>


<?php endif; ?>

Now the pings are displayed below the comments. The above code will show the pings in full comment boxes. I personally like a simple ordered list with a link and title of the ping. To achieve this without a foreach (Thanks Ryan Boren for the tip!)

Open your themes functions.php file and create a callback function for wp_list_comments. The following code should be inserted:

<?php

function list_pings($comment, $args, $depth) { $GLOBALS[‘comment’] = $comment; ?> <li id=“comment-

<?php comment_ID(); ?>">

<?php comment_author_link(); ?>


<?php } ?>

Replace this:

<ol class="commentlist">
<?php wp_list_comments('type=pings'); ?>

With this:

<ol class="pinglist">
<?php wp_list_comments('type=pings&callback=list_pings'); ?>

If your theme doesn’t have a functions.php just create it and include the above code.

In this case our full comment “loop” should now look like:

<?php if ( have_comments() ) : ?>


<?php if ( ! empty($comments_by_type['comment']) ) : ?>
    <h3 id="comments">

<?php comments_number('No Responses', 'One Response', '% Responses' );?> to &#8220;

<?php the_title(); ?>&#8221;</h3>

    <ol class="commentlist">


<?php wp_list_comments('type=comment'); ?>
    </ol>


<?php endif; ?>



<?php if ( ! empty($comments_by_type['pings']) ) : ?>
    <h3 id="pings">Trackbacks/Pingbacks</h3>

    <ol class="pinglist">


<?php wp_list_comments('type=pings&callback=list_pings'); ?>
    </ol>


<?php endif; ?>

    <div class="navigation">
        <div class="alignleft">

<?php previous_comments_link() ?></div>
        <div class="alignright">

<?php next_comments_link() ?></div>
    </div>


<?php else : // this is displayed if there are no comments so far ?>



<?php if ('open' == $post->comment_status) : ?>


<!-- If comments are open, but there are no comments. -->



<?php else : // comments are closed ?>


<!-- If comments are closed. -->
        <p class="nocomments">Comments are closed.</p>



<?php endif; ?>


<?php endif; ?>

One last (optional) task is to modify the comment counts to only reflect the number of comments minus pings.

Open your themes functions.php and add the following code:

<?php
add_filter('get_comments_number', 'comment_count', 0);
function comment_count( $count ) {
    if ( ! is_admin() ) {
        global $id;
        $comments_by_type = &separate_comments(get_comments('status=approve&post_id=' . $id));
        return count($comments_by_type['comment']);
    } else {
        return $count;
    }
}
?>

Again if your theme doesn’t have a functions.php just create it and include the above code.

There you have it. If you have any questions let me know.

HowTo PHP Plugins WordPress

XCache Admin Cannot Login When Using Apache and mod_fcgid

I have been helping a friend setup a dedicated server to host his clients sites on and wanted to make things as streamlined and as easy as possible. To do so I installed Apache 2.2, PHP5, XCache and mod_fcgid. I am using suexec with Apache to run the scripts as the users who own the scripts.

I wanted to verify that XCache was working, so I copied the XCache admin directory into one of the document roots and tried to login. To my surprise I was not able to login even though I was using a known good md5 password hash in the XCache configuration.

It took me about a month of searching to find out that the server variables PHP_AUTH_USER and PHP_AUTH_PW don’t seem to work with mod_fcgid. This Lighttpd forum entry led me to the XCache admin config.php.

Here is what is required:

  1. Create a file in your XCache admin directory called config.php
  2. In this file add the following, using the information you provided in the XCache configuration:

    <?php $_SERVER[‘PHP_AUTH_USER’] = ‘admin_username’; $_SERVER[‘PHP_AUTH_PW’] = ‘admin_password’; ?>

  3. Configure some other means of authentication such as htpasswd or htdigest

HowTo Linux PHP Technology

Getting Lighttpd, FastCGI and PHP working on CentOS 4

Over the years I have been installing Lighttpd from the RPMforge repository on my CentOS 4 servers for high traffic sites. The one thing that bothers me time and again is that installing lighttpd, lighttpd-fastcgi and PHP; configuring lighttpd.conf to enable FastCGI and configuring FastCGI for PHP isn’t all that is required. Try doing only that and starting Lighttpd. It will die immediately all the while telling you that it started successfully.

The problem is that the default configuration for FastCGI + PHP in lighttpd.conf tries to place the PHP sockets into /var/run/lighttpd/ which doesn’t exist.

Only 2 quick steps are required to finish the installation and configuration:

  1. mkdir /var/run/lighttpd
  2. chown lighttpd. /var/run/lighttpd

Now fire up Lighttpd and enjoy the wonderful world of PHP on a web server that doesn’t suck.

Side Note: For those of you who are trying to find the location of php-cgi on your PHP 4.3.9 install from the base or updates CentOS repo, you aren’t going to find what you are looking for. Uninstall PHP 4.3.9 and install PHP 5.1.6 from the centosplus repo.

HowTo Linux PHP Technology

Display Most Recent WordPress Posts On Another Site

I was recently had the job of displaying the most recent WordPress posts on a sites main page. The easiest way I could think of doing this is to use the RSS feed.

I’ll give two sample php functions that will do this as one requires some pear packages and the other doesn’t.

Option 1

This option requires the use of several PHP Pear packages. Those packages are XML_RSS, XML_Tree and XML_Parser. This is the preferred option as the code is specific to RSS instead of XML generically.

<?php
require_once "XML/RSS.php";

// read_rss(display_n_items,feed_url)
function read_rss($display=0,$url='') {
    $rss =& new XML_RSS($url);
    $rss->parse();
    $itemArr = array();
    foreach ($rss->getItems() as $item) {
        if ($display == 0) {
            break;
        }

        array_push($itemArr,$item);

        $display--;
    }
    return $itemArr;
}
?>

Option 2

This option does not require any special Pear packages which would be helpful for users who do not have the capability to install them or have their hosting provider install them.

<?php
// read_rss(display_n_items,feed_url)
function read_rss($display=0,$url='') {
    $doc = new DOMDocument();
    $doc->load($url);
    $itemArr = array();
    foreach ($doc->getElementsByTagName('item') as $node) {
        if ($display == 0) {
            break;
        }

        $itemRSS = array (
            'title'       => $node->getElementsByTagName('title')->item(0)->nodeValue,
            'description' => $node->getElementsByTagName('description')->item(0)->nodeValue,
            'link'        => $node->getElementsByTagName('link')->item(0)->nodeValue,
            'pubdate'     => $node->getElementsByTagName('pubDate')->item(0)->nodeValue
        );

        array_push($itemArr, $itemRSS);

        $display--;
    }
    return $itemArr;
}
?>

Now to use either of these functions we would do something similar to the following:

<ul>
<?php
$items = read_rss(2, 'http://sivel.net/feed');
foreach ( $items as $item ) {
    echo '<li><a href="' . $item['link'] . '">' . $item['title'] . '</a>';
}
?>
</ul>
HowTo PHP WordPress