Mostly about my amusement

Tag: php (page 1 of 1)

Excerpts and not full content, but only sometimes

WordPress filters and actions remains one of my favorite features. There is so much that you can easily manipulate without modifying a theme’s files.

For example: on my front page I like the latest published post to show the whole content with a featured image if there is one. For the rest of the articles I want to display the excerpt and no featured image. This is the same on the front page and subsequent pages.

One way to do this is to create a child theme and modify the PHP to get the effect you like. There’s a few reasons why I don’t like that option.

  1. Child themes are fun and I always recommend users create them. But I’m bad at maintaining them when the parent theme is updated.
  2. My CSS is just awful and I’m pretty sure I’d break the responsiveness of my site.
  3. Filters are cool! I can use this code in a plugin.

Filter the_content

I took a shot at making my own filter but a quick search found that Justin Tadlock had written a really good post on the topic already in 2008. I use that code in my function but added a few lines.

// Get the ID of the last published post
$mh_last_id = wp_get_recent_posts( array( 'numberposts' => '1' ,
     'post_status' => 'publish' ) )['0']['ID'];

// Get the post format. If the post is a standard format then the value will be false
$mh_post_type = get_post_format();

I do not want to show an excerpt for the latest post  and only want to modify standard post formats. Anything else I want to skip. The reason I only want to play with standard format posts is that other post types break horribly when I force the excerpt this way.

Except for adding to the conditional statement, the whole function is copied from Justin’s post. He writes great code and explains it much better than I do.

// If is the home page, an archive, or search results and not the last post and is a standard format
if((is_front_page() || is_archive() || is_search()) and $mh_last_id != get_the_ID() and !$mh_post_type )

That’s a little ugly to look at but it does the job.

What about the featured image?

In the past when I wanted to hide the featured image in a child theme I would use CSS like so.

.ryu-featured-thumbnail, .attachment-ryu-featured-thumbnail, .wp-post-image {
     display: none;
}

Which works but is a little heavy handed. My WordPress installation still sends the HTML for the featured image and the browser still pulls that image. The end user just doesn’t see it because it’s not being displayed.

I don’t want to remove featured image support from the theme and I don’t want to send that HTML either. Thanks to the post_thumbnail_html filter I don’t have to.

add_filter( 'post_thumbnail_html', 'mh_post_image_html', 10, 3 );

function mh_post_image_html( $html, $post_id, $post_image_id ) {

// Get the ID of the last published post
$mh_last_id = wp_get_recent_posts( array( 'numberposts' => '1' ,
     'post_status' => 'publish' ) )['0']['ID'];

if ( (is_front_page() || is_archive() || is_search()) and $mh_last_id != get_the_ID() ) {
     $html = '<!-- Featured image not displayed in excerpt -->';
     }
return $html;
}

This code checks if we’re the first post and replaces the post_thumbnail_html with a simple HTML comment.

Child theme or plugin?

This code works either way. At the moment I am using this in a plugin but the whole thing can be implemented in my child theme’s function.php file.

It belongs in the child theme because I’m playing with the presentation and that is theme territory. Editing a copy of content.php in the child theme directory would be more theme’ish but I like filters. Filters are cool.

I’m not good at keeping my child theme changes in sync with the parent theme so using a filter lets me just play with the results and not mess with theme files. In a plugin or the child theme’s functions.php file the filters still work the same.

Better living through WordPress filters

codex

Every now and then you find an interesting support question in the WordPress forums. A member wanted to take the HTML YouTube oEmbed code and modify it to suit his needs.

It was an easy set of requirements.

  1. Replace ?feature=oembed with ?wmode=transparent
  2. Append add wmode=”Opaque” to the end of the start iframe tag

My solution was to find all of the embeded YouTube <iframe…> tags in the post and modify the_content via a filter with some preg_match_all code.

You can see the code I came up with via this pastebin.com link.

It’s a nice enough solution and really highlights the point I was trying to make:

You do not have to hack existing code in WordPress to get the results you want.

Just use the available WordPress filters to modify the output as you need.

Jan? You do know you got that completely wrong right?

Yes. Yes I do. Well maybe not completely wrong but the code I posted was not the best solution.

I filtered the content because I’m used to playing in that space and it’s so easy to do. But my solution did not work for the person asking because what he was referring to did not output via the_content. He had to add another filter to make it work.

The original question was about how to modify oEmbed output. That’s a completely different filter and using the right one gets you a targeted solution that will work (should work anyways) at any place the oEmbed output is used.

Last year Mika Epstein posted a plugin called Rickroll that does exactly what it sounds like. It takes oEmbed video and replaces it with the Rickroll video.

You can learn a lot looking at other people’s code. It also has exactly what I needed to examine and make the modification to the YouTube oEmbed html.

Here’s the new code in a plugin.

add_filter('embed_oembed_html','mh_adjustyoutube',10,3);
function mh_adjustyoutube( $html, $url, $args ) {
if ( strstr($url, 'youtube.com') ) {
	// Replace ?feature=oembed
	$mh_new = str_replace( "?feature=oembed" , "?wmode=transparent" , $html );
	// Append wmode="Opaque"
	$mh_new = preg_replace( '/></iframe>$/' , ' wmode="Opaque">' , $mh_new );
	$html = $mh_new;
}
// Modified or not return $html
return $html;
}

This has fewer lines, simpler logic, and it is a solution that specifically filters the oEmbed output. It directly addresses the original question and can be used where ever the oEmbed code gets outputted.

You can see an easier to read version via this new pastebin.com link.

The lesson I learned is this: using WordPress filters is a powerful feature but using them correctly is even better.

Beware the canary mismatch on efree monster

For traffic logs, I use Clicky Web Analytics and take a look from time to time. See that flat dark blue line? Around noon on December 3rd my blog stopped serving web pages and it was not until about 5 hours later that I noticed it. I don’t get a lot of traffic but I do like my blog to be working.

It wasn’t that my VPS went nuts, the CPU usage was fine. What was happening was that my PHP interpreter was tossing hundreds of these errors.

[Thu Dec 03 12:17:27 2009] [error] [client 66.249.71.233] ALERT - canary mismatch on efree() - heap overflow detected

Not cool and until I restarted Apache2, my blog was not serving anything. PHP just kept blowing up. This has been an ongoing problem for me that has been attributed to the Suhosin PHP security patch and I had not found the magic bullet to fix.

I’m not going to disable the hardened PHP. That’s like turning off the safety switch on an excercise treadmill. It’s juts not safe.

As a work around I have done the following: I activated the WP Super Cache plugin, removed the Xcache op cache I setup, and disabled the ssh2 PHP extension I installed.

The WP Super Cache created static HTML pages for your dynamic content.  It does cache expiration, garbage collection, etc. and limits the amount of time PHP needs to be run.

The XCache was a hold over from when I was running my blog on a Pentium II.  The VPS I use is very responsive and losing it does not hurt me.  Using the Pingdom tools I can see that I still get a good response from my web server.

Losing the ssh2 was easy; I only added it to my PHP to be able to answer a WordPress support forum questions. I never use it. I’ll look for any other PHP extensions that I added as a “what the hell” but so far so good. No more canary mismatch errors as yet.

WordPress file monitoring

Over a week ago I complained about WordPress users crying security wolf and not being able to recover their blog when the “Bad Thing(tm)” happens.

Since then a real brawl developed on the support forum that could be summed up like so:

  1. One or more users is insisting that there is an XMLRPC exploit in 2.5.1.
  2. The same one or more users refuses to back this claim up with data, or apparently send the WordPress security e-mail alias any info (maybe, how would other people know what was sent via e-mail?)
  3. Many people tried to reasonably explain that such an exploit may exist but without data there is nothing to solve.

This discussion was just plain nuts and went around in circles.  Complaining about a problem without providing any proof and then getting all pissy about it is totally useless.  It is entirely possible that such an exploit exists and many people replied so.  But without any providing data other than saying “I can assure you that the hack occurs via XMLRPC”, then everyone’s time gets wasted.

Fortunately, Donncha provided a page that covers the issue succinctly and today he added another post on setting up aide.  His two posts are good and anyone considering monitoring their WordPress files for modification should give this a try.

Aide will let you see if your installation files and directories have been tampered with.  It won’t protect you against HTTP POSTS or database attacks but it’s very good if someone succeeds in modifying your files.

There are ways to log what’s being sent via an HTTP POST and examine that information; if (or even when) I get hacked, I’ll try to start looking at that data.  MYSQL database monitoring, that could be interesting but for now I’m not aware of a good tool to do that.

On my OpenSuSE installation, installing aide is simple.  As root run

zypper install aide
aide --init
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
aide --check
cp /usr/share/doc/packages/aide/examples/etc/cron.daily/aide.sh /etc/cron.daily/

All of which I just did.  I ran the check option to make sure I did not create any issues with the aide.conf file.  I’ll play with the aide.conf file and see what kind of output I get when the daily cron job gets run.  If I add and modify files and I set it up correctly then I should see that in daily cron job’s output.

Update: this worked but in /etc/aide.conf change the line verbose=1 to verbose=5.  That will get you a useful output of which files and directories changed.

Sigh, WordPress users and hacking

If you are not running the latest version of WordPress and you get hacked, don’t go to the WordPress forum and tell the world.  Odds are you invited the disaster yourself.

When WordPress 2.5 came out I was disappointed to find that the old version 2.3.x was basically abandoned.  There would be no more planned patches for 2.3.x just the current 2.5.  The 2.0.x branch would continue to be supported as part of the commitment to the Debian version model.

So as of right now versions 2.0.11 and 2.5.1 are supported. If you are running 2.2.x, 2.3.x, 2.5(.0), or any other version then you run the risk of being exploited.

So why do users continue to use the old versions?  Everyday there are posts in the support forum that (so far) always deals with someone’s blog getting hacked and they are not using the current 2.5.1 version (as of this writing).  Eventually someone writes “I’ve been hacked” and some other user writes “Is this a vulnerability of insert current version HERE?!? Why are the developers not doing SOMETHING?!”.

It’s like there is some axe to grind and the first one to find the axe gets 1000 gold points.  The moderators usually show great patience; I’d get ticked if I were them.  These users seriously should just avail themselves of WordPress.com and stop trying to self host a blog.

The freely available WordPress from WordPress.ORG is not commercially supported, and commercial support if often not that good anyway. So for anyone who is thinking about using WordPress.org’s software, they should be able to do the following by themselves.

You need to be able to make backups.

Read this Codex article for backing up your WordPress installation.

WordPress uses two components.  The easy one is the file system and backing that up should be trivial.  I use a shell script that creates a tar.gz archive every night.  Another cron job deletes backups that are older than 30 days.  Why fill up my disk?  The backups are not for historical use, just to get me back to the state I was 24 hours ago if need be.  30 days is too much but hey, disk space is cheap.

The mysql database is the other component.  The same backup script also creates a text dump of my entire WordPress database.  This copy gets gzipped and added to my file backup.  The mysqldump command is your friend and should be used.

You need to be able to know how to restore those backups.

The Codex has a good article on how to restore your blog database here.

Making the best backups is pointless if you don’t know what to do with them when the “Bad Thing” happens.  Take your backup and restore it to a WAMP or LAMP installation on your own PC.  If you need a Windows Apache Mysql Php setup, use Google and install the one you feel comfortable with.  In Linux just add the packages (See this link for Ubuntu).

Once you have the Apache web server, Mysql, and PHP running locally on your PC then start playing.  Install WordPress locally, restore your backup and just change the name of your installation in wp-config.php to localhost and test.  To adjust your local installation to run on your PC just add these two lines to the copy of the wp-config.php on your PC:

define('WP_SITEURL', 'http://localhost');
define('WP_HOME', 'http://localhost');

Then on your PC point your browser to http://localhost/ and test it.  Beat it up; it’s a local copy on your PC.  Go nuts on it and confirm that your posts, categories, tags, comments, etc. are all there.  Anything on your PC that you mess up in WAMP or LAMP should be no big deal.  Just start over if you get lost.

Play with it until you understand what you are doing, because when you DO lose your blog you’ll need to do this for real.

Practice performing an upgrade on your PC’s local copy.

That sounds like a plan right? Some plugins don’t work with the latest and greatest version.  If the version you are running is vulnerable to an exploit then you don’t need that plug in.

Security updates are the number one driver for minor number version releases such as 2.5 to 2.5.1.  Yes, there are bugs but they usually are tolerable.  Exploitable code is serious business and usually gets fixed quickly.

Once you are comfortable with upgrading and testing your local installation, upgrade your real blog.  I personally keep good backups and know how to restore them so I never bother with this step.

If you know how to backup and restore your blog, then even if the upgrade is bad, you will be able to put it back the way it was before the upgrade.

eAccelerator for Opensuse 10.0

Updated: I bumped the version from 0.9.5 to 0.9.5.1.

The source RPM for 0.9.5.1 can be found here.

The 32 bit compiled version can be found here.

I no longer have access to a x86_64 opensuse installation but running this command:

rpmbuild -bb php5-eaccelerator-0.9.5.1-1.src.rpm

should create them on your system.

——————————-

I wanted to add APC or even XCache but found that my PHP version 5.0.4 was not supported. Changing to 5.2.1 did not really seem to work well for me and some plugins did not work. So I went back to the default updated opensuse 10.0 packages.

The PHP cache software eaccelerator 0.9.5 does work with php 5.0.4. In fact sometimes it speeds up php by almost half.

The opensuse 10.0 source rpm I put together can be found here. I built the .x86_64.rpm and put a copy here. The src.rpm will figure out where to put the extension so if you do a rpmbuild on the src.rpm on another opensuse which has php5 installed it should work.

The spec file has some build requirements, most of which can be commented out I am sure. I built it with

configure –enable-eaccelerator=shared –with-php-config=/usr/bin/php-config

I put the eaccelerator.cache_dir in /var/spool/eaccelerator and made that directory part of the package.

Inside the footer of my theme I put

<!– <?php echo get_num_queries(); ?> queries. <?php timer_stop(1); ?> seconds. –>

The timer shows that pages were taking 1.3 seconds or more to generate, sometimes longer.

With eaccelerator I get 0.628 seconds or so.

I also keep

define( ‘ENABLE_CACHE’, true );

in my wp-config.php right below the line that reads define (‘WPLANG’, ”);.

This caches database information such as categories etc. I turned it off and the frequent hitting of my mysql tables introduced a big delay in response time.

Next up will be to tune my mysql settings.