PNG  IHDRP3YgAMA asRGB ņ *."s.„t~s".8:eb Py9&o"v ӥXh31F&1U{= \|8&TD0+׋mb;1H^X'Dy""C6p]/!J 7@Q8:E]%8j 潄I*ֆo]": {7SRs.#MqbEfxZ%U8u$Z 6s>^1)t=>˨(6}hyFH|\Xaڤ A]dF"b狌k]VM0ψ!1TkpsԣuMrM+ kXqsnzG6AA*%6{f{6ã[p!.~qA Mz]m ]7uu uW7._U>P bA, ĂX bA,/ڒܿ.Mz_zg?H`F̙q"bpH?CLG IENDB`) $this->args['recent']) $arg .= " and post_date > date_sub(now(), interval {$this->args['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 post-data. */ 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 demo_request_filter($arg) { global $wpdb; $wpdb->query("set @count = 0;"); $loremipsum = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras tincidunt justo a urna. Ut turpis. Phasellus'. 'convallis, odio sit amet cursus convallis, eros orci scelerisque velit, ut sodales neque nisl at ante. '. 'Suspendisse metus. Curabitur auctor pede quis mi. Pellentesque lorem justo, condimentum ac, dapibus sit '. 'amet, ornare et, erat. Quisque velit. Etiam sodales dui feugiat neque suscipit bibendum. Integer mattis. '. 'Nullam et ante non sem commodo malesuada. Pellentesque ultrices fermentum lectus. Maecenas hendrerit neque ac '. 'est. Fusce tortor mi, tristique sed, cursus at, pellentesque non, dui. Suspendisse potenti.'; return "SELECT SQL_CALC_FOUND_ROWS ID + {$this->demo_limit} as ID, post_author, post_date, post_date_gmt, '{$loremipsum}' as post_content, concat('".__('Example post ','yarpp')."', @count:=@count+1) as post_title, 0 as post_category, '' as post_excerpt, 'publish' as post_status, 'open' as comment_status, 'open' as ping_status, '' as post_password, concat('example-post-',@count) as post_name, '' as to_ping, '' as pinged, post_modified, post_modified_gmt, '' as post_content_filtered, 0 as post_parent, concat('PERMALINK',@count) as guid, 0 as menu_order, 'post' as post_type, '' as post_mime_type, 0 as comment_count, 'SCORE' as score FROM $wpdb->posts ORDER BY ID DESC LIMIT 0, {$this->demo_limit}"; } public function limit_filter($arg) { global $wpdb; return ($this->online_limit) ? " limit {$this->online_limit} " : $arg; } /** * RELATEDNESS CACHE CONTROL */ public function begin_yarpp_time($reference_ID, $args) { global $wpdb; $this->yarpp_time = true; $options = array( 'threshold', 'show_pass_post', 'past_only', 'weight', 'require_tax', 'exclude', 'recent', 'limit' ); $this->args = $this->core->parse_args($args, $options); $this->related_postdata = $wpdb->get_results($this->sql($reference_ID, $args), ARRAY_A); $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')); add_action('parse_query',array(&$this,'set_score_override_flag')); // sets the score override flag. } public function begin_demo_time($limit) { $this->demo_time = true; $this->demo_limit = $limit; add_action('pre_get_posts',array(&$this,'add_signature')); add_filter('posts_request',array(&$this,'demo_request_filter')); } public function end_yarpp_time() { $this->yarpp_time = false; 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')); remove_action('parse_query',array(&$this,'set_score_override_flag')); } public function end_demo_time() { $this->demo_time = false; remove_action('pre_get_posts',array(&$this,'add_signature')); remove_filter('posts_request',array(&$this,'demo_request_filter')); } // @return YARPP_NO_RELATED | YARPP_RELATED // @used by enforce protected function update($reference_ID) { global $wpdb; return YARPP_RELATED; } 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; } // reverse lookup if ( is_int($related_ID) && is_null($reference_ID) ) { _doing_it_wrong( __METHOD__, 'YARPP_Cache_Bypass::related cannot do a reverse lookup', '3.4' ); return; } $results = $wpdb->get_results($this->sql($reference_ID), ARRAY_A); if ( !$results || !count($results) ) return false; $results_ids = wp_list_pluck( $results, 'ID' ); if ( is_null($related_ID) ) { return $results_ids; } else { return in_array( $related_ID, $results_ids ); } } }RPP_TABLES_RELATED_TABLE."` ( `reference_ID` bigint(20) unsigned NOT NULL default '0', `ID` bigint(20) unsigned NOT NULL default '0', `score` float unsigned NOT NULL default '0', `date` timestamp NOT NULL default CURRENT_TIMESTAMP, PRIMARY KEY (`reference_ID`,`ID`), INDEX (`score`), INDEX (`ID`) )$charset_collate;" ); } public function upgrade($last_version) { global $wpdb; if ( $last_version && version_compare('3.2.1b4', $last_version) > 0 ) { // Change primary key to be (reference_ID, ID) to ensure that we don't // get duplicates. // We unfortunately have to clear the cache first here, to ensure that there // are no duplicates. $this->flush(); $wpdb->query('ALTER TABLE ' . $wpdb->prefix . YARPP_TABLES_RELATED_TABLE . ' DROP PRIMARY KEY ,' . ' ADD PRIMARY KEY ( `reference_ID` , `ID` ),' . ' ADD INDEX (`score`), ADD INDEX (`ID`)'); } if ( $last_version && version_compare('3.5.2b3', $last_version) > 0 ) { // flush object cache, as bad is_cached_* values were stored before wp_cache_flush(); } if ( $last_version && version_compare('3.6b1', $last_version) > 0 ) { // remove keywords table if ( defined('YARPP_TABLES_KEYWORDS_TABLE') ) $old_keywords_table = $wpdb->prefix . YARPP_TABLES_KEYWORDS_TABLE; else $old_keywords_table = $wpdb->prefix . 'yarpp_keyword_cache'; $wpdb->query("drop table if exists `$old_keywords_table`"); } } public function cache_status() { global $wpdb; return $wpdb->get_var("select (count(p.ID)-sum(c.ID IS NULL))/count(p.ID) FROM `{$wpdb->posts}` as p LEFT JOIN `{$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . "` as c ON (p.ID = c.reference_ID) 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->prefix}" . YARPP_TABLES_RELATED_TABLE . "` as c ON (p.ID = c.reference_ID) WHERE p.post_status = 'publish' and c.ID 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(id = 0, 0, count(ID)) as num from {$wpdb->prefix}yarpp_related_cache group by reference_ID) as t group by num order by num asc", OBJECT_K), 'ct'); } public function graph_data( $threshold = 5 ) { global $wpdb; $threshold = absint($threshold); $results = $wpdb->get_results("select pair, sum(score) as score from ((select concat(reference_ID, '-', ID) as pair, score from {$wpdb->prefix}yarpp_related_cache where reference_ID < ID) union (select concat(ID, '-', reference_ID) as pair, score from {$wpdb->prefix}yarpp_related_cache where ID < reference_ID)) as t group by pair having sum(score) > {$threshold}"); return $results; } /** * MAGIC FILTERS */ public function join_filter($arg) { global $wpdb; if ($this->yarpp_time) $arg .= " join {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " as yarpp on {$wpdb->posts}.ID = yarpp.ID"; return $arg; } public function where_filter($arg) { global $wpdb; $threshold = $this->core->get_option('threshold'); if ($this->yarpp_time) { $arg = str_replace("$wpdb->posts.ID = ","yarpp.score >= $threshold and yarpp.reference_ID = ",$arg); $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; if ($this->yarpp_time and $this->score_override) $arg = str_replace("$wpdb->posts.post_date","yarpp.score",$arg); return $arg; } public function fields_filter($arg) { global $wpdb; if ($this->yarpp_time) $arg .= ", yarpp.score"; return $arg; } public function limit_filter($arg) { global $wpdb; if ($this->yarpp_time and $this->online_limit) { return " limit {$this->online_limit} "; } return $arg; } /** * RELATEDNESS CACHE CONTROL */ public function begin_yarpp_time() { $this->yarpp_time = true; add_filter('posts_join',array(&$this,'join_filter')); 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; remove_filter('posts_join',array(&$this,'join_filter')); 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')); 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) { global $wpdb; $result = wp_cache_get( 'is_cached_' . $reference_ID, 'yarpp' ); if ( false !== $result ) return $result; // @since 3.5.3b3: check for max instead of min, so that if ID=0 and ID=X // are both saved, we act like there *are* related posts, because there are. $max_id = $wpdb->get_var("select max(ID) as max_id from {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " where reference_ID = $reference_ID"); if ( is_null( $max_id ) ) return YARPP_NOT_CACHED; if ( 0 == $max_id ) $result = YARPP_NO_RELATED; else $result = YARPP_RELATED; wp_cache_set( 'is_cached_' . $reference_ID, $result, 'yarpp' ); return $result; } public function clear( $reference_IDs ) { global $wpdb; $reference_IDs = wp_parse_id_list( $reference_IDs ); if ( !count($reference_IDs) ) return; $wpdb->query("delete from {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " where reference_ID in (".implode(',',$reference_IDs).")"); // @since 3.5.2: clear is_cached_* values as well foreach ( $reference_IDs as $id ) wp_cache_delete( 'is_cached_' . $id, 'yarpp' ); } // @return YARPP_RELATED | YARPP_NO_RELATED // @used by enforce protected function update($reference_ID) { global $wpdb; $original_related = (array) @$this->related($reference_ID); if ( count($original_related) ) { // clear out the cruft $this->clear($reference_ID); } $wpdb->query("insert into {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " (reference_ID,ID,score) " . $this->sql($reference_ID) . " on duplicate key update date = now()"); // If there were related entries saved... if ( $wpdb->rows_affected ) { $new_related = $this->related($reference_ID); if ($this->core->debug) echo ""; // 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 { $wpdb->query("insert into {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " (reference_ID,ID,score) values ($reference_ID,0,0) on duplicate key update date = now()"); // 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() { global $wpdb; $wpdb->query("truncate table `{$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . "`"); // @since 3.5.2: clear object cache, used for is_cached_* values wp_cache_flush(); } 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 = $wpdb->get_col("select ID from {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " where reference_ID = $reference_ID and ID = $related_ID"); return count($results) > 0; } // return a list of ID's of "related" entries if ( !is_null($reference_ID) ) { return $wpdb->get_col("select distinct ID from {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " where reference_ID = $reference_ID and ID != 0"); } // return a list of entities which list this post as "related" if ( !is_null($related_ID) ) { return $wpdb->get_col("select distinct reference_ID from {$wpdb->prefix}" . YARPP_TABLES_RELATED_TABLE . " where ID = $related_ID"); } return false; } // @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' ) { global $wpdb; if ( !is_int($ID) ) return false; // @since 4: compute fresh each time, instead of using cache table. // the old keyword cache would basically have to be recomputed every time the // relatedness cache was recomputed, but no more, so there's no point in keeping // these around separately. $keywords = array( 'body' => $this->body_keywords($ID), 'title' => $this->title_keywords($ID) ); if ( empty($keywords) ) return false; if ( 'all' == $type ) return $keywords; return $keywords[$type]; } }