Skip to content

Instantly share code, notes, and snippets.

@pcfreak30
Last active December 22, 2016 19:24
Show Gist options
  • Save pcfreak30/3cc7afb94fd1070c9e1c6bc6f9dfc10f to your computer and use it in GitHub Desktop.
Save pcfreak30/3cc7afb94fd1070c9e1c6bc6f9dfc10f to your computer and use it in GitHub Desktop.
YARPP_Cache ksort Class Fix for WordPress 4.7
<?php
abstract class YARPP_Cache {
protected $core;
protected $yarpp_time = false;
public $score_override = false;
public $online_limit = false;
public $last_sql;
function __construct( &$core ) {
$this->core = &$core;
$this->name = __($this->name, 'yarpp');
}
function add_signature( $query ) {
$query->yarpp_cache_type = $this->name;
}
/**
* GENERAL CACHE CONTROL
*/
public function is_yarpp_time() {
return $this->yarpp_time;
}
public function flush() {
}
public function setup() {
}
public function upgrade( $last_version ) {
}
/*
* POST CACHE CONTROL
*/
/*
* Note: return value changed in 3.4
* return YARPP_NO_RELATED | YARPP_RELATED | YARPP_DONT_RUN | false if no good input
*/
function enforce($reference_ID, $force = false) {
/**
* @since 3.5.3 Don't compute on revisions.
* wp_is_post_revision will return the id of the revision parent instead.
*/
if ($the_post = wp_is_post_revision($reference_ID)) $reference_ID = $the_post;
if (!is_int($reference_ID)) return false;
$status = $this->is_cached($reference_ID);
$status = apply_filters('yarpp_cache_enforce_status', $status, $reference_ID);
// There's a stop signal:
if ($status === YARPP_DONT_RUN) return YARPP_DONT_RUN;
// If not cached, process now:
if ($status === YARPP_NOT_CACHED || $force) $status = $this->update((int) $reference_ID); // status now will be YARPP_NO_RELATED | YARPP_RELATED
// There are no related posts
if ($status === YARPP_NO_RELATED) return YARPP_NO_RELATED;
// There are results
return YARPP_RELATED;
}
/**
* @param int $reference_ID
* @return string YARPP_NO_RELATED | YARPP_RELATED | YARPP_NOT_CACHED
*/
public function is_cached($reference_ID) {
return YARPP_NOT_CACHED;
}
public function clear($reference_ID) {
}
/*
* POST STATUS INTERACTIONS
*/
/**
* Clear the cache for this entry and for all posts which are "related" to it.
* @since 3.2 This is called when a post is deleted.
*/
function delete_post($post_ID) {
// Clear the cache for this post.
$this->clear((int) $post_ID);
// Find all "peers" which list this post as a related post and clear their caches
if ($peers = $this->related(null, (int) $post_ID)) $this->clear($peers);
}
/**
* @since 3.2.1 Handle various post_status transitions
*/
function transition_post_status( $new_status, $old_status, $post ) {
$post_ID = $post->ID;
/**
* @since 3.4 Don't compute on revisions
* @since 3.5 Compute on the parent instead
*/
if ($the_post = wp_is_post_revision($post_ID)) $post_ID = $the_post;
// Un-publish
if ($old_status === 'publish' && $new_status !== 'publish') {
// Find all "peers" which list this post as a related post and clear their caches
if ($peers = $this->related(null, (int) $post_ID)) $this->clear($peers);
}
// Publish
if ($old_status !== 'publish' && $new_status === 'publish') {
/*
* Find everything which is related to this post, and clear them,
* so that this post might show up as related to them.
*/
if ($related = $this->related($post_ID, null)) $this->clear($related);
}
/**
* @since 3.4 Simply clear the cache on save; don't recompute.
*/
$this->clear((int) $post_ID);
}
function set_score_override_flag($q) {
if ($this->is_yarpp_time()) {
$this->score_override = (isset($q->query_vars['orderby']) && $q->query_vars['orderby'] === 'score');
if (!empty($q->query_vars['showposts'])) {
$this->online_limit = $q->query_vars['showposts'];
} else {
$this->online_limit = false;
}
} else {
$this->score_override = false;
$this->online_limit = false;
}
}
/**
* SQL!
*/
protected function sql($reference_ID = false, $args = array()) {
global $wpdb, $post;
if (is_object($post) && !$reference_ID) {
$reference_ID = $post->ID;
}
if (!is_object($post) || $reference_ID != $post->ID) {
$reference_post = get_post($reference_ID);
} else {
$reference_post = $post;
}
$options = array(
'threshold',
'show_pass_post',
'past_only',
'weight',
'require_tax',
'exclude',
'recent',
'limit'
);
extract($this->core->parse_args($args, $options));
// The maximum number of items we'll ever want to cache
$limit = max($limit, $this->core->get_option('rss_limit'));
// Fetch keywords
$keywords = $this->get_keywords($reference_ID);
// SELECT
$newsql = "SELECT $reference_ID as reference_ID, ID, "; //post_title, post_date, post_content, post_excerpt,
$newsql .= 'ROUND(0';
if (isset($weight['body']) && isset($weight['body']) && (int) $weight['body']) {
$newsql .= " + (MATCH (post_content) AGAINST ('".esc_sql($keywords['body'])."')) * ".absint($weight['body']);
}
if (isset($weight['body']) && isset($weight['title']) && (int) $weight['title']) {
$newsql .= " + (MATCH (post_title) AGAINST ('".esc_sql($keywords['title'])."')) * ".absint($weight['title']);
}
// Build tax criteria query parts based on the weights
foreach ((array) $weight['tax'] as $tax => $tax_weight) {
$newsql .= " + ".$this->tax_criteria($reference_ID, $tax)." * ".intval($tax_weight);
}
$newsql .= ',1) as score';
$newsql .= "\n from $wpdb->posts \n";
$exclude_tt_ids = wp_parse_id_list($exclude);
if (count($exclude_tt_ids) || count((array) $weight['tax']) || count($require_tax)) {
$newsql .= "left join $wpdb->term_relationships as terms on ( terms.object_id = $wpdb->posts.ID ) \n";
}
/*
* Where
*/
$newsql .= " where post_status in ( 'publish', 'static' ) and ID != '$reference_ID'";
/**
* @since 3.1.8 Revised $past_only option
*/
if ($past_only) $newsql .= " and post_date <= '$reference_post->post_date' ";
if (!$show_pass_post) $newsql .= " and post_password ='' ";
if ((bool) $recent) $newsql .= " and post_date > date_sub(now(), interval {$recent}) ";
$newsql .= " and post_type = 'post'";
// GROUP BY
$newsql .= "\n group by ID \n";
// HAVING
// number_format fix suggested by vkovalcik! :)
$safethreshold = number_format(max($threshold,0.1), 2, '.', '');
/**
* @since 3.5.3: ID=0 is a special value; never save such a result.
*/
$newsql .= " having score >= $safethreshold and ID != 0";
if (count($exclude_tt_ids)) {
$newsql .= " and bit_or(terms.term_taxonomy_id in (".join(',', $exclude_tt_ids).")) = 0";
}
foreach ((array) $require_tax as $tax => $number) {
$newsql .= ' and '.$this->tax_criteria($reference_ID, $tax).' >= '.intval($number);
}
$newsql .= " order by score desc limit $limit";
if (isset($args['post_type'])) {
$post_types = (array) $args['post_type'];
} else {
$post_types = $this->core->get_post_types();
}
$queries = array();
foreach ($post_types as $post_type) {
$queries[] = '('.str_replace("post_type = 'post'", "post_type = '{$post_type}'", $newsql).')';
}
$sql = implode(' union ', $queries);
if ($this->core->debug) echo "<!-- $sql -->";
$this->last_sql = $sql;
return $sql;
}
private function tax_criteria($reference_ID, $taxonomy) {
$terms = get_the_terms($reference_ID, $taxonomy);
// if there are no terms of that tax
if (false === $terms) return '(1 = 0)';
$tt_ids = wp_list_pluck($terms, 'term_taxonomy_id');
return "count(distinct if( terms.term_taxonomy_id in (".join(',',$tt_ids)."), terms.term_taxonomy_id, null ))";
}
/*
* KEYWORDS
*/
/**
* @param int $ID
* @param string $type body | title | all
* @return string|array depending on whether "all" were requested or not
*/
public function get_keywords($ID, $type = 'all') {
if (!$ID = absint($ID)) return false;
$keywords = array(
'body' => $this->body_keywords($ID),
'title' => $this->title_keywords($ID)
);
if (empty($keywords)) return false;
if ($type === 'all') return $keywords;
return $keywords[$type];
}
protected function title_keywords($ID, $max = 20) {
return apply_filters('yarpp_title_keywords', $this->extract_keywords(get_the_title($ID), $max, $ID), $max, $ID);
}
protected function body_keywords( $ID, $max = 20 ) {
global $wp_current_filter;
$filter_count = array_count_values( $wp_current_filter );
if ( ! empty( $filter_count['the_content'] ) && $filter_count['the_content'] > 1 ) {
return '';
}
$post = get_post( $ID );
if ( empty( $post ) ) {
return '';
}
return apply_filters( 'yarpp_body_keywords', $this->extract_keywords( apply_filters( 'the_content', $post->post_content ), $max, $ID ), $max, $ID );
}
private function extract_keywords( $html, $max = 20, $ID = 0 ) {
/**
* @filter yarpp_extract_keywords
*
* Use this filter to override YARPP's built-in keyword computation
* Return values should be a string of space-delimited words
*
* @param $keywords
* @param $html unfiltered HTML content
* @param (int) $max maximum number of keywords
* @param (int) $ID
*/
if ($keywords = apply_filters('yarpp_extract_keywords', false, $html, $max, $ID)) return $keywords;
if (defined('WPLANG')) {
switch ( substr(WPLANG, 0, 2) ) {
case 'de':
$lang = 'de_DE';
break;
case 'it':
$lang = 'it_IT';
break;
case 'pl':
$lang = 'pl_PL';
break;
case 'bg':
$lang = 'bg_BG';
break;
case 'fr':
$lang = 'fr_FR';
break;
case 'cs':
$lang = 'cs_CZ';
break;
case 'nl':
$lang = 'nl_NL';
break;
default:
$lang = 'en_US';
break;
}
}
else {
$lang = 'en_US';
}
$words_file = YARPP_DIR.'/lang/words-'.$lang.'.php';
if (file_exists($words_file)) include($words_file);
if (!isset($overusedwords)) $overusedwords = array();
// strip tags and html entities
$text = preg_replace('/&(#x[0-9a-f]+|#[0-9]+|[a-zA-Z]+);/', '', strip_tags($html) );
// 3.2.2: ignore soft hyphens
// Requires PHP 5: http://bugs.php.net/bug.php?id=25670
$softhyphen = html_entity_decode('&#173;',ENT_NOQUOTES,'UTF-8');
$text = str_replace($softhyphen, '', $text);
$charset = get_option('blog_charset');
if ( function_exists('mb_split') && !empty($charset) ) {
mb_regex_encoding($charset);
$wordlist = mb_split('\s*\W+\s*', mb_strtolower($text, $charset));
} else
$wordlist = preg_split('%\s*\W+\s*%', strtolower($text));
// Build an array of the unique words and number of times they occur.
$tokens = array_count_values($wordlist);
// Remove the stop words from the list.
$overusedwords = apply_filters( 'yarpp_keywords_overused_words', $overusedwords );
if ( is_array($overusedwords) ) {
foreach ($overusedwords as $word) {
unset($tokens[$word]);
}
}
// Remove words which are only a letter
foreach (array_keys($tokens) as $word) {
if ( function_exists('mb_strlen') )
if (mb_strlen($word) < 2) unset($tokens[$word]);
else
if (strlen($word) < 2) unset($tokens[$word]);
}
arsort($tokens, SORT_NUMERIC);
$types = array_keys($tokens);
if (count($types) > $max)
$types = array_slice($types, 0, $max);
return implode(' ', $types);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment