" );
add_action('admin_notices', create_function( '', "echo '$notice';" ) );
}
}
public function filterPostContent($content) {
// We don't want to filter if this is a feed or if settings tell us not to
if (
(
$this->_settings['erp']['auto_insert'] == 'all' ||
( $this->_settings['erp']['auto_insert'] == 'posts' && !is_page() ) ||
( $this->_settings['erp']['auto_insert'] == 'single-all' && is_singular() && !is_attachment() && !is_home() ) ||
( $this->_settings['erp']['auto_insert'] == 'single' && is_single() )
)
&& !is_feed()
) {
$content .= $this->getRelatedPosts();
}
return $content;
}
public function filterPostContentRSS($content) {
if ( $this->_settings['erp']['rss'] == 'yes' && is_feed() ) {
$content .= $this->getRelatedPosts();
}
return $content;
}
/**
* @param [optional]$args Array of arguments containing any of the following:
* [num_to_display] - Number of Posts to display
* [no_rp_text] - Text to display if there are no related posts
* [title] - Title for related posts list, empty for none
*/
public function getRelatedPosts( $args = array() ) {
global $post;
$output = '';
$settings = wp_parse_args($args, $this->_settings['erp']);
$relatedPosts = get_post_meta($post->ID, '_efficient_related_posts', true);
if ( empty($relatedPosts) || $settings['num_to_display'] == 0 ){
/**
* @todo The before and after setting should apply to this too
*/
$output .= "
{$settings['no_rp_text']}
";
} else {
$relatedPosts = array_slice($relatedPosts, 0, $settings['num_to_display']);
foreach ( $relatedPosts as $p ) {
/**
* Handle IDs for backwards compat
*/
if ( ctype_digit($p) ) {
$related_post = get_post($p);
$p = array(
'ID' => $related_post->ID,
'post_title' => $related_post->post_title,
'permalink' => get_permalink($related_post->ID),
'post_thumbnail' => $related_post->post_thumbnail
);
}
$link = "".wptexturize($p['post_title']).'';
if($p['post_thumbnail'] != ''){ $link = "" . $p['post_thumbnail'] . '' . $link; }
/**
* @todo Make a before and after setting for this
*/
$output .= "
{$link}
";
}
}
/**
* @todo Make a before and after setting for this
*/
$output = "
{$output}
";
if ( !empty($settings['title']) ) {
$output = "
{$settings['title']}
{$output}";
}
return $output;
}
/**
* @param [optional]$args See efficientRelatedPosts::getRelatedPosts
*/
public function relatedPosts( $args = array() ) {
echo $this->getRelatedPosts($args);
}
private function _getPostIDs(&$p, $key) {
$p = absint($p['ID']);
}
private function _findRelations($post, $processRelated = false, $postIds = null) {
// Try to increase the time limit
set_time_limit(60);
global $wpdb;
$now = current_time('mysql', 1);
$post = get_post($post);
$tags = wp_get_post_tags($post->ID);
if ( !empty($tags) ) {
$tagList = array();
foreach ( $tags as $t ) {
$tagList[] = $t->term_id;
}
$tagList = implode(',', $tagList);
if ( !empty($postIds) ) {
// Make sure each element is an integer and filter out any 0s
array_walk($postIds, array($this, '_getPostIDs'));
$postIds = array_diff(array_unique((array) $postIds), array('','0'));
}
if ( !empty($postIds) ) {
// If it's still not empty, make a SQL WHERE clause
$postIds = 'p.ID IN (' . implode(',', $postIds) . ') AND';
} else {
// If it's empty, make sure it's a string so we don't get notices
$postIds = '';
}
$q = <<term_taxonomy} t_t,
{$wpdb->term_relationships} t_r,
{$wpdb->posts} p
WHERE
{$postIds}
t_t.taxonomy ='post_tag' AND
t_t.term_taxonomy_id = t_r.term_taxonomy_id AND
t_r.object_id = p.ID AND
(t_t.term_id IN ({$tagList})) AND
p.ID != {$post->ID} AND
p.post_status = 'publish' AND
p.post_date_gmt < '{$now}'
GROUP BY
t_r.object_id
ORDER BY
matches DESC,
p.post_date_gmt DESC
QUERY;
$related_posts = $wpdb->get_results($q);
$allRelatedPosts = array();
$relatedPostsToStore = array();
$threshold = '';
if ($related_posts) {
foreach ($related_posts as $related_post ){
$overlap = array_intersect(wp_get_post_categories($related_post->ID), $this->_settings['erp']['ignore_cats']);
$allRelatedPosts[] = $related_post;
if ( empty($overlap) && count($relatedPostsToStore) < $this->_settings['erp']['max_relations_stored'] ) {
$threshold = $related_post->matches;
//unset($related_post->matches);
$related_post->permalink = get_permalink($related_post->ID);
if ( function_exists('get_the_post_thumbnail') ) {
$related_post->post_thumbnail = get_the_post_thumbnail($related_post->ID);
}
$relatedPostsToStore[] = (array)$related_post;
}
}
}
if (!add_post_meta($post->ID, '_efficient_related_posts', $relatedPostsToStore, true)) {
update_post_meta($post->ID, '_efficient_related_posts', $relatedPostsToStore);
}
/**
* The threshold is the lowest number of matches in the related posts
* that we store. We use this to see if we need to process an old post.
*/
if (!add_post_meta($post->ID, '_relation_threshold', $threshold, true)) {
update_post_meta($post->ID, '_relation_threshold', $threshold);
}
if ($processRelated) {
foreach ( $allRelatedPosts as $p ) {
$threshold = get_post_meta($p->ID, '_relation_threshold', true);
if ( empty($threshold) || $threshold <= $p->matches ) {
// Get the current related posts
$relatedPosts = get_post_meta($p->ID, '_efficient_related_posts', true);
$relatedPosts[] = array('ID'=>$post->ID,'post_title'=>$post->post_title);
// Find the relations, but limit the posts that are checked to save memory/time
$this->_findRelations( $p->ID, false, $relatedPosts );
}
}
}
}
}
public function processPost( $a ) {
$a = get_post( $a );
// Don't Process revisions
if ( $a->post_type == 'revision' ) {
return;
}
$this->_findRelations( $a, true );
}
public function processAllPosts( $args = array() ) {
//set_time_limit(600);
global $wpdb;
$defaults = array(
'drafts' => false,
'pending' => false,
'scheduled' => false,
'continue' => false
);
$args = wp_parse_args((array) $args, $defaults);
$statuses = array('publish');
if ( $args['drafts'] == 'true' ) {
$statuses[] = 'draft';
}
if ( $args['scheduled'] == 'true' ) {
$statuses[] = 'future';
}
if ( $args['pending'] == 'true' ) {
$statuses[] = 'pending';
}
$q = "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_status` IN ('%s')";
if ( $args['continue'] ) {
$this->_processedPosts = get_option('erp-processedPosts');
if ( !empty($this->_processedPosts) && is_array($this->_processedPosts) ) {
$q .= ' && `ID` NOT IN (' . implode(',', $this->_processedPosts) . ')';
} else {
$this->_processedPosts = array();
}
}
$q = sprintf( $q, implode("','", $statuses));
$postIDs = $wpdb->get_col( $q );
foreach ($postIDs as $pid) {
$this->_findRelations( $pid );
$this->_processedPosts[] = $pid;
update_option('erp-processedPosts', $this->_processedPosts);
if (memory_get_usage() >= .8 * get_memory_limit()) {
break;
}
}
delete_option('erp-processedPosts');
return $postIDs;
}
public function fixPermalinks(){
global $wpdb;
$query = <<postmeta}` WHERE `meta_key`='_efficient_related_posts'
QUERY;
$relatedPostMeta = $wpdb->get_results($query);
foreach ($relatedPostMeta as $relatedPosts) {
$relatedPosts->meta_value = maybe_unserialize($relatedPosts->meta_value);
foreach ($relatedPosts->meta_value as &$relatedPost) {
$relatedPost['permalink'] = get_permalink($relatedPost['ID']);
}
$relatedPosts->meta_value = maybe_serialize( stripslashes_deep($relatedPosts->meta_value) );
$data = array( 'meta_value' => $relatedPosts->meta_value);
$where = array(
'meta_key' => $relatedPosts->meta_key,
'post_id' => $relatedPosts->post_id
);
$wpdb->update( $wpdb->postmeta, $data, $where );
wp_cache_delete($relatedPosts->post_id, 'post_meta');
}
}
public function activate() {
$this->processAllPosts();
}
/**
* Replace our shortCode with the list of related posts
*
* @param array $attr - array of attributes from the shortCode
* @param string $content - Content of the shortCode
* @return string - formatted XHTML replacement for the shortCode
*/
public function handleShortcodes($attr, $content = '') {
if ( !empty($content) && empty($attr['title']) ) {
$attr['title'] = $content;
}
$attr = shortcode_atts($this->_settings['erp'], $attr);
return $this->getRelatedPosts($attr);
}
public function filterSettings($settings) {
$defaults = array(
'title' => __("Related Posts:", $this->_slug),
'no_rp_text' => __("No Related Posts", $this->_slug),
'ignore_cats' => array(),
'max_relations_stored' => 10,
'num_to_display' => 5,
'auto_insert' => 'no',
'rss' => 'no'
);
$settings = wp_parse_args($settings, $defaults);
if ( !is_array($settings['ignore_cats']) ) {
$settings['ignore_cats'] = preg_split('/\s*,\s*/', trim($settings['ignore_cats']), -1, PREG_SPLIT_NO_EMPTY);
}
$settings['max_relations_stored'] = intval($settings['max_relations_stored']);
$settings['num_to_display'] = intval($settings['num_to_display']);
return $settings;
}
}
/**
* Our custom Walker because Walker_Category_Checklist doesn't let you use your own field name
*/
class Walker_Category_Checklist_ERP extends Walker {
var $tree_type = 'category';
var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this
function start_lvl(&$output, $depth, $args) {
$indent = str_repeat("\t", $depth);
$output .= "$indent