putty-vi

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.

4999436984_aca3f6862d_b_controlled-implosion

The replacement VPS didn’t go BOOM!

Yesterday I moved my WordPress network from one VPS in Chicago to Atlanta (different VPS hosting company). I like using a VPS because it maintains my illusion of being in control of my server.

*Drinks more coffee*

Surprisingly it went well. Except for missing a couple of PHP modules I had no problems and the site has been stable overnight.

If you plan to do this then give this Codex article a read. Of course I didn’t read it myself, it’s much more fun for me just winging it.

Create and configure my new VPS

I installed an image of Ubuntu 13.04 and made sure SMTP was configured to work. Apache2, PHP, mysql and mod_ssl were added and activated as well.

That was a surprise for me. The default image installs a ton of stuff that I don’t think I’ll ever need or want. I would have preferred to use a 14.04 LTS image (not available, too new) but that one is still maintained so it’s all good.

Creating the new empty database was straight forward. I used the same database name and user from the original VPS setup. Configuring the vhosts was just a matter of copying the old config files and making sure the certs and directories are all preserved.

Set DNS TTL on stun

My default DNS TTL (time-to-live) is 1800 seconds. I wasn’t sure if this would go well or not so I made the TTL 300 seconds (5 minutes). I didn’t change any IP addresses but if I broke something and couldn’t fix it then I was looking at only 5 minutes for it to come back to life.

Copy the files and database

My WordPress network has around 1.4 GB of file data from the last 7 years or so and the mysqldump was about 70MB . The file copy was just scp -r and the mysqldump command was just for that one network database.

Importing the database was just

zcat dumpfile.sql.gz | mysql -u name -p databasename

Once that was all done I updated my DNS IP and waited.

And I waited. And waited some more.

I could see in my access log that my new site was getting hits but I was still hitting my old web server (I was tailing the old logs in another windows) well after 5 minutes.

What the heck? It’s DNS. Setting the TTL just works. Except when it doesn’t.

I was using Google Chrome and that has it’s own application level DNS cache. It has a DNS cache that apparently doesn’t honor the TTL on the record.

Once I cleared that cache then I could see myself hitting the new IP address.

Nothing broke! Fantastic.

Next steps

Once I’ve confirmed that I have moved everything off the old VPS and onto the new then I’ll rebuild the old one and might re-do this whole exercise in the other direction. I’m sure the unstable nature of the old one is due to some dumb thing I did code I installed that’s running amok.

In the meanwhile I’m going to enjoy some nice stability and uptime for my site.

Note: The CC image above was a result of my typing “controlled implosion” into the WP Inject WordPress plugin. It’s a very cool plugin for finding CC images and I plan on leaving a review on WordPress.org sometime.

Featured image photo by Savannah River Site

Favorite new WordPress 3.9 feature

Copying and pasting from Microsoft Word directly into the Visual Editor is my new favorite thing in 3.9 beta. I just tried it on Lily’s store WordPress site and it worked alright. This is a fortunate side effect of 3.9 getting a new version of TinyMCE.

I know, that sounds anti-climatic even a little mundane given the great enhancements that 3.9 will be delivering. But I occasionally (once a month) have this conversation.

Them: How can I copy this Word document into WordPress?

Me: First select the text and paste that into notepad. I like notepad++ myself.

Me: Then you take the text you just copied into notepad select and copy it into the Visual Editor. Again.

Me: Make sure you copy from notepad. Bad things will happen if you paste that into the Visual Editor directly from Word.

Me: Then you apply the styling such as bold, underline, etc. To that text. For titles I like to use the <h3> tag myself.

Me: No, that layout thing you did in Word won’t work.

Me: Images? If you use the Snipping Tool then you can save that image to your hard disk.

Me: Once you’ve done that, upload that into the media library.

Me: Then you can insert it into the WordPress post. The image I mean, I usually go with centered and no link.

Them: Zzzzzz Wha-? What we’re we talking about??

I myself don’t like the idea of users creating content for WordPress outside of WordPress but I’m told I’m special. Apparently “regular” users (yes I’m doing the “air quotes”) such as my wife and some siblings use Word that way.

Lily creates flyers for wine tastings once a week. Right now she has to wait for me to create the event on the WordPress site (thank you Modern Tribe! that’s a great plugin) then cross post it to the company Facebook page. If I can show her how to just paste the content into WordPress to create the event then she can deliver the post sooner.

Also that means I’ll have one less thing to do each week.

Next I have got to test out dragging images into the Visual Editor to upload them that way. That’s got to improve “regular” users workflow too.

Let’s play a game called SERP

On the support forums occasionally (OK today) someone will ask that a post be edited to remove a link or company name for SEO reasons. Unless there’s a good reason for that (and SEO isn’t) then it just isn’t done. There are millions of posts on those forums; can you imagine if a small percentage of members asked for posts to be edited that way?

It’s not always necessary to edit The Interwebz

I am not a web front end developer. I don’t do “SEO”, I don’t at this time have any advertisements on my site. I post to my self-hosted WordPress blog for my own amusement and occasionally the amusement of my friends.

But just for giggles, let’s do a search on Google for my name. I wonder what comes up?

seo-games-jan-dembowski

Huh. That’s weird.

The first hit is my Twitter page, followed by my Make/Support author page, a Polish biologist then a general who both died before I was born (no relation). Then there’s some images (hey, 3 of those are me!) and then my WordPress site. Ah, there’s my Flickr page. I was worried about that not being there.

There is nothing on that search engine results page pointing to the WordPress forums. That’s a shame. I’ve got *looks WOW* 10,772 posts in the forums. That’s not necessarily a lot by the way.

How did that happen?

Again I am not into “SEO” and I haven’t done anything to impact that SERP. I even had to look up what SERP meant to make sure I’m using the term correctly.

But my guess is that the results happened that way because those links are pertinent and each of those links have content that is updated. That’s all there is to it.

  • I tweet everyday non-stop so it’s no wonder that popped up as the first hit.
  • I post to make/support at least once a week so there’s that.
  • Links 3 and 4 are cool and I like that my name is notable (even if the original spelling was Dębowski, ę is pronounced /ɛm/, w is a v sound, look it up).

The important thing is that I produce content and that’s why when someone looks up my name you get sites that I actually update.

So “SEO” magic isn’t real?

There are people who advertise and I assume make a living on SEO work and I am sure they know what they are doing.

If I had a site that I was selling something then I may be concerned that my actual site is 6th down from the top (skipping the images). If I were selling something then perhaps I’d use an SEO plugin. I’d also update my actual site more frequently.

Even without my doing anything special a search for my name shows the links that I expected to see.

My advice to people who want links removed from the forums or anywhere remains the same: if you don’t like your search engine results then change them. Produce original content on your own site. That’s really all there is to it.

WordPress actions and filters are still very cool

I spend time perusing the WordPress support forums (now that’s an understatement) and sometimes I come across someone being unhappy with a plugin. In this particular case a plugin was adding a notice to the admin screens saying “Upgrade now for only $24″.

I really have nothing against plugin authors deriving income that way but I prefer that messages like that in my WordPress dashboard be dismissible. That dashboard real estate is mine and I just don’t like to share.

The plugin adds that message using this code.

add_action( 'admin_notices', 'emg_upgradepro_message' );

WordPress actions and filters are a wonderful thing. It’s a queuing mechanism meaning that the order that your PHP code loads or is executed does not matter. What matters is that actions (or filters) get added to the queue and executed in priority order.

That add_action() does not have a priority so it defaults to 10. Actions that are added that way can be removed too but you have to have that remove_action() in the queue after the action is added. You can’t remove it before it’s added.

I was able to easily (took me 3 minutes) by creating another plugin that just removes that action like so.

<?php
/*
Plugin Name: Remove Easy Media Gallery Upgrade Notice
Version: 0.1
Description: This plugin removes the Easy Media Gallery Upgrade notice in the WordPress dashboard.
Author: Jan Dembowski
Author URI: http://blog.dembowski.net/
*/

add_action( 'admin_init', 'mh_no_upgrade' , 15 );
function mh_no_upgrade () {
        remove_action( 'admin_notices', 'emg_upgradepro_message' );
}

And that’s it. The priority 15 should make it run after the action that adds that message and it does: the message is gone. This may not be the best way to do it but it’s an easy 3 minute fix.

Keep in mind that I don’t use this plugin on my main blog but exercises like this one just show how easy it is to extend WordPress.

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.

Jetpack Carousel for Themify themes

This is probably documented somewhere but I’m posting it here so I don’t forget (again).

I wanted to give Jetpack’s Carousel module a spin but the built in Themify Pretty Photo lightbox kept getting used instead.

To disable the PrettyPhoto lightbox add these lines to your child theme’s functions.php file.

add_action('wp_enqueue_scripts', 'mh_remove_pretty_photo', 20);
function mh_remove_pretty_photo() {
        wp_dequeue_style( 'pretty-photo' );
        wp_dequeue_script( 'pretty-photo' );
        wp_deregister_script( 'themify-carousel-js' );
}

That will let another lightbox be used instead such as Jetpack’s Carousel. The 20 argument in the add_action() is to make sure my function gets queued after the parent theme function.

Or center embedded tweets with just CSS

After my earlier post on “Centering embedded tweets in WordPress” I’d gotten a reply from Ipstenu and Otto on Twitter.

Customizing how tweets are displayed is not a new problem. ;)

This got me taking a second look at the CSS of an embedded tweet. With Firebug you can inspect just about any items properties and I found the rule quickly.

I’m still picking up CSS knowledge all the time and I always forget about !important.

That tag lets you override rules even when it the normal CSS should get precedence. Which is why when I tried this in CSS previously it didn’t work for me, the rule I added was missing that tag. Continue reading