This repository has been archived on 2026-10-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2016-09-28 21:41:25 +02:00

256 lines
8.2 KiB
PHP

<?php
class YARPP_Cache_Postmeta extends YARPP_Cache {
public $name = "postmeta";
// variables used for lookup
private $related_postdata = array();
private $related_IDs = array();
/**
* SETUP/STATUS
*/
function __construct( &$core ) {
parent::__construct( $core );
}
public function is_enabled() {
return true; // always enabled.
}
public function setup() {
}
public function upgrade( $last_version ) {
if ( $last_version && version_compare('3.4b1', $last_version) > 0 ) {
// 3.4 moved _yarpp_body_keywords and _yarpp_title_keywords into the single
// postmeta _yarpp_keywords, so clear out the old data now.
delete_post_meta_by_key('_yarpp_title_keywords');
delete_post_meta_by_key('_yarpp_body_keywords');
}
}
public function cache_status() {
global $wpdb;
return $wpdb->get_var("select (count(p.ID)-sum(m.meta_value IS NULL))/count(p.ID)
FROM `{$wpdb->posts}` as p
LEFT JOIN `{$wpdb->postmeta}` as m ON (p.ID = m.post_id and m.meta_key = '" . YARPP_POSTMETA_RELATED_KEY . "')
WHERE p.post_status = 'publish'");
}
public function uncached($limit = 20, $offset = 0) {
global $wpdb;
return $wpdb->get_col("select SQL_CALC_FOUND_ROWS p.ID
FROM `{$wpdb->posts}` as p
LEFT JOIN `{$wpdb->postmeta}` as m ON (p.ID = m.post_id and m.meta_key = '" . YARPP_POSTMETA_RELATED_KEY . "')
WHERE p.post_status = 'publish' and m.meta_value IS NULL
LIMIT $limit OFFSET $offset");
}
public function stats() {
global $wpdb;
return wp_list_pluck($wpdb->get_results("select num, count(*) as ct from (select 0 + if(meta_value = '" . YARPP_NO_RELATED . "', 0, substring(substring_index(meta_value,':',2),3)) as num from `{$wpdb->postmeta}` where meta_key = '" . YARPP_POSTMETA_RELATED_KEY . "') as t group by num order by num asc", OBJECT_K), 'ct');
}
/**
* MAGIC FILTERS
*/
public function where_filter($arg) {
global $wpdb;
// modify the where clause to use the related ID list.
if (!count($this->related_IDs))
$this->related_IDs = array(0);
$arg = preg_replace("!{$wpdb->posts}.ID = \d+!","{$wpdb->posts}.ID in (".join(',',$this->related_IDs).")",$arg);
// if recent is set, add an additional condition
$recent = $this->core->get_option('recent');
if ((bool) $recent) $arg .= " and post_date > date_sub(now(), interval {$recent}) ";
return $arg;
}
public function orderby_filter($arg) {
global $wpdb;
// only order by score if the score function is added in fields_filter, which only happens
// if there are related posts in the postdata
if ($this->score_override &&
is_array($this->related_postdata) && count($this->related_postdata))
return str_replace("$wpdb->posts.post_date","score",$arg);
return $arg;
}
public function fields_filter($arg) {
global $wpdb;
if (is_array($this->related_postdata) && count($this->related_postdata)) {
$scores = array();
foreach ($this->related_postdata as $related_entry) {
$scores[] = " WHEN {$related_entry['ID']} THEN {$related_entry['score']}";
}
$arg .= ", CASE {$wpdb->posts}.ID" . join('',$scores) ." END as score";
}
return $arg;
}
public function limit_filter($arg) {
if ($this->online_limit)
return " limit {$this->online_limit} ";
return $arg;
}
/**
* RELATEDNESS CACHE CONTROL
*/
public function begin_yarpp_time($reference_ID) {
$this->yarpp_time = true;
// get the related posts from postmeta, and also construct the relate_IDs array
$this->related_postdata = get_post_meta($reference_ID,YARPP_POSTMETA_RELATED_KEY,true);
if (is_array($this->related_postdata) && count($this->related_postdata))
$this->related_IDs = wp_list_pluck( $this->related_postdata, 'ID' );
add_filter('posts_where',array(&$this,'where_filter'));
add_filter('posts_orderby',array(&$this,'orderby_filter'));
add_filter('posts_fields',array(&$this,'fields_filter'));
add_filter('post_limits',array(&$this,'limit_filter'));
add_action('pre_get_posts',array(&$this,'add_signature'));
// sets the score override flag.
add_action('parse_query',array(&$this,'set_score_override_flag'));
}
public function end_yarpp_time() {
$this->yarpp_time = false;
$this->related_IDs = array();
$this->related_postdata = array();
remove_filter('posts_where',array(&$this,'where_filter'));
remove_filter('posts_orderby',array(&$this,'orderby_filter'));
remove_filter('posts_fields',array(&$this,'fields_filter'));
remove_filter('post_limits',array(&$this,'limit_filter'));
remove_action('pre_get_posts',array(&$this,'add_signature'));
// sets the score override flag.
remove_action('parse_query',array(&$this,'set_score_override_flag'));
}
// @return YARPP_NO_RELATED | YARPP_RELATED | YARPP_NOT_CACHED
public function is_cached($reference_ID) {
$related = get_post_meta($reference_ID, YARPP_POSTMETA_RELATED_KEY, true);
if ( YARPP_NO_RELATED === $related )
return YARPP_NO_RELATED;
if ( '' == $related )
return YARPP_NOT_CACHED;
return YARPP_RELATED;
}
public function clear( $reference_IDs ) {
$reference_IDs = wp_parse_id_list( $reference_IDs );
if ( !count($reference_IDs) )
return;
// clear each cache
foreach( $reference_IDs as $id ) {
delete_post_meta( $id, YARPP_POSTMETA_RELATED_KEY );
delete_post_meta( $id, YARPP_POSTMETA_KEYWORDS_KEY );
}
}
// @return YARPP_NO_RELATED | YARPP_RELATED
// @used by enforce
protected function update($reference_ID) {
global $wpdb;
$original_related = $this->related($reference_ID);
$related = $wpdb->get_results($this->sql($reference_ID), ARRAY_A);
$new_related = wp_list_pluck( $related, 'ID' );
if ( count($new_related) ) {
update_post_meta($reference_ID, YARPP_POSTMETA_RELATED_KEY, $related);
if ($this->core->debug) echo "<!--YARPP just set the cache for post $reference_ID-->";
// Clear the caches of any items which are no longer related or are newly related.
if (count($original_related)) {
$this->clear(array_diff($original_related, $new_related));
$this->clear(array_diff($new_related, $original_related));
}
return YARPP_RELATED;
} else {
update_post_meta($reference_ID, YARPP_POSTMETA_RELATED_KEY, YARPP_NO_RELATED);
// Clear the caches of those which are no longer related.
if (count($original_related))
$this->clear($original_related);
return YARPP_NO_RELATED;
}
}
public function flush() {
delete_post_meta_by_key( YARPP_POSTMETA_RELATED_KEY );
delete_post_meta_by_key( YARPP_POSTMETA_KEYWORDS_KEY );
}
public function related($reference_ID = null, $related_ID = null) {
global $wpdb;
if ( !is_int( $reference_ID ) && !is_int( $related_ID ) ) {
_doing_it_wrong( __METHOD__, 'reference ID and/or related ID must be set', '3.4' );
return;
}
if (!is_null($reference_ID) && !is_null($related_ID)) {
$results = get_post_meta($reference_ID,YARPP_POSTMETA_RELATED_KEY,true);
foreach($results as $result) {
if ($result['ID'] == $related_ID)
return true;
}
return false;
}
// return a list of ID's of "related" entries
if (!is_null($reference_ID)) {
$results = get_post_meta($reference_ID,YARPP_POSTMETA_RELATED_KEY,true);
if (!$results || $results == YARPP_NO_RELATED)
return array();
return wp_list_pluck( $results, 'ID' );
}
// return a list of entities which list this post as "related"
if (!is_null($related_ID)) {
return $wpdb->get_col("select post_id from `{$wpdb->postmeta}` where meta_key = '" . YARPP_POSTMETA_RELATED_KEY . "' and meta_value regexp 's:2:\"ID\";s:\d+:\"{$related_ID}\"'");
}
return false;
}
/**
* KEYWORDS CACHE CONTROL
*/
// @return (array) with body and title keywords
private function cache_keywords($ID) {
$keywords = array(
'body' => $this->body_keywords($ID),
'title' => $this->title_keywords($ID)
);
update_post_meta($ID, YARPP_POSTMETA_KEYWORDS_KEY, $keywords);
return $keywords;
}
// @param $ID (int)
// @param $type (string) 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 = get_post_meta($ID, YARPP_POSTMETA_KEYWORDS_KEY, true);
if ( empty($keywords) ) // if empty, try caching them first.
$keywords = $this->cache_keywords($ID);
if ( empty($keywords) )
return false;
if ( 'all' == $type )
return $keywords;
return $keywords[$type];
}
}