Last active
December 22, 2016 19:24
-
-
Save pcfreak30/3cc7afb94fd1070c9e1c6bc6f9dfc10f to your computer and use it in GitHub Desktop.
YARPP_Cache ksort Class Fix for WordPress 4.7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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('­',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