Removing sharedaddy’s (jetbacks sharing) extra og:description without hacking php

I’ve come across a problem where multiple plugins insert facebook opengraph meta tags into the header of my posts without letting me turn that behavior on or off. They all assume that no one explicitly puts open graph tags in their blog. This includes sharedaddy (jetpack sharing). It does so with the following comment:

	public function display_header() {
		if ( $this->share_type == 'share' ) {
			// Set the open graph description, otherwise Facebook may pick up some random text from the page
			global $post;
			
			if ( $post && $post->ID > 0 )
				echo '<meta property="og:description" content="'.esc_attr( apply_filters( 'sharing_post_title', $post->post_title, $post->ID, $this->id ) ).'" />';
		}
	}

Source in wordpress trak.

Problem is I’d rather define my og tags or rely on a plugin focused on doing this well.

There are several plugins to do open graph tag insertion that do a better job. You may want to roll your own directly into your theme or using one of the general SEO plugins.

So, I want to remove these extraneous tags. Online tips suggest I go into each plugin and comment out the php code inserting these tags. That’s a direct option but I hate modifying plugins. I don’t want to maintain these hacks through updates.

So, I solved with javascript. The approach is a hack. It requires that sharedaddy and other plugins insert their og:description tags before the tags I want to preserve and that I start my desired facebook tags with an fb:admins tag.

function removeExtraOpenGraphMetaTags()
{
	//assumes extra og tags occur before an fb:admins
	var first_og_tag = jQuery("meta[property]").first();
        //if the first meta tag with a property attribute is fb:admins - do nothing
	if (jQuery("meta[property]").first().attr('property') != 'fb:admins') 
	{
		//remove all subsequent og tags until fb:admins
		var removed_tags = first_og_tag.nextUntil("meta[property='fb:admins']", "meta[property*='og:']").remove();
		if (removed_tags) { first_og_tag.remove(); }
	}
}

How to add an options form to a wordpress theme using settings_fields

I spent some time today modifying a WordPress theme to take configuration properties.

I want one theme that I can quickly re-configure to create multiple blogs along different topics with different color/graphic schemes. I want easy maintenance so I’d love to share one instance of the theme across these different instances.

We’re using enough different plugins that WordPress Mu isn’t yet worth fighting. So database options and the Settings API seemed the best way.

The documentation on how to extend a theme this way is not so easy to find but there are plenty of examples. They tend to break the process into steps but don’t give as much sense of what you actually get and how to use it.

I based my code on this example: http://blog.starscapetheme.com/2008/05/31/create-settings-page-for-theme/

After the fact, I found this description which seems well written: http://www.pixelace.com/2009/theme-options-for-wordpress-27/

I created a menu item and a corresponding properties form:

Wordpress Theme Options FormWordpress Theme Menu Item
 

My form adds three properties which are stored in the WordPress wp_options table and easily exposed on template pages

<link rel="stylesheet" href="<?php $options = get_option('vertical'); echo $options['vertical_custom_css_url']; ?>" type="text/css" media="screen" />

Here’s the actual code I added to the functions.php page of the theme. If you don’t have a functions.php you can just create one in your theme folder. You need to make sure the code below is wrapped in “<?php” “?>” tags.

//encapsulate the logic into a class
$cpanel = new ControlPanel();

class ControlPanel {
/* static array to contain default values
the values set an additional css to override standard css in the theme
as well as an image and link that is rendered in the sidebar. These
three settings allow me to use the same theme with minor variations
on different blogs on different topics but with very similar looks and feels */

var $default_settings = Array(
‘vertical_custom_css_url’ => ,
‘topic_banner_img’ => ‘/images/banner.jpg’,
‘topic_url’ => ‘http://www.judykat.com/ken’

);
//constructor
function ControlPanel()
{
//hook to add a menu item in the Theme’s area of the admin sidebar
add_action(‘admin_menu’, array(&$this, ‘vertical_admin_menu’));
/* if options are not already created in the database, add them and set to default values
this creates a single database entry in wp_options with key vertical and
values a hash of key/value pairs */

if (!is_array(get_option(‘vertical’)))
add_option(‘vertical’, $this->default_settings);
//load the existing options into an array accessible as a property of this instance of ControlPanel
$this->options = get_option(‘vertical’);
}
//the function that ties an html form to the hook defined in the constructor.
function vertical_admin_menu() {
add_theme_page(‘Vertical Theme Control Panel’, ‘Customize Theme’, ‘edit_themes’, “vertical”, array(&$this, ‘vertical_theme_page’));
}
//function that defines the form for viewing and setting properties for the theme.
function vertical_theme_page() {
//if the form is being submitted, update the options in the database
if ( isset( $_POST[‘submit’] ) ) {
//if the “Save Changes” button was clicked, set the user entered values from the form
if (‘Save Changes’ == $_POST[‘submit’]) {
$this->options[“vertical_custom_css_url”] = $_POST[‘vertical_custom_css_url’];
$this->options[“topic_banner_img”] = $_POST[‘topic_banner_img’];
$this->options[“topic_url”] = $_POST[‘topic_url’];
$state=“saved”;
} //else if “Defaults” was clicked, reset values to default
else if (‘Defaults’ == $_POST[‘submit’]) {
$this->options[“vertical_custom_css_url”] = $this->default_settings[‘vertical_custom_css_url’];
$this->options[“topic_banner_img”] = $this->default_settings[‘topic_banner_img’];
$this->options[“topic_url”] = $this->default_settings[‘topic_url’];
$state=“reverted to defaults”;
} //commit the changes to the database
update_option(‘vertical’, $this->options);
//render a status message of the above actions in the standard WordPress admin dialog box at the top of the form.
echo ‘<div class=“updated fade” id=“message” style=“background-color: rgb(255, 251, 204); width: 300px; margin-left: 20px”><p>Settings <strong>‘.$state.’</strong>.</p></div>‘;
}
//the actual html form in standard markup to appear standard in the WordPress Admin
?>
<div class=‘wrap’>
<h2><?php _e(‘Customize Vertical Theme’); ?></h2>
<div id=“header”>
<div id=“headwrap”>
<div id=“header”>
<div id=“headerimg”>
<h1><?php bloginfo(‘name’); ?></h1>
<div class=“description”><?php bloginfo(‘description’); ?></div>
</div>
</div>
</div>
</div>
<br>
<form id=“vertical-settings-form” method=“post” action=“”>
<?php settings_fields( ‘vertical-settings’ ); ?>
<table class=“form-table”>
<tr valign=“top”>
<th scope=“row”>Path to Vertical CSS file:</th>
<td>
<input size=“70” type=“text” name=“vertical_custom_css_url” id=“vertical_custom_css_url” value=<?php echo $this->options[“vertical_custom_css_url”]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-“,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/style.css</small>
</td>
</tr>
<tr valign=“top”>
<th scope=“row”>Path to Category Page:</th>
<td>
<input size=“70” type=“text” name=“topic_url” id=“topic_url” value=<?php echo $this->options[“topic_url”]; ?>” />
<br/><small>example: http://www.judykat.com/ken</small>
</td>
</tr>
<tr valign=“top”>
<th scope=“row”>Path to Category Banner:</th>
<td>
<input size=“70” type=“text” name=“topic_banner_img” id=“topic_banner_img” value=<?php echo $this->options[“topic_banner_img”]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-“,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/images/banner.jpg</small>
</td>
</tr>
</table>
<p class=“submit”>
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Save Changes’) ?> />
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Defaults’) ?> />
</p>
<input type=“hidden” name=“saved” value=“true”>
</form>
</div>
<?php
}
}

Fixing markup in cross posts to wordpress using metaWeblog, xml-rpc, & xpost plugin

I’m experimenting with cross posting from one wordpress blog to another using the metaWeblog API and XML-RPC. This led me to the xpost plugin by Jan Gossman.

Easy enough to test. I set up two blogs, activated xpost on one of them and posted to the other.

The plugin works as promised. You can selectively post to multiple blogs and assign categories. Tags and standard properties are preserved. Most impressively, the relationship between source and target blogs is maintained. Changes in the source are updated in the targets.

However markup in the cross posts is broken because single and double quotes are escaped with a backslash. For example, link tags become <a href=\"....

From what I can find this is a known issue intentionally introduced within the WordPress’ XML-RPC implementation as brute force protection against a SQL injection vulnerability.

I don’t want to expose myself to this vulnerability. Nor do I want to hack a wordpress build.

It occurred to me one way to get past this issue is to strip those backslashes at the presentation level within the theme of the blog to which I want to crosspost. I don’t see any reason to render backslashes within posts.

So, with guidance from the WordPress codex, I modified the single and index templates…

Replacing:

<?php the_content(); ?>

With:

<?php
$content = get_the_content();
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
$content = str_replace('\\','',$content); /* This strips escapes inserted through XML-RPC */
print $content ?>

I think this will work for me. I’m glad to be proven wrong. Am I missing something?