관리-도구
편집 파일: YARPP_Cache_Postmeta.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( $wpdb->prepare( "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 %d OFFSET %d", $limit, $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 ) { /* * Only order by score if the score function is added in fields_filter, * which only happens if there are related posts in the post-data. * If ordering by score also order by post ID to keep them consistent in cases where the score is the same * for multiple posts. */ if ( $this->score_override && is_array( $this->related_postdata ) && count( $this->related_postdata ) ) { $arg = $this->orderby_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 ); } } /** * Caches the related posts in postmeta. * * @param int $reference_ID post ID to which we want to find related content * @param array $args see YARPP::display_related() * * @return string (YARPP_NO_RELATED | YARPP_RELATED) */ protected function update( $reference_ID, $args = array() ) { $original_related = $this->related( $reference_ID ); $related = $this->query_safely( 'get_results', array( $this->sql( $reference_ID, $args ), ARRAY_A, ) ); if ( $related instanceof WP_Error ) { return YARPP_DONT_RUN; } $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( $wpdb->prepare( "select post_id FROM `{$wpdb->postmeta}` WHERE meta_key = '" . YARPP_POSTMETA_RELATED_KEY . "' AND meta_value regexp 's:2:\"ID\";s:\d+:\"%d\"'", $reference_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 ]; } }