Category Archives: Wordpress

WordPress misses Publishing Schedule

I haven’t figured out why WordPress is missing schedule post, but I wrote a script that is ran with crontab that notifies me when it happens.

<?php

include 'wp-load.php';

$total_missed_schedules = 0;

$blogs = crontab_get_blogs();

$output = '';

foreach($blogs as $blog) {
	$blog_prefix = $wpdb->get_blog_prefix( $blog->blog_id );

	$results = query_missed_schedules( $blog_prefix );

	$total_missed_schedules += count($results);

	$output .= ($blog->domain . ' (blog id:' . $blog->blog_id . ') missed schedules ' . count($results) . '<br />' . PHP_EOL);

	if ($results) {

		switch_to_blog( $blog->blog_id );

		foreach ( $results as $row ) {
			$output .= ("post_id: <a href='" . get_edit_post_link($row->ID) . "'>" . $row->ID . "</a> date: " . $row->post_date . " post_type: " . $row->post_type . "<br />" . PHP_EOL);
		}

		restore_current_blog();
	}
}

echo $output;

if ($total_missed_schedules > 0 || isset($_GET['mailtest'])) {

	$to = 'matt@thiessen.us';
	$subject = 'Missed scheduled posts';
	$text = '';

	if(isset($_GET['cron_src'])) {
		$text = 'cron ran from ' . $_GET['cron_src'];
		$text .= '<br />wget http://thegazette.com/missed_pub_notifier.php<br /><br />';
	}

	add_filter('wp_mail_content_type',create_function('', 'return "text/html";'));
	wp_mail($to, $subject . " (wp_mail)", $text . $output);
}

function query_missed_schedules( $blog_prefix ) {
	global $wpdb;

	$sql = "SELECT ID, post_date, post_date_gmt, post_type, post_title FROM " . $blog_prefix . "posts WHERE post_status = 'future' AND post_date_gmt <= UTC_TIMESTAMP();";

	$results = $wpdb->get_results($sql);

	return $results;
}

function crontab_get_blogs() {
	global $wpdb;

	$sql = "SELECT blog_id, domain, path FROM $wpdb->blogs WHERE deleted = 0 AND archived = '0' ORDER BY domain, path";
	$results = $wpdb->get_results($sql);
	return ($results);
}

?>

How to Add CSS Styles to WordPress Breadcrumbs

functions.php

function get_page_parents( $id=0, $separator="/" ){
	$itisme=get_post($id);
	$lineage = '<span>'.$itisme->post_title.'</span>';
	$parentID=$itisme->post_parent;
	while( $parentID != 0 ){
		$parent=get_post($parentID);
		$lineage='<a href="' . get_permalink($parent->ID) . '">' . $parent->post_title . '</a>'.$separator.$lineage;
		$parentID=$parent->post_parent;
	}
	return $lineage;
}

include 'includes/breadcrumb-styles.php';
add_action('wp_head', 'add_breadcrumb_styles');

page.php

<?php get_template_part( 'nav', 'above-page' ); ?>

nav-above-page.php

<div id="page-bread-crumbs">
<a class="home" href="/">Home</a> &gt; <?php echo get_page_parents( $post->ID, " &gt; " ) ?>
</div>

includes/breadcrumb-styles.php

<?php

global $eia_parents;

$eia_parents = array();

function build_menu_style( $menu_name, $color, $locations ) {

	global $eia_parents;

	$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );

	$menu_items = wp_get_nav_menu_items($menu->term_id);

	$page_ids = array();

	foreach ( (array) $menu_items as $key => $menu_item ) {

		$page_id = $menu_item->object_id;

		echo '/* ' . $menu_item->title . ' */' . PHP_EOL;
		echo '.page-id-'.$page_id.' #page-bread-crumbs a,' . PHP_EOL;
		echo '.page-id-'.$page_id.' #page-bread-crumbs span {color:'.$color.';}' . PHP_EOL;

		if( $menu_item->post_parent && !array_key_exists( 'post_parent_id_'.$menu_item->post_parent, $eia_parents ) ) {
			array_push( $eia_parents, array( 'post_parent_id_'.$menu_item->post_parent => array('ID' => $menu_item, 'color' => $color ) ) );
		}
	}

	$page_ids = null;
}

function add_breadcrumb_styles() { ?><style type="text/css"><?php

global $eia_parents;

echo PHP_EOL;

$color1 = '#A08A42 /* book a flight (tan) */'; // tan /* book a flight */
$color2 = '#4AAAD6 /* check a flight (blue) */'; // blue /* check a flight */
$color3 = '#B25029 /* at the airport (burnt) */'; // burnt /* at the airport */
$color4 = '#40847A /* about the airport (green) */'; // green /* about the airport */

// update this array with the menus you wish to add styles from

$menu_locations = array(
	"home-subnav-1" => $color1,
	"home-subnav-2" => $color2,
	"home-subnav-3" => $color3,
	"home-subnav-4" => $color4
);

$locations = get_nav_menu_locations();

foreach( $menu_locations as $menu_name => $color ):
	if ( ( $locations ) && isset( $locations[ $menu_name ] ) ) {
		build_menu_style( $menu_name, $color, $locations );
	}
endforeach;

foreach ($eia_parents as $parent):
	echo PHP_EOL . '/* ' . get_the_title( $parent_id ) . ' */' . PHP_EOL;
	echo '.parent-pageid-'.$parent['ID'].' #page-bread-crumbs a,' . PHP_EOL;
	echo '.parent-pageid-'.$parent['ID'].' #page-bread-crumbs span {color:'.$parent['color'].';}' . PHP_EOL. PHP_EOL;
endforeach;

?></style><?php } ?>

WordPress custom menu link target _blank

Problem

In WordPress at least for custom links, it would be great to allow menu options to open in a new window/tab via the target=”_blank” element in the link tags. Controlling menus in the WP Menu tool is awesome, but many of the sites I work with have external links in the main navigation menus that need to open in a new tab.

Solution

Custom link nav-menu

 

jQuery('a[title="_blank"]').each(
	function(i) {
		jQuery(this).attr('target', '_blank');
		jQuery(this).attr('title', jQuery(this).text());
	}
);

Result

<a title=”_blank” href=”http://www2.allegiantair.com/”>Allegiant Air</a>

turns into

<a title=”Allegiant Air” href=”http://www2.allegiantair.com/” target=”_blank”>Allegiant Air</a>

Flush wp_rewrite rules

As stated on WordPress Codex: Flushing the rewrite rules is an expensive operation. So it’s best to refresh your wp_rewrite rules by not using the init hook.  Austin Passy chooses to Flush your rewrite rules on plugin/theme activation on checking $_GET parameters.  I’ve tried it two different ways.  The first option seemed to work for a while, but my added rule disappeared somehow and began sending requests to a 404 page so I started using the other option.

Option 1:

$custom_permalink_rules_exist = get_option( $this->permalink_rule_option_name );

if( $custom_permalink_rules_exist != "1") {
	add_action( 'init', 'flush_rewrite_rules');
	add_action( 'generate_rewrite_rules', array( &$this, 'add_rewrite_rules' ) );

	update_option( $this->permalink_rule_option_name, '1');
}

Option 2:

/**
	 * Flushing the wp_rewrite rules is an expensive proceedure so check
	 * if the rules exist
	 *
	 * @global object $wp_rewrite
	 */
	function verify_rewrite_rule_exists() {
		global $wp_rewrite;

		if( empty($this->rewrite_rule_key) ||
			!array_key_exists($this->rewrite_rule_key, $wp_rewrite->rules ) ) {
			add_action( 'generate_rewrite_rules', array( &$this, 'add_rewrite_rules' ) );
		}
	}

	function add_rewrite_rules( $wp_rewrite ) {
		global $wp_rewrite;

		$this->rewrite_rule_key = "^{$this->post_type_slug}/([^/]*)/([^/]*)/([^/]*)$";

		// match a custom post_type with a parent and child taxonomy
		$new_rules = array( "^{$this->post_type_slug}/([^/]*)/([^/]*)/([^/]*)$" => "index.php?{$this->post_type_slug}=" . $wp_rewrite->preg_index(3) );

		// match a custom post_type with only one taxonomy; however, will break the archive page for two taxonomies
		//$new_rules = array( "^{$this->post_type_slug}/([^/]*)/([^/]*)$" => "index.php?{$this->post_type_slug}=" . $wp_rewrite->preg_index(2) );

		// Add the new rewrite rule into the top of the global rules array
		$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;

		flush_rewrite_rules();

		return $wp_rewrite->rules;
	}

Custom Post Type redirects to 404 page

This function from dev4press really helped me debug my custom post type redirect to a 404 page.

 

Place this code in your functions.php file:

function dev4press_debug_page_request() {
		global $wp, $template;

		echo '<pre>!-- Request: ';
		echo empty($wp->request) ? "None" : esc_html($wp->request);
		echo ' -->'.PHP_EOL;
		echo '!-- Matched Rewrite Rule: ';
		echo empty($wp->matched_rule) ? None : esc_html($wp->matched_rule);
		echo ' -->'.PHP_EOL;
		echo '!-- Matched Rewrite Query: ';
		echo empty($wp->matched_query) ? "None" : esc_html($wp->matched_query);
		echo ' -->'.PHP_EOL;
		echo '!-- Loaded Template: ';
		echo basename($template);
		echo ' --></pre>'.PHP_EOL;
	}

Place this in your template file:

dev4press_debug_page_request();

echo '<h1>Rewrite Rules</h1>';

global $wp_rewrite;

echo '<pre>';
print_r($wp_rewrite->rules);
echo '</pre>';

Breadcrumbs for Taxonomy for a Custom Post type

This is what I came up with to display the category, or rather a custom taxonomy, of a single posttype page of use in a breadcrumb. The taxonomy I used is ‘smg-logo-brand’ and the terms slug where ‘kcrg’, ‘the-gazette’ and ‘sourcemedia.’ I compared the terms associated with the post to that in the URL to determine which term belonged in the breadcrumb.

if (!is_tax() && get_post_type() == 'smg-logo' && has_term( array( 'kcrg', 'the-gazette', 'sourcemedia', 'other' ), 'smg-logo-brand' ) ) {
			$terms = get_the_terms( get_the_ID(), 'smg-logo-brand' );
			foreach ( $terms as $term ) {
				if ( strpos( $_SERVER["REQUEST_URI"], $term->slug ) !== false) {
					$breads['terms'] = '<a href="/logos/'. $term->slug . '/">' . $term->name . '</a>';
				}
			}
		}

Custom post type capabilities

$custom_posts_caps = array('edit_custom_post',
'read_custom_post',
'delete_custom_post',
'edit_custom_posts',
'edit_others_custom_posts',
'publish_custom_posts',
'read_private_custom_posts');

_smg_add_cap('administrator', $custom_posts_caps);
_smg_add_cap('editor', $custom_posts_caps);

'capabilities' => array(
'edit_post' => 'edit_custom_post',
'read_post' => 'read_custom_post',
'delete_post' => 'delete_custom_post',
'edit_posts' => 'edit_custom_posts',
'edit_others_posts' => 'edit_others_custom_posts',
'publish_posts' => 'publish_custom_posts',
'read_private_posts' => 'read_private_custom_posts'
),

Create and verify a nonce

All of this is created in a class

// place this in __construct of the class
$this->nonce_name = 'name_' . $my_post_type_slug;
$this->nonce_action = 'saving_posttype_' . $my_post_type_slug;
add_action('save_post', 'save_my_custom_posttype', 10);

// place this in a meta box
echo '
';

// your custom save w/ nonce
function save_my_custom_posttype($post_id) {

	if (isset($_POST[ $this->nonce_name ]) && wp_verify_nonce( $_POST[ $this->nonce_name ], $this->nonce_action ) !== false ) {
		// do something
	}
}