File "post.php"
Full Path: /home/pylifeesyu/www/wp-content/plugins/bwp-google-xml-sitemaps/src/modules/post.php
File size: 9.69 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Copyright (c) 2011 Khang Minh <betterwp.net>
*
* @license http://www.gnu.org/licenses/gpl.html GNU GENERAL PUBLIC LICENSE
* @package BWP Google XML Sitemaps
*/
class BWP_GXS_MODULE_POST extends BWP_GXS_MODULE
{
public function __construct()
{
// $this->set_current_time() should always be called, it will allow you
// to use $this->now (the current Unix Timestamp).
// @since 1.3.0 this is called from main class
/* $this->set_current_time(); */
// $this->module_data hold four things, but you only need to take
// note of 'sub_module' and 'module_name'. For example when you are
// browsing to http://example.com/taxonomy_category.xml
// $this->module_data['sub_module'] is 'category' (the singular
// name) and $this->module_data['module_name'] is 'taxonomy_category'
// (also singular). If you have a custom module for taxonomy_category,
// you must name your class BWP_GXS_MODULE_TAXONOMY_CATEGORY and save
// the file as taxonomy_category.php (same goes for taxonomy_post_tag.php).
// If no custom post type is requested, use the default post type
// @since 1.3.0 this is set in main class
/* $this->requested = !empty($this->module_data['sub_module']) */
/* ? $this->module_data['sub_module'] : 'post'; */
// $this->module_data['part'] let you determine whether or not to build
// a post sitemap as part of a large post sitemap. If this value is
// greater than 0, for example 2, or 3 it means that we are building
// part 2, or part 3 of that large sitemap, and we will have to modify
// our SQL query accordingly - @since BWP GXS 1.1.0
// @since 1.3.0 this is set in main class
/* $this->part = $bwp_gxs->module_data['module_part']; */
// properties that are not dependent on module data can be initiated here,
// otherwise must be initiated using ::init_module_properties method
$this->perma_struct = get_option('permalink_structure');
// @since 1.3.0 no need to manually call this anymore
/* $this->build_data(); */
}
protected function init_module_properties()
{
$this->post_type = get_post_type_object($this->requested);
}
/**
* Get ids of the images attached with latest posts
*
* @param WP_Post[] $posts
* @return array
* @since 1.4.0
*/
protected function get_image_ids_from_posts(array $posts)
{
$post_ids = array();
foreach ($posts as $post)
$post_ids[] = $post->ID;
if ($post_ids && $this->is_image_allowed())
{
global $wpdb;
$image_query = "
SELECT
pm.post_id,
pm.meta_value as image_id
FROM $wpdb->postmeta pm
WHERE pm.meta_key = '_thumbnail_id'
AND pm.post_id IN (" . implode(',', $post_ids) . ")
";
// this will be an array that have:
// 1. post id as key
// 2. an object with image_id property which is the image id we need
$image_ids = $wpdb->get_results($image_query, OBJECT_K);
// convert image ids to a simple array of post id => image id
foreach ($image_ids as $key => $value)
$image_ids[$key] = $value->image_id;
// get posts without storing the returnd values, this is done to
// warm up the cache for later image-related operation
get_posts(array(
'post_type' => 'attachment',
'include' => array_values($image_ids)
));
return $image_ids;
}
}
/**
* Get actual image data from a single post
*
* @param int $image_id
* @return mixed null|array that should have 'location', 'title' and 'caption'
* @since 1.4.0
*/
protected function get_image_data($image_id)
{
$image = get_post($image_id);
return array(
'location' => wp_get_attachment_thumb_url($image->ID),
'title' => $image->post_title,
'caption' => $image->post_excerpt
);
}
/**
* This is the main function that generates our data.
*
* Since we are dealing with heavy queries here, it's better that you use
* generate_data() which will get called by build_data(). This way you will
* query for no more than the SQL limit configurable in this plugin's
* option page. If you happen to use LIMIT in your SQL statement for other
* reasons then use build_data() instead.
*/
protected function generate_data()
{
global $wpdb, $bwp_gxs, $post;
$requested = $this->requested;
/**
* Filter posts that are added to a post-based sitemaps.
*
* @example hooks/filter_bwp_gxs_excluded_posts.php 2
*
* @param array $post_ids Post IDs to exclude.
* @param string $post_type The post type being processed. See
* http://codex.wordpress.org/Function_Reference/register_post_type
* for more info.
*
* @since 1.3.0 Use a different filter hook that expects an array instead.
*/
$excluded_posts = apply_filters('bwp_gxs_excluded_posts', array(), $requested);
$excluded_posts = $excluded_posts && is_array($excluded_posts) ? $excluded_posts : array();
// @since 1.4.0 if we need to exclude posts by terms, find all the
// posts that belong to excluded terms so we can later exclude them by
// their ids
$excluded_term_ids = apply_filters('bwp_gxs_excluded_terms', array(), null, true);
if ($bwp_gxs->options['enable_exclude_posts_by_terms'] == 'yes'
&& $excluded_term_ids && is_array($excluded_term_ids)
) {
$excluded_term_ids_sql = 'AND t.term_id IN (' . implode(',', $excluded_term_ids) . ')';
$excluded_posts_by_terms_sql = '
SELECT p.ID
FROM ' . $wpdb->posts . ' p
INNER JOIN ' . $wpdb->term_relationships . ' tr
ON tr.object_id = p.ID
INNER JOIN ' . $wpdb->term_taxonomy . ' tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN ' . $wpdb->terms . ' t
ON tt.term_id = t.term_id' . "
WHERE p.post_status = 'publish'
AND p.post_password = ''
AND p.post_type = %s
$excluded_term_ids_sql
GROUP BY p.ID
ORDER BY p.post_modified DESC";
$excluded_posts_by_terms = $wpdb->get_col($wpdb->prepare($excluded_posts_by_terms_sql, $requested));
$excluded_posts = array_merge($excluded_posts, $excluded_posts_by_terms);
}
$excluded_posts_sql = sizeof($excluded_posts) > 0
? ' AND p.ID NOT IN (' . implode(',', $excluded_posts) . ') '
: '';
/**
* Filter the WHERE part of a post module's query.
*
* @example hooks/filter_bwp_gxs_post_where.php 2
*
* @param string $where The `WHERE` part.
* @param string $post_type The current post type.
*
* @return string Make sure you use `p` as the table alias, for e.g.
* `WHERE p.post_password = 'password'`. The `wposts` alias is kept
* for backward-compatibility purpose only and can be removed without
* notice.
*
* @since 1.3.0 This should be used to add other things to the SQL
* instead of excluding posts.
*/
$sql_where = apply_filters('bwp_gxs_post_where', '', $requested);
// @since 1.3.0 use a different alias for post table
$sql_where = str_replace('wposts', 'p', $sql_where);
// If $requested is 'post' and this site uses %category% in
// permalink structure, we will have to use a complex SQL query so
// this plugin can scale up to millions of posts.
if ('post' == $requested && strpos($this->perma_struct, '%category%') !== false)
{
// @since 1.3.0 do not fetch posts that are password-protected
$latest_post_query = '
SELECT *
FROM ' . $wpdb->term_relationships . ' tr
INNER JOIN ' . $wpdb->posts . ' p
ON tr.object_id = p.ID' . "
AND p.post_status = 'publish'
AND p.post_password = ''
AND p.post_type = %s" . '
INNER JOIN ' . $wpdb->term_taxonomy . ' tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id' . "
AND tt.taxonomy = 'category'
INNER JOIN $wpdb->terms t
ON tt.term_id = t.term_id
WHERE 1 = 1
$excluded_posts_sql
$sql_where
GROUP BY p.ID
ORDER BY p.post_modified DESC, p.ID DESC";
}
else
{
// @since 1.3.0 do not fetch posts that are password-protected
$latest_post_query = '
SELECT p.*
FROM ' . $wpdb->posts . " p
WHERE p.post_status = 'publish'
AND p.post_password = ''
AND p.post_type = %s
$excluded_posts_sql
$sql_where" . '
ORDER BY p.post_modified DESC';
}
// Use $this->get_results instead of $wpdb->get_results, remember to
// escape your query using $wpdb->prepare or $wpdb->escape, @see
// http://codex.wordpress.org/Function_Reference/wpdb_Class
$latest_posts = $this->get_results($wpdb->prepare($latest_post_query, $requested));
// This check helps you stop the cycling sooner. It basically means if
// there is nothing to loop through anymore we return false so the
// cycling can stop.
if (!isset($latest_posts) || 0 == sizeof($latest_posts))
return false;
$using_permalinks = $this->using_permalinks();
// always init your $data
$data = array();
// @since 1.4.0 try to get image ids as well
$image_ids = $this->get_image_ids_from_posts($latest_posts);
for ($i = 0; $i < sizeof($latest_posts); $i++)
{
/* @var $post WP_Post */
$post = $latest_posts[$i];
// init your $data with the previous item's data. This makes sure
// no item is mal-formed.
$data = $this->init_data($data);
// @since 1.1.0 - get permalink independently, as we don't need
// caching or some complicated stuff. If permalink is being used,
// yet postname is missing, ignore this item
if ($using_permalinks && empty($post->post_name))
$data['location'] = '';
else
$data['location'] = $this->get_permalink();
$data['lastmod'] = $this->get_lastmod($post);
$data['freq'] = $this->cal_frequency($post);
$data['priority'] = $this->cal_priority($post, $data['freq']);
// prepare an image if there's any
if (isset($image_ids[$post->ID]))
$data['image'] = $this->get_image_data($image_ids[$post->ID]);
// pass data back to the plugin to handle
$this->data[] = $data;
}
unset($latest_posts);
// always return true if we can get here, otherwise you're stuck in a
// SQL cycling loop
return true;
}
}