Category Archives: PHP

How to make WordPress display Full Text in RSS Feeds

... and why WordPress Moderators are obviously idiots

Today I got an email asking me to enable full text RSS feeds - so far so good, only when I activated the "Full Text" option nothing changed - neither in FireFox, nor in Google Reader, nor anywhere else. Only in Feed Proxy I saw a <content:encoded> tag appear that contained the full text (including html tags), but the description still only contained the excerpt (without html tags).

Before I link you to the thread that made me conclude the statement in the post title, let me quote from the RSS 2.0 specs:

A channel may contain any number of <item>s. An item may represent a "story" -- much like a story in a newspaper or magazine; if so its description is a synopsis of the story, and the link points to the full story. An item may also be complete in itself, if so, the description contains the text (entity-encoded HTML is allowed; see examples), and the link and title may be omitted. All elements of an item are optional, however at least one of title or description must be present.

That said take a look at http://wordpress.org/support/topic/190901 - having the problem described above and reading the replies, it just left me with one question:

If Otto42 is a moderator, where does WordPress get its trolls from?

The RSS Specs are pretty unspecific and blurry when it comes to the issue, one can at most point to http://www.feedvalidator.org/docs/warning/DuplicateDescriptionSemantics.html, but the main issue I have is that the rants of this "moderator" don't help me fix my problem, because Google Reader and FireFox still don't display the full entries.

A fix for it

If you want to fix it, you can do the following (in WP 2.7):

Open up wp-includes/feed-rss2.php and change

<?php if (get_option('rss_use_excerpt')) : ?>
<description><![CDATA[<?php the_excerpt_rss() ?>]]></description>
<?php else : ?>
<description><![CDATA[<?php the_excerpt_rss() ?>]]></description>
<?php if ( strlen( $post->post_content ) > 0 ) : ?>
<content:encoded><![CDATA[<?php the_content() ?>]]></content:encoded>
<?php else : ?>
<content:encoded><![CDATA[<?php the_excerpt_rss() ?>]]></content:encoded>
<?php endif; ?>
<?php endif; ?>

to

<?php if (get_option('rss_use_excerpt')) : ?>
<description><![CDATA[<?php the_excerpt_rss() ?>]]></description>
<?php else : ?>
<description><![CDATA[<?php the_content() ?>]]></description>
<?php endif; ?>

Similarly, if you want to fix your comments, too, open wp-includes/feed-rss2-comments.php and change

<?php if ( post_password_required($comment_post) ) : ?>
<description><?php echo ent2ncr(__('Protected Comments: Please enter your password to view comments.')); ?></description>
<content:encoded><![CDATA[<?php echo get_the_password_form() ?>]]></content:encoded>
<?php else : // post pass ?>
<description><?php comment_text_rss() ?></description>
<content:encoded><![CDATA[<?php comment_text() ?>]]></content:encoded>
<?php endif; // post pass

to

<?php if ( post_password_required($comment_post) ) : ?>
<description><![CDATA[<?php echo get_the_password_form() ?>]]></description>
<?php else : // post pass ?>
<description><![CDATA[<?php comment_text() ?>]]></description>
<?php endif; // post pass

Cheers,
Andreas

WordPress Hacking II

privatepagesfixI have a few private pages that I use to store random stuff and ideas and private pages (for a reason I don't understand) don't show up in the pages widget.

It turns out that WordPress's get_pages function always filters them out, while get_posts doesn't (it actually has some logic to figure out whether to show private pages or not).

I've decided to fix this. A real fix would probably be merging get_pages and get_posts because both seem to do pretty much the same except that get_posts is a tad bit more advanced, but I'm all for quick fixes at the moment, because I don't have much time and I don't want to end up considering myself a PHP developer ;-)

To make get_pages return private pages, too, you have to open the file wp-includes/post.php and change the following lines near the bottom of the get_pages function:

	$query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'page' AND post_status = 'publish') $where ";
	$query .= $author_query;
	$query .= " ORDER BY " . $sort_column . " " . $sort_order ;

to:

	$private_pages_inclusion_where = "";
	if ( is_user_logged_in() ) {
		$private_pages_inclusion_where  = current_user_can( "read_private_pages" ) ? " OR post_status = 'private'" : " OR post_author = $user_ID AND post_status = 'private'";
	}

	$query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'page' AND (post_status = 'publish' $private_pages_inclusion_where)) $where ";
	$query .= $author_query;
	$query .= " ORDER BY " . $sort_column . " " . $sort_order ;

If you also want to make it easier to distinguish private pages from normal ones, you can also change the following bits in wp-includes/classes.php in the method Walker_Page::start_el:

$output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) .
	'" title="' . attribute_escape(apply_filters('the_title', $page->post_title)) . '">' .
	$link_before . apply_filters('the_title', $page->post_title) . $link_after . '</a>';

to:

$output .= $indent . '<li class="' . $css_class . '"><a href="' . get_page_link($page->ID) .
	'" title="' . attribute_escape(apply_filters('the_title', $page->post_title)) . '">' .
	$link_before . apply_filters('the_title', $page->post_title) . ($page->post_status == 'private' ? " (Private)" : "") . $link_after . '</a>';

Cheers,
Andreas

More WordPress Pimping

PHP and CSS and all that funky web design stuff are funky, because they are so easy to use and you quickly get results. I like it.

I've decided to release my first plugin into the world (it's big hack, but it has turned out to be very useful on my other blog http://info1.blackhc.net).

It supports 3 text replacements:

Xkcd-style Tooltips as Replacement for Footnotes

Example:

[[:This is a default footnote. Hover over it to display it.]]

Result:

´

You can use a different marker, too:
Example:

[[:My Footnote#This is a default footnote. Hover over it to display it.]]

Result:
My Footnote

Linking to Wikipedia

Example:

[[wikipedia:Pie]]

Result:

Pie

The link text can be changed, too, of course.
Example (you can use : as seperator, too):

[[wikipedia:pi#Fake Pie]]

Result:

Fake Pie

Expandable Text

Example:

[[expandable#Expandable Text...]]

Result:

The link text can be changed, too:
Example:

[[expandable#Click me! Click me! Pleeease!#Yay!]]

Result:

And we can nest it and it works with other tags.
Example:

[[expandable:#Expandable Text...

[[expandable:Click me! Click me! Pleeease!#Yay!]]
// some Java code

]]

Result:

We can also use a Heredoc-like mode:
Example:

[[expandable_ex:EOD#Heredoc-like Expandable#[[[[[[[]][[EOD]]

Result:

Escaping [[ and ]]

Example:

Escaping [[escape_left]] and [[escape_right]]

Source Code

Hopefully this can be useful for somebody else, too.
Cheers,
Andreas

WordPress Hacking

Since I've been working on another blog (http://info1.blackhc.net) for my tutorial at university, I've played around with using Microsoft Word for publishing and editing content on the blog. I gotta say that SmartArts are really nice and good way to lighten up blog posts easily.

However Word's support for the current version of WordPress is sub-optimal - that is, it totally messes up formatting when retrieving existing blog posts (that is, Word doesn't recognize any paragraphs or line breaks). I've spent some time digging around in the blog's .php code to find a way to fix it and after an hour or so, I've been able to fix it.
It's one-liner I want to share with you:

//'description' => $post['main'], // line 1939 in xmlrpc.php (function mw_getPost)
'description' => wpautop( $post['main'] ),

The function wpautop adds <p> tags to your text (and by default <br> tags, too).

This will fix the formatting bug in Word. This is a hack, of course, but it works for Word.

WordPress has a bug in its Atom Publishing Protocol code, too:
It messes up the status code header when asking for user credentials, which prevents your browser from displaying the login form.
Again only one line needs to be changed:

// header('Status: ' . $msg); // line 1014 in wp-app.php (function: auth_required)
header('Status: 401 ' . $msg);

Stay tuned for more updates in the next months.. :-)
Cheers,
Andreas

PS: University is really keeping me busy..