+/**
+ * Retrieve enclosures already enclosed for a post.
+ *
+ * @since 1.5.0
+ * @uses $wpdb
+ *
+ * @param int $post_id Post ID.
+ * @return array List of enclosures
+ */
+function get_enclosed($post_id) {
+ $custom_fields = get_post_custom( $post_id );
+ $pung = array();
+ if ( !is_array( $custom_fields ) )
+ return $pung;
+
+ foreach ( $custom_fields as $key => $val ) {
+ if ( 'enclosure' != $key || !is_array( $val ) )
+ continue;
+ foreach( $val as $enc ) {
+ $enclosure = split( "\n", $enc );
+ $pung[] = trim( $enclosure[ 0 ] );
+ }
+ }
+ $pung = apply_filters('get_enclosed', $pung);
+ return $pung;
+}
+
+/**
+ * Retrieve URLs already pinged for a post.
+ *
+ * @since 1.5.0
+ * @uses $wpdb
+ *
+ * @param int $post_id Post ID.
+ * @return array
+ */
+function get_pung($post_id) {
+ global $wpdb;
+ $pung = $wpdb->get_var( $wpdb->prepare( "SELECT pinged FROM $wpdb->posts WHERE ID = %d", $post_id ));
+ $pung = trim($pung);
+ $pung = preg_split('/\s/', $pung);
+ $pung = apply_filters('get_pung', $pung);
+ return $pung;
+}
+
+/**
+ * Retrieve URLs that need to be pinged.
+ *
+ * @since 1.5.0
+ * @uses $wpdb
+ *
+ * @param int $post_id Post ID
+ * @return array
+ */
+function get_to_ping($post_id) {
+ global $wpdb;
+ $to_ping = $wpdb->get_var( $wpdb->prepare( "SELECT to_ping FROM $wpdb->posts WHERE ID = %d", $post_id ));
+ $to_ping = trim($to_ping);
+ $to_ping = preg_split('/\s/', $to_ping, -1, PREG_SPLIT_NO_EMPTY);
+ $to_ping = apply_filters('get_to_ping', $to_ping);
+ return $to_ping;
+}
+
+/**
+ * Do trackbacks for a list of URLs.
+ *
+ * @since 1.0.0
+ *
+ * @param string $tb_list Comma separated list of URLs
+ * @param int $post_id Post ID
+ */
+function trackback_url_list($tb_list, $post_id) {
+ if ( ! empty( $tb_list ) ) {
+ // get post data
+ $postdata = wp_get_single_post($post_id, ARRAY_A);
+
+ // import postdata as variables
+ extract($postdata, EXTR_SKIP);
+
+ // form an excerpt
+ $excerpt = strip_tags($post_excerpt ? $post_excerpt : $post_content);
+
+ if (strlen($excerpt) > 255) {
+ $excerpt = substr($excerpt,0,252) . '...';
+ }
+
+ $trackback_urls = explode(',', $tb_list);
+ foreach( (array) $trackback_urls as $tb_url) {
+ $tb_url = trim($tb_url);
+ trackback($tb_url, stripslashes($post_title), $excerpt, $post_id);
+ }
+ }
+}
+
+//
+// Page functions
+//
+
+/**
+ * Get a list of page IDs.
+ *
+ * @since 2.0.0
+ * @uses $wpdb
+ *
+ * @return array List of page IDs.
+ */
+function get_all_page_ids() {
+ global $wpdb;
+
+ if ( ! $page_ids = wp_cache_get('all_page_ids', 'posts') ) {
+ $page_ids = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE post_type = 'page'");
+ wp_cache_add('all_page_ids', $page_ids, 'posts');
+ }
+
+ return $page_ids;
+}
+
+/**
+ * Retrieves page data given a page ID or page object.
+ *
+ * @since 1.5.1
+ *
+ * @param mixed $page Page object or page ID. Passed by reference.
+ * @param string $output What to output. OBJECT, ARRAY_A, or ARRAY_N.
+ * @param string $filter How the return value should be filtered.
+ * @return mixed Page data.
+ */
+function &get_page(&$page, $output = OBJECT, $filter = 'raw') {
+ if ( empty($page) ) {
+ if ( isset( $GLOBALS['post'] ) && isset( $GLOBALS['post']->ID ) ) {
+ return get_post($GLOBALS['post'], $output, $filter);
+ } else {
+ $page = null;
+ return $page;
+ }
+ }
+
+ $the_page = get_post($page, $output, $filter);
+ return $the_page;
+}
+
+/**
+ * Retrieves a page given its path.
+ *
+ * @since 2.1.0
+ * @uses $wpdb
+ *
+ * @param string $page_path Page path
+ * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A.
+ * @return mixed Null when complete.
+ */
+function get_page_by_path($page_path, $output = OBJECT) {
+ global $wpdb;
+ $page_path = rawurlencode(urldecode($page_path));
+ $page_path = str_replace('%2F', '/', $page_path);
+ $page_path = str_replace('%20', ' ', $page_path);
+ $page_paths = '/' . trim($page_path, '/');
+ $leaf_path = sanitize_title(basename($page_paths));
+ $page_paths = explode('/', $page_paths);
+ $full_path = '';
+ foreach( (array) $page_paths as $pathdir)
+ $full_path .= ($pathdir!=''?'/':'') . sanitize_title($pathdir);
+
+ $pages = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE post_name = %s AND (post_type = 'page' OR post_type = 'attachment')", $leaf_path ));
+
+ if ( empty($pages) )
+ return null;
+
+ foreach ($pages as $page) {
+ $path = '/' . $leaf_path;
+ $curpage = $page;
+ while ($curpage->post_parent != 0) {
+ $curpage = $wpdb->get_row( $wpdb->prepare( "SELECT ID, post_name, post_parent FROM $wpdb->posts WHERE ID = %d and post_type='page'", $curpage->post_parent ));
+ $path = '/' . $curpage->post_name . $path;
+ }
+
+ if ( $path == $full_path )
+ return get_page($page->ID, $output);
+ }
+
+ return null;
+}
+
+/**
+ * Retrieve a page given its title.
+ *
+ * @since 2.1.0
+ * @uses $wpdb
+ *
+ * @param string $page_title Page title
+ * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A.
+ * @return mixed
+ */
+function get_page_by_title($page_title, $output = OBJECT) {
+ global $wpdb;
+ $page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type='page'", $page_title ));
+ if ( $page )
+ return get_page($page, $output);
+
+ return null;
+}
+
+/**
+ * Retrieve child pages from list of pages matching page ID.
+ *
+ * Matches against the pages parameter against the page ID. Also matches all
+ * children for the same to retrieve all children of a page. Does not make any
+ * SQL queries to get the children.
+ *
+ * @since 1.5.1
+ *
+ * @param int $page_id Page ID.
+ * @param array $pages List of pages' objects.
+ * @return array
+ */
+function &get_page_children($page_id, $pages) {
+ $page_list = array();
+ foreach ( (array) $pages as $page ) {
+ if ( $page->post_parent == $page_id ) {
+ $page_list[] = $page;
+ if ( $children = get_page_children($page->ID, $pages) )
+ $page_list = array_merge($page_list, $children);
+ }
+ }
+ return $page_list;
+}
+
+/**
+ * Order the pages with children under parents in a flat list.
+ *
+ * It uses auxiliary structure to hold parent-children relationships and
+ * runs in O(N) complexity
+ *
+ * @since 2.0.0
+ *
+ * @param array $posts Posts array.
+ * @param int $parent Parent page ID.
+ * @return array A list arranged by hierarchy. Children immediately follow their parents.
+ */
+function &get_page_hierarchy( &$pages, $page_id = 0 ) {
+
+ if ( empty( $pages ) )
+ return null;
+
+ $children = array();
+ foreach ( (array) $pages as $p ) {
+
+ $parent_id = intval( $p->post_parent );
+ $children[ $parent_id ][] = $p;
+ }
+
+ $result = array();
+ _page_traverse_name( $page_id, $children, $result );
+
+ return $result;
+}
+
+/**
+ * function to traverse and return all the nested children post names of a root page.
+ * $children contains parent-chilren relations
+ *
+ */
+function _page_traverse_name( $page_id, &$children, &$result ){
+
+ if ( isset( $children[ $page_id ] ) ){
+
+ foreach( (array)$children[ $page_id ] as $child ) {
+
+ $result[ $child->ID ] = $child->post_name;
+ _page_traverse_name( $child->ID, $children, $result );
+ }
+ }
+}
+
+/**
+ * Builds URI for a page.
+ *
+ * Sub pages will be in the "directory" under the parent page post name.
+ *
+ * @since 1.5.0
+ *
+ * @param int $page_id Page ID.
+ * @return string Page URI.
+ */
+function get_page_uri($page_id) {
+ $page = get_page($page_id);
+ $uri = $page->post_name;
+
+ // A page cannot be it's own parent.
+ if ( $page->post_parent == $page->ID )
+ return $uri;
+
+ while ($page->post_parent != 0) {
+ $page = get_page($page->post_parent);
+ $uri = $page->post_name . "/" . $uri;
+ }
+
+ return $uri;
+}
+
+/**
+ * Retrieve a list of pages.
+ *
+ * The defaults that can be overridden are the following: 'child_of',
+ * 'sort_order', 'sort_column', 'post_title', 'hierarchical', 'exclude',
+ * 'include', 'meta_key', 'meta_value','authors', 'number', and 'offset'.
+ *
+ * @since 1.5.0
+ * @uses $wpdb
+ *
+ * @param mixed $args Optional. Array or string of options that overrides defaults.
+ * @return array List of pages matching defaults or $args
+ */
+function &get_pages($args = '') {
+ global $wpdb;
+
+ $defaults = array(
+ 'child_of' => 0, 'sort_order' => 'ASC',
+ 'sort_column' => 'post_title', 'hierarchical' => 1,
+ 'exclude' => '', 'include' => '',
+ 'meta_key' => '', 'meta_value' => '',
+ 'authors' => '', 'parent' => -1, 'exclude_tree' => '',
+ 'number' => '', 'offset' => 0
+ );
+
+ $r = wp_parse_args( $args, $defaults );
+ extract( $r, EXTR_SKIP );
+ $number = (int) $number;
+ $offset = (int) $offset;
+
+ $cache = array();
+ $key = md5( serialize( compact(array_keys($defaults)) ) );
+ if ( $cache = wp_cache_get( 'get_pages', 'posts' ) ) {
+ if ( is_array($cache) && isset( $cache[ $key ] ) ) {
+ $pages = apply_filters('get_pages', $cache[ $key ], $r );
+ return $pages;
+ }
+ }
+
+ if ( !is_array($cache) )
+ $cache = array();
+
+ $inclusions = '';
+ if ( !empty($include) ) {
+ $child_of = 0; //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
+ $parent = -1;
+ $exclude = '';
+ $meta_key = '';
+ $meta_value = '';
+ $hierarchical = false;
+ $incpages = preg_split('/[\s,]+/',$include);
+ if ( count($incpages) ) {
+ foreach ( $incpages as $incpage ) {
+ if (empty($inclusions))
+ $inclusions = $wpdb->prepare(' AND ( ID = %d ', $incpage);
+ else
+ $inclusions .= $wpdb->prepare(' OR ID = %d ', $incpage);
+ }
+ }
+ }
+ if (!empty($inclusions))
+ $inclusions .= ')';
+
+ $exclusions = '';
+ if ( !empty($exclude) ) {
+ $expages = preg_split('/[\s,]+/',$exclude);
+ if ( count($expages) ) {
+ foreach ( $expages as $expage ) {
+ if (empty($exclusions))
+ $exclusions = $wpdb->prepare(' AND ( ID <> %d ', $expage);
+ else
+ $exclusions .= $wpdb->prepare(' AND ID <> %d ', $expage);
+ }
+ }
+ }
+ if (!empty($exclusions))
+ $exclusions .= ')';
+
+ $author_query = '';
+ if (!empty($authors)) {
+ $post_authors = preg_split('/[\s,]+/',$authors);
+
+ if ( count($post_authors) ) {
+ foreach ( $post_authors as $post_author ) {
+ //Do we have an author id or an author login?
+ if ( 0 == intval($post_author) ) {
+ $post_author = get_userdatabylogin($post_author);
+ if ( empty($post_author) )
+ continue;
+ if ( empty($post_author->ID) )
+ continue;
+ $post_author = $post_author->ID;
+ }
+
+ if ( '' == $author_query )
+ $author_query = $wpdb->prepare(' post_author = %d ', $post_author);
+ else
+ $author_query .= $wpdb->prepare(' OR post_author = %d ', $post_author);
+ }
+ if ( '' != $author_query )
+ $author_query = " AND ($author_query)";
+ }
+ }
+
+ $join = '';
+ $where = "$exclusions $inclusions ";
+ if ( ! empty( $meta_key ) || ! empty( $meta_value ) ) {
+ $join = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )";
+
+ // meta_key and meta_value might be slashed
+ $meta_key = stripslashes($meta_key);
+ $meta_value = stripslashes($meta_value);
+ if ( ! empty( $meta_key ) )
+ $where .= $wpdb->prepare(" AND $wpdb->postmeta.meta_key = %s", $meta_key);
+ if ( ! empty( $meta_value ) )
+ $where .= $wpdb->prepare(" AND $wpdb->postmeta.meta_value = %s", $meta_value);
+
+ }
+
+ if ( $parent >= 0 )
+ $where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
+
+ $query = "SELECT * FROM $wpdb->posts $join WHERE (post_type = 'page' AND post_status = 'publish') $where ";
+ $query .= $author_query;
+ $query .= " ORDER BY " . $sort_column . " " . $sort_order ;
+
+ if ( !empty($number) )
+ $query .= ' LIMIT ' . $offset . ',' . $number;
+
+ $pages = $wpdb->get_results($query);
+
+ if ( empty($pages) ) {
+ $pages = apply_filters('get_pages', array(), $r);
+ return $pages;
+ }
+
+ // Sanitize before caching so it'll only get done once
+ $num_pages = count($pages);
+ for ($i = 0; $i < $num_pages; $i++) {
+ $pages[$i] = sanitize_post($pages[$i], 'raw');
+ }
+
+ // Update cache.
+ update_page_cache($pages);
+
+ if ( $child_of || $hierarchical )
+ $pages = & get_page_children($child_of, $pages);
+
+ if ( !empty($exclude_tree) ) {
+ $exclude = (int) $exclude_tree;
+ $children = get_page_children($exclude, $pages);
+ $excludes = array();
+ foreach ( $children as $child )
+ $excludes[] = $child->ID;
+ $excludes[] = $exclude;
+ $num_pages = count($pages);
+ for ( $i = 0; $i < $num_pages; $i++ ) {
+ if ( in_array($pages[$i]->ID, $excludes) )
+ unset($pages[$i]);
+ }
+ }
+
+ $cache[ $key ] = $pages;
+ wp_cache_set( 'get_pages', $cache, 'posts' );
+
+ $pages = apply_filters('get_pages', $pages, $r);
+
+ return $pages;
+}
+
+//
+// Attachment functions
+//
+
+/**
+ * Check if the attachment URI is local one and is really an attachment.
+ *
+ * @since 2.0.0
+ *
+ * @param string $url URL to check
+ * @return bool True on success, false on failure.
+ */
+function is_local_attachment($url) {
+ if (strpos($url, get_bloginfo('url')) === false)
+ return false;
+ if (strpos($url, get_bloginfo('url') . '/?attachment_id=') !== false)
+ return true;
+ if ( $id = url_to_postid($url) ) {
+ $post = & get_post($id);
+ if ( 'attachment' == $post->post_type )
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Insert an attachment.
+ *
+ * If you set the 'ID' in the $object parameter, it will mean that you are
+ * updating and attempt to update the attachment. You can also set the
+ * attachment name or title by setting the key 'post_name' or 'post_title'.
+ *
+ * You can set the dates for the attachment manually by setting the 'post_date'
+ * and 'post_date_gmt' keys' values.
+ *
+ * By default, the comments will use the default settings for whether the
+ * comments are allowed. You can close them manually or keep them open by
+ * setting the value for the 'comment_status' key.
+ *
+ * The $object parameter can have the following:
+ * 'post_status' - Default is 'draft'. Can not be overridden, set the same as parent post.
+ * 'post_type' - Default is 'post', will be set to attachment. Can not override.
+ * 'post_author' - Default is current user ID. The ID of the user, who added the attachment.
+ * 'ping_status' - Default is the value in default ping status option. Whether the attachment
+ * can accept pings.
+ * 'post_parent' - Default is 0. Can use $parent parameter or set this for the post it belongs
+ * to, if any.
+ * 'menu_order' - Default is 0. The order it is displayed.
+ * 'to_ping' - Whether to ping.
+ * 'pinged' - Default is empty string.
+ * 'post_password' - Default is empty string. The password to access the attachment.
+ * 'guid' - Global Unique ID for referencing the attachment.
+ * 'post_content_filtered' - Attachment post content filtered.
+ * 'post_excerpt' - Attachment excerpt.
+ *
+ * @since 2.0.0
+ * @uses $wpdb
+ * @uses $user_ID
+ * @uses do_action() Calls 'edit_attachment' on $post_ID if this is an update.
+ * @uses do_action() Calls 'add_attachment' on $post_ID if this is not an update.
+ *
+ * @param string|array $object Arguments to override defaults.
+ * @param string $file Optional filename.
+ * @param int $post_parent Parent post ID.
+ * @return int Attachment ID.
+ */
+function wp_insert_attachment($object, $file = false, $parent = 0) {
+ global $wpdb, $user_ID;
+
+ $defaults = array('post_status' => 'draft', 'post_type' => 'post', 'post_author' => $user_ID,
+ 'ping_status' => get_option('default_ping_status'), 'post_parent' => 0,
+ 'menu_order' => 0, 'to_ping' => '', 'pinged' => '', 'post_password' => '',
+ 'guid' => '', 'post_content_filtered' => '', 'post_excerpt' => '', 'import_id' => 0);
+
+ $object = wp_parse_args($object, $defaults);
+ if ( !empty($parent) )
+ $object['post_parent'] = $parent;
+
+ $object = sanitize_post($object, 'db');
+
+ // export array as variables
+ extract($object, EXTR_SKIP);
+
+ // Make sure we set a valid category
+ if ( !isset($post_category) || 0 == count($post_category) || !is_array($post_category)) {
+ $post_category = array(get_option('default_category'));
+ }
+
+ if ( empty($post_author) )
+ $post_author = $user_ID;
+
+ $post_type = 'attachment';
+ $post_status = 'inherit';
+
+ // Are we updating or creating?
+ if ( !empty($ID) ) {
+ $update = true;
+ $post_ID = (int) $ID;
+ } else {
+ $update = false;
+ $post_ID = 0;
+ }
+
+ // Create a valid post name.
+ if ( empty($post_name) )
+ $post_name = sanitize_title($post_title);
+ else
+ $post_name = sanitize_title($post_name);
+
+ // expected_slashed ($post_name)
+ $post_name = wp_unique_post_slug($post_name, $post_ID, $post_status, $post_type, $post_parent);
+
+ if ( empty($post_date) )
+ $post_date = current_time('mysql');
+ if ( empty($post_date_gmt) )
+ $post_date_gmt = current_time('mysql', 1);
+
+ if ( empty($post_modified) )
+ $post_modified = $post_date;
+ if ( empty($post_modified_gmt) )
+ $post_modified_gmt = $post_date_gmt;
+
+ if ( empty($comment_status) ) {
+ if ( $update )
+ $comment_status = 'closed';
+ else
+ $comment_status = get_option('default_comment_status');
+ }
+ if ( empty($ping_status) )
+ $ping_status = get_option('default_ping_status');
+
+ if ( isset($to_ping) )
+ $to_ping = preg_replace('|\s+|', "\n", $to_ping);
+ else
+ $to_ping = '';
+
+ if ( isset($post_parent) )
+ $post_parent = (int) $post_parent;
+ else
+ $post_parent = 0;
+
+ if ( isset($menu_order) )
+ $menu_order = (int) $menu_order;
+ else
+ $menu_order = 0;
+
+ if ( !isset($post_password) )
+ $post_password = '';
+
+ if ( ! isset($pinged) )
+ $pinged = '';
+
+ // expected_slashed (everything!)
+ $data = compact( array( 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_content_filtered', 'post_title', 'post_excerpt', 'post_status', 'post_type', 'comment_status', 'ping_status', 'post_password', 'post_name', 'to_ping', 'pinged', 'post_modified', 'post_modified_gmt', 'post_parent', 'menu_order', 'post_mime_type', 'guid' ) );
+ $data = stripslashes_deep( $data );
+
+ if ( $update ) {
+ $wpdb->update( $wpdb->posts, $data, array( 'ID' => $post_ID ) );
+ } else {
+ // If there is a suggested ID, use it if not already present
+ if ( !empty($import_id) ) {
+ $import_id = (int) $import_id;
+ if ( ! $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE ID = %d", $import_id) ) ) {
+ $data['ID'] = $import_id;
+ }
+ }
+
+ $wpdb->insert( $wpdb->posts, $data );
+ $post_ID = (int) $wpdb->insert_id;
+ }
+
+ if ( empty($post_name) ) {
+ $post_name = sanitize_title($post_title, $post_ID);
+ $wpdb->update( $wpdb->posts, compact("post_name"), array( 'ID' => $post_ID ) );
+ }
+
+ wp_set_post_categories($post_ID, $post_category);
+
+ if ( $file )
+ update_attached_file( $post_ID, $file );
+
+ clean_post_cache($post_ID);
+
+ if ( isset($post_parent) && $post_parent < 0 )
+ add_post_meta($post_ID, '_wp_attachment_temp_parent', $post_parent, true);
+
+ if ( $update) {
+ do_action('edit_attachment', $post_ID);
+ } else {
+ do_action('add_attachment', $post_ID);
+ }
+
+ return $post_ID;
+}
+
+/**
+ * Delete an attachment.
+ *
+ * Will remove the file also, when the attachment is removed. Removes all post
+ * meta fields, taxonomy, comments, etc associated with the attachment (except
+ * the main post).
+ *
+ * @since 2.0.0
+ * @uses $wpdb
+ * @uses do_action() Calls 'delete_attachment' hook on Attachment ID.
+ *
+ * @param int $postid Attachment ID.
+ * @param bool $force_delete Whether to bypass trash and force deletion
+ * @return mixed False on failure. Post data on success.
+ */
+function wp_delete_attachment( $post_id, $force_delete = false ) {
+ global $wpdb;
+
+ if ( !$post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) ) )
+ return $post;
+
+ if ( 'attachment' != $post->post_type )
+ return false;
+
+ if ( !$force_delete && EMPTY_TRASH_DAYS && MEDIA_TRASH && 'trash' != $post->post_status )
+ return wp_trash_post( $post_id );
+
+ delete_post_meta($post_id, '_wp_trash_meta_status');
+ delete_post_meta($post_id, '_wp_trash_meta_time');
+
+ $meta = wp_get_attachment_metadata( $post_id );
+ $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
+ $file = get_attached_file( $post_id );
+
+ do_action('delete_attachment', $post_id);
+
+ wp_delete_object_term_relationships($post_id, array('category', 'post_tag'));
+ wp_delete_object_term_relationships($post_id, get_object_taxonomies($post->post_type));
+
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_thumbnail_id' AND meta_value = %d", $post_id ));
+
+ $comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id ));
+ if ( ! empty($comment_ids) ) {
+ do_action( 'delete_comment', $comment_ids );
+ $in_comment_ids = "'" . implode("', '", $comment_ids) . "'";
+ $wpdb->query( "DELETE FROM $wpdb->comments WHERE comment_ID IN($in_comment_ids)" );
+ do_action( 'deleted_comment', $comment_ids );
+ }
+
+ $post_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d ", $post_id ));
+ if ( !empty($post_meta_ids) ) {
+ do_action( 'delete_postmeta', $post_meta_ids );
+ $in_post_meta_ids = "'" . implode("', '", $post_meta_ids) . "'";
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_id IN($in_post_meta_ids)" );
+ do_action( 'deleted_postmeta', $post_meta_ids );
+ }
+
+ do_action( 'delete_post', $post_id );
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE ID = %d", $post_id ));
+ do_action( 'deleted_post', $post_id );
+
+ $uploadpath = wp_upload_dir();
+
+ if ( ! empty($meta['thumb']) ) {
+ // Don't delete the thumb if another attachment uses it
+ if (! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $meta['thumb'] . '%', $post_id)) ) {
+ $thumbfile = str_replace(basename($file), $meta['thumb'], $file);
+ $thumbfile = apply_filters('wp_delete_file', $thumbfile);
+ @ unlink( path_join($uploadpath['basedir'], $thumbfile) );
+ }
+ }
+
+ // remove intermediate and backup images if there are any
+ $sizes = apply_filters('intermediate_image_sizes', array('thumbnail', 'medium', 'large'));
+ foreach ( $sizes as $size ) {
+ if ( $intermediate = image_get_intermediate_size($post_id, $size) ) {
+ $intermediate_file = apply_filters('wp_delete_file', $intermediate['path']);
+ @ unlink( path_join($uploadpath['basedir'], $intermediate_file) );
+ }
+ }
+
+ if ( is_array($backup_sizes) ) {
+ foreach ( $backup_sizes as $size ) {
+ $del_file = path_join( dirname($meta['file']), $size['file'] );
+ $del_file = apply_filters('wp_delete_file', $del_file);
+ @ unlink( path_join($uploadpath['basedir'], $del_file) );
+ }
+ }
+
+ $file = apply_filters('wp_delete_file', $file);
+
+ if ( ! empty($file) )
+ @ unlink($file);
+
+ clean_post_cache($post_id);
+
+ return $post;
+}
+
+/**
+ * Retrieve attachment meta field for attachment ID.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID
+ * @param bool $unfiltered Optional, default is false. If true, filters are not run.
+ * @return string|bool Attachment meta field. False on failure.
+ */
+function wp_get_attachment_metadata( $post_id, $unfiltered = false ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+
+ $data = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
+
+ if ( $unfiltered )
+ return $data;
+
+ return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
+}
+
+/**
+ * Update metadata for an attachment.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID.
+ * @param array $data Attachment data.
+ * @return int
+ */
+function wp_update_attachment_metadata( $post_id, $data ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+
+ $data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID );
+
+ return update_post_meta( $post->ID, '_wp_attachment_metadata', $data);
+}
+
+/**
+ * Retrieve the URL for an attachment.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID.
+ * @return string
+ */
+function wp_get_attachment_url( $post_id = 0 ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+
+ $url = '';
+ if ( $file = get_post_meta( $post->ID, '_wp_attached_file', true) ) { //Get attached file
+ if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) { //Get upload directory
+ if ( 0 === strpos($file, $uploads['basedir']) ) //Check that the upload base exists in the file location
+ $url = str_replace($uploads['basedir'], $uploads['baseurl'], $file); //replace file location with url location
+ elseif ( false !== strpos($file, 'wp-content/uploads') )
+ $url = $uploads['baseurl'] . substr( $file, strpos($file, 'wp-content/uploads') + 18 );
+ else
+ $url = $uploads['baseurl'] . "/$file"; //Its a newly uploaded file, therefor $file is relative to the basedir.
+ }
+ }
+
+ if ( empty($url) ) //If any of the above options failed, Fallback on the GUID as used pre-2.7, not recomended to rely upon this.
+ $url = get_the_guid( $post->ID );
+
+ if ( 'attachment' != $post->post_type || empty($url) )
+ return false;
+
+ return apply_filters( 'wp_get_attachment_url', $url, $post->ID );
+}
+
+/**
+ * Retrieve thumbnail for an attachment.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID.
+ * @return mixed False on failure. Thumbnail file path on success.
+ */
+function wp_get_attachment_thumb_file( $post_id = 0 ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+ if ( !is_array( $imagedata = wp_get_attachment_metadata( $post->ID ) ) )
+ return false;
+
+ $file = get_attached_file( $post->ID );
+
+ if ( !empty($imagedata['thumb']) && ($thumbfile = str_replace(basename($file), $imagedata['thumb'], $file)) && file_exists($thumbfile) )
+ return apply_filters( 'wp_get_attachment_thumb_file', $thumbfile, $post->ID );
+ return false;
+}
+
+/**
+ * Retrieve URL for an attachment thumbnail.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID
+ * @return string|bool False on failure. Thumbnail URL on success.
+ */
+function wp_get_attachment_thumb_url( $post_id = 0 ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+ if ( !$url = wp_get_attachment_url( $post->ID ) )
+ return false;
+
+ $sized = image_downsize( $post_id, 'thumbnail' );
+ if ( $sized )
+ return $sized[0];
+
+ if ( !$thumb = wp_get_attachment_thumb_file( $post->ID ) )
+ return false;
+
+ $url = str_replace(basename($url), basename($thumb), $url);
+
+ return apply_filters( 'wp_get_attachment_thumb_url', $url, $post->ID );
+}
+
+/**
+ * Check if the attachment is an image.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Attachment ID
+ * @return bool
+ */
+function wp_attachment_is_image( $post_id = 0 ) {
+ $post_id = (int) $post_id;
+ if ( !$post =& get_post( $post_id ) )
+ return false;
+
+ if ( !$file = get_attached_file( $post->ID ) )
+ return false;
+
+ $ext = preg_match('/\.([^.]+)$/', $file, $matches) ? strtolower($matches[1]) : false;
+
+ $image_exts = array('jpg', 'jpeg', 'gif', 'png');
+
+ if ( 'image/' == substr($post->post_mime_type, 0, 6) || $ext && 'import' == $post->post_mime_type && in_array($ext, $image_exts) )
+ return true;
+ return false;
+}
+
+/**
+ * Retrieve the icon for a MIME type.
+ *
+ * @since 2.1.0
+ *
+ * @param string $mime MIME type
+ * @return string|bool
+ */
+function wp_mime_type_icon( $mime = 0 ) {
+ if ( !is_numeric($mime) )
+ $icon = wp_cache_get("mime_type_icon_$mime");
+ if ( empty($icon) ) {
+ $post_id = 0;
+ $post_mimes = array();
+ if ( is_numeric($mime) ) {
+ $mime = (int) $mime;
+ if ( $post =& get_post( $mime ) ) {
+ $post_id = (int) $post->ID;
+ $ext = preg_replace('/^.+?\.([^.]+)$/', '$1', $post->guid);
+ if ( !empty($ext) ) {
+ $post_mimes[] = $ext;
+ if ( $ext_type = wp_ext2type( $ext ) )
+ $post_mimes[] = $ext_type;
+ }
+ $mime = $post->post_mime_type;
+ } else {
+ $mime = 0;
+ }
+ } else {
+ $post_mimes[] = $mime;
+ }
+
+ $icon_files = wp_cache_get('icon_files');
+
+ if ( !is_array($icon_files) ) {
+ $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/crystal' );
+ $icon_dir_uri = apply_filters( 'icon_dir_uri', includes_url('images/crystal') );
+ $dirs = apply_filters( 'icon_dirs', array($icon_dir => $icon_dir_uri) );
+ $icon_files = array();
+ while ( $dirs ) {
+ $dir = array_shift($keys = array_keys($dirs));
+ $uri = array_shift($dirs);
+ if ( $dh = opendir($dir) ) {
+ while ( false !== $file = readdir($dh) ) {
+ $file = basename($file);
+ if ( substr($file, 0, 1) == '.' )
+ continue;
+ if ( !in_array(strtolower(substr($file, -4)), array('.png', '.gif', '.jpg') ) ) {
+ if ( is_dir("$dir/$file") )
+ $dirs["$dir/$file"] = "$uri/$file";
+ continue;
+ }
+ $icon_files["$dir/$file"] = "$uri/$file";
+ }
+ closedir($dh);
+ }
+ }
+ wp_cache_set('icon_files', $icon_files, 600);
+ }
+
+ // Icon basename - extension = MIME wildcard
+ foreach ( $icon_files as $file => $uri )
+ $types[ preg_replace('/^([^.]*).*$/', '$1', basename($file)) ] =& $icon_files[$file];
+
+ if ( ! empty($mime) ) {
+ $post_mimes[] = substr($mime, 0, strpos($mime, '/'));
+ $post_mimes[] = substr($mime, strpos($mime, '/') + 1);
+ $post_mimes[] = str_replace('/', '_', $mime);
+ }
+
+ $matches = wp_match_mime_types(array_keys($types), $post_mimes);
+ $matches['default'] = array('default');
+
+ foreach ( $matches as $match => $wilds ) {
+ if ( isset($types[$wilds[0]])) {
+ $icon = $types[$wilds[0]];
+ if ( !is_numeric($mime) )
+ wp_cache_set("mime_type_icon_$mime", $icon);
+ break;
+ }
+ }
+ }
+
+ return apply_filters( 'wp_mime_type_icon', $icon, $mime, $post_id ); // Last arg is 0 if function pass mime type.
+}
+
+/**
+ * Checked for changed slugs for published posts and save old slug.
+ *
+ * The function is used along with form POST data. It checks for the wp-old-slug
+ * POST field. Will only be concerned with published posts and the slug actually
+ * changing.
+ *
+ * If the slug was changed and not already part of the old slugs then it will be
+ * added to the post meta field ('_wp_old_slug') for storing old slugs for that
+ * post.
+ *
+ * The most logically usage of this function is redirecting changed posts, so
+ * that those that linked to an changed post will be redirected to the new post.
+ *
+ * @since 2.1.0
+ *
+ * @param int $post_id Post ID.
+ * @return int Same as $post_id
+ */
+function wp_check_for_changed_slugs($post_id) {
+ if ( !isset($_POST['wp-old-slug']) || !strlen($_POST['wp-old-slug']) )
+ return $post_id;
+
+ $post = &get_post($post_id);
+
+ // we're only concerned with published posts
+ if ( $post->post_status != 'publish' || $post->post_type != 'post' )
+ return $post_id;
+
+ // only bother if the slug has changed
+ if ( $post->post_name == $_POST['wp-old-slug'] )
+ return $post_id;
+
+ $old_slugs = (array) get_post_meta($post_id, '_wp_old_slug');
+
+ // if we haven't added this old slug before, add it now
+ if ( !count($old_slugs) || !in_array($_POST['wp-old-slug'], $old_slugs) )
+ add_post_meta($post_id, '_wp_old_slug', $_POST['wp-old-slug']);
+
+ // if the new slug was used previously, delete it from the list
+ if ( in_array($post->post_name, $old_slugs) )
+ delete_post_meta($post_id, '_wp_old_slug', $post->post_name);
+
+ return $post_id;
+}
+
+/**
+ * Retrieve the private post SQL based on capability.
+ *
+ * This function provides a standardized way to appropriately select on the
+ * post_status of posts/pages. The function will return a piece of SQL code that
+ * can be added to a WHERE clause; this SQL is constructed to allow all
+ * published posts, and all private posts to which the user has access.
+ *
+ * It also allows plugins that define their own post type to control the cap by
+ * using the hook 'pub_priv_sql_capability'. The plugin is expected to return
+ * the capability the user must have to read the private post type.
+ *
+ * @since 2.2.0
+ *
+ * @uses $user_ID
+ * @uses apply_filters() Call 'pub_priv_sql_capability' filter for plugins with different post types.
+ *
+ * @param string $post_type currently only supports 'post' or 'page'.
+ * @return string SQL code that can be added to a where clause.
+ */
+function get_private_posts_cap_sql($post_type) {
+ global $user_ID;
+ $cap = '';
+
+ // Private posts
+ if ($post_type == 'post') {
+ $cap = 'read_private_posts';
+ // Private pages
+ } elseif ($post_type == 'page') {
+ $cap = 'read_private_pages';
+ // Dunno what it is, maybe plugins have their own post type?
+ } else {
+ $cap = apply_filters('pub_priv_sql_capability', $cap);
+
+ if (empty($cap)) {
+ // We don't know what it is, filters don't change anything,
+ // so set the SQL up to return nothing.
+ return '1 = 0';
+ }
+ }
+
+ $sql = '(post_status = \'publish\'';
+
+ if (current_user_can($cap)) {
+ // Does the user have the capability to view private posts? Guess so.
+ $sql .= ' OR post_status = \'private\'';
+ } elseif (is_user_logged_in()) {
+ // Users can view their own private posts.
+ $sql .= ' OR post_status = \'private\' AND post_author = \'' . $user_ID . '\'';
+ }
+
+ $sql .= ')';
+
+ return $sql;
+}
+
+/**
+ * Retrieve the date the the last post was published.
+ *
+ * The server timezone is the default and is the difference between GMT and
+ * server time. The 'blog' value is the date when the last post was posted. The
+ * 'gmt' is when the last post was posted in GMT formatted date.
+ *
+ * @since 0.71
+ *
+ * @uses $wpdb
+ * @uses $blog_id
+ * @uses apply_filters() Calls 'get_lastpostdate' filter
+ *
+ * @global mixed $cache_lastpostdate Stores the last post date
+ * @global mixed $pagenow The current page being viewed
+ *
+ * @param string $timezone The location to get the time. Can be 'gmt', 'blog', or 'server'.
+ * @return string The date of the last post.
+ */
+function get_lastpostdate($timezone = 'server') {
+ global $cache_lastpostdate, $wpdb, $blog_id;
+ $add_seconds_server = date('Z');
+ if ( !isset($cache_lastpostdate[$blog_id][$timezone]) ) {
+ switch(strtolower($timezone)) {
+ case 'gmt':
+ $lastpostdate = $wpdb->get_var("SELECT post_date_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_date_gmt DESC LIMIT 1");
+ break;
+ case 'blog':
+ $lastpostdate = $wpdb->get_var("SELECT post_date FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_date_gmt DESC LIMIT 1");
+ break;
+ case 'server':
+ $lastpostdate = $wpdb->get_var("SELECT DATE_ADD(post_date_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_date_gmt DESC LIMIT 1");
+ break;
+ }
+ $cache_lastpostdate[$blog_id][$timezone] = $lastpostdate;
+ } else {
+ $lastpostdate = $cache_lastpostdate[$blog_id][$timezone];
+ }
+ return apply_filters( 'get_lastpostdate', $lastpostdate, $timezone );
+}
+
+/**
+ * Retrieve last post modified date depending on timezone.
+ *
+ * The server timezone is the default and is the difference between GMT and
+ * server time. The 'blog' value is just when the last post was modified. The
+ * 'gmt' is when the last post was modified in GMT time.
+ *
+ * @since 1.2.0
+ * @uses $wpdb
+ * @uses $blog_id
+ * @uses apply_filters() Calls 'get_lastpostmodified' filter
+ *
+ * @global mixed $cache_lastpostmodified Stores the date the last post was modified
+ *
+ * @param string $timezone The location to get the time. Can be 'gmt', 'blog', or 'server'.
+ * @return string The date the post was last modified.
+ */
+function get_lastpostmodified($timezone = 'server') {
+ global $cache_lastpostmodified, $wpdb, $blog_id;
+ $add_seconds_server = date('Z');
+ if ( !isset($cache_lastpostmodified[$blog_id][$timezone]) ) {
+ switch(strtolower($timezone)) {
+ case 'gmt':
+ $lastpostmodified = $wpdb->get_var("SELECT post_modified_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_modified_gmt DESC LIMIT 1");
+ break;
+ case 'blog':
+ $lastpostmodified = $wpdb->get_var("SELECT post_modified FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_modified_gmt DESC LIMIT 1");
+ break;
+ case 'server':
+ $lastpostmodified = $wpdb->get_var("SELECT DATE_ADD(post_modified_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY post_modified_gmt DESC LIMIT 1");
+ break;
+ }
+ $lastpostdate = get_lastpostdate($timezone);
+ if ( $lastpostdate > $lastpostmodified ) {
+ $lastpostmodified = $lastpostdate;
+ }
+ $cache_lastpostmodified[$blog_id][$timezone] = $lastpostmodified;
+ } else {
+ $lastpostmodified = $cache_lastpostmodified[$blog_id][$timezone];
+ }
+ return apply_filters( 'get_lastpostmodified', $lastpostmodified, $timezone );
+}
+
+/**
+ * Updates posts in cache.
+ *
+ * @usedby update_page_cache() Aliased by this function.
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 1.5.1
+ *
+ * @param array $posts Array of post objects
+ */
+function update_post_cache(&$posts) {
+ if ( !$posts )
+ return;
+
+ foreach ( $posts as $post )
+ wp_cache_add($post->ID, $post, 'posts');
+}
+
+/**
+ * Will clean the post in the cache.
+ *
+ * Cleaning means delete from the cache of the post. Will call to clean the term
+ * object cache associated with the post ID.
+ *
+ * clean_post_cache() will call itself recursively for each child post.
+ *
+ * This function not run if $_wp_suspend_cache_invalidation is not empty. See
+ * wp_suspend_cache_invalidation().
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 2.0.0
+ *
+ * @uses do_action() Calls 'clean_post_cache' on $id before adding children (if any).
+ *
+ * @param int $id The Post ID in the cache to clean
+ */
+function clean_post_cache($id) {
+ global $_wp_suspend_cache_invalidation, $wpdb;
+
+ if ( !empty($_wp_suspend_cache_invalidation) )
+ return;
+
+ $id = (int) $id;
+
+ wp_cache_delete($id, 'posts');
+ wp_cache_delete($id, 'post_meta');
+
+ clean_object_term_cache($id, 'post');
+
+ wp_cache_delete( 'wp_get_archives', 'general' );
+
+ do_action('clean_post_cache', $id);
+
+ if ( $children = $wpdb->get_col( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_parent = %d", $id) ) ) {
+ foreach( $children as $cid )
+ clean_post_cache( $cid );
+ }
+}
+
+/**
+ * Alias of update_post_cache().
+ *
+ * @see update_post_cache() Posts and pages are the same, alias is intentional
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 1.5.1
+ *
+ * @param array $pages list of page objects
+ */
+function update_page_cache(&$pages) {
+ update_post_cache($pages);
+}
+
+/**
+ * Will clean the page in the cache.
+ *
+ * Clean (read: delete) page from cache that matches $id. Will also clean cache
+ * associated with 'all_page_ids' and 'get_pages'.
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 2.0.0
+ *
+ * @uses do_action() Will call the 'clean_page_cache' hook action.
+ *
+ * @param int $id Page ID to clean
+ */
+function clean_page_cache($id) {
+ clean_post_cache($id);
+
+ wp_cache_delete( 'all_page_ids', 'posts' );
+ wp_cache_delete( 'get_pages', 'posts' );
+
+ do_action('clean_page_cache', $id);
+}
+
+/**
+ * Call major cache updating functions for list of Post objects.
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 1.5.0
+ *
+ * @uses $wpdb
+ * @uses update_post_cache()
+ * @uses update_object_term_cache()
+ * @uses update_postmeta_cache()
+ *
+ * @param array $posts Array of Post objects
+ */
+function update_post_caches(&$posts) {
+ // No point in doing all this work if we didn't match any posts.
+ if ( !$posts )
+ return;
+
+ update_post_cache($posts);
+
+ $post_ids = array();
+
+ for ($i = 0; $i < count($posts); $i++)
+ $post_ids[] = $posts[$i]->ID;
+
+ update_object_term_cache($post_ids, 'post');
+
+ update_postmeta_cache($post_ids);
+}
+
+/**
+ * Updates metadata cache for list of post IDs.
+ *
+ * Performs SQL query to retrieve the metadata for the post IDs and updates the
+ * metadata cache for the posts. Therefore, the functions, which call this
+ * function, do not need to perform SQL queries on their own.
+ *
+ * @package WordPress
+ * @subpackage Cache
+ * @since 2.1.0
+ *
+ * @uses $wpdb
+ *
+ * @param array $post_ids List of post IDs.
+ * @return bool|array Returns false if there is nothing to update or an array of metadata.
+ */
+function update_postmeta_cache($post_ids) {
+ return update_meta_cache('post', $post_ids);
+}
+
+//
+// Hooks
+//
+
+/**
+ * Hook for managing future post transitions to published.
+ *
+ * @since 2.3.0
+ * @access private
+ * @uses $wpdb
+ * @uses do_action() Calls 'private_to_published' on post ID if this is a 'private_to_published' call.
+ * @uses wp_clear_scheduled_hook() with 'publish_future_post' and post ID.
+ *
+ * @param string $new_status New post status
+ * @param string $old_status Previous post status
+ * @param object $post Object type containing the post information
+ */
+function _transition_post_status($new_status, $old_status, $post) {
+ global $wpdb;
+
+ if ( $old_status != 'publish' && $new_status == 'publish' ) {
+ // Reset GUID if transitioning to publish and it is empty
+ if ( '' == get_the_guid($post->ID) )
+ $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post->ID ) ), array( 'ID' => $post->ID ) );
+ do_action('private_to_published', $post->ID); // Deprecated, use private_to_publish
+ }
+
+ // Always clears the hook in case the post status bounced from future to draft.
+ wp_clear_scheduled_hook('publish_future_post', $post->ID);
+}
+
+/**
+ * Hook used to schedule publication for a post marked for the future.
+ *
+ * The $post properties used and must exist are 'ID' and 'post_date_gmt'.
+ *
+ * @since 2.3.0
+ * @access private
+ *
+ * @param int $deprecated Not Used. Can be set to null.
+ * @param object $post Object type containing the post information
+ */
+function _future_post_hook($deprecated = '', $post) {
+ wp_clear_scheduled_hook( 'publish_future_post', $post->ID );
+ wp_schedule_single_event(strtotime($post->post_date_gmt. ' GMT'), 'publish_future_post', array($post->ID));
+}
+
+/**
+ * Hook to schedule pings and enclosures when a post is published.
+ *
+ * @since 2.3.0
+ * @access private
+ * @uses $wpdb
+ * @uses XMLRPC_REQUEST and APP_REQUEST constants.
+ * @uses do_action() Calls 'xmlprc_publish_post' on post ID if XMLRPC_REQUEST is defined.
+ * @uses do_action() Calls 'app_publish_post' on post ID if APP_REQUEST is defined.
+ *
+ * @param int $post_id The ID in the database table of the post being published
+ */
+function _publish_post_hook($post_id) {
+ global $wpdb;
+
+ if ( defined('XMLRPC_REQUEST') )
+ do_action('xmlrpc_publish_post', $post_id);
+ if ( defined('APP_REQUEST') )
+ do_action('app_publish_post', $post_id);
+
+ if ( defined('WP_IMPORTING') )
+ return;
+
+ $data = array( 'post_id' => $post_id, 'meta_value' => '1' );
+ if ( get_option('default_pingback_flag') ) {
+ $wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_pingme' ) );
+ do_action( 'added_postmeta', $wpdb->insert_id, $post_id, '_pingme', 1 );
+ }
+ $wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_encloseme' ) );
+ do_action( 'added_postmeta', $wpdb->insert_id, $post_id, '_encloseme', 1 );
+
+ wp_schedule_single_event(time(), 'do_pings');
+}
+
+/**
+ * Hook used to prevent page/post cache and rewrite rules from staying dirty.
+ *
+ * Does two things. If the post is a page and has a template then it will
+ * update/add that template to the meta. For both pages and posts, it will clean
+ * the post cache to make sure that the cache updates to the changes done
+ * recently. For pages, the rewrite rules of WordPress are flushed to allow for
+ * any changes.
+ *
+ * The $post parameter, only uses 'post_type' property and 'page_template'
+ * property.
+ *
+ * @since 2.3.0
+ * @access private
+ * @uses $wp_rewrite Flushes Rewrite Rules.
+ *
+ * @param int $post_id The ID in the database table for the $post
+ * @param object $post Object type containing the post information
+ */
+function _save_post_hook($post_id, $post) {
+ if ( $post->post_type == 'page' ) {
+ clean_page_cache($post_id);
+ // Avoid flushing rules for every post during import.
+ if ( !defined('WP_IMPORTING') ) {
+ global $wp_rewrite;
+ $wp_rewrite->flush_rules(false);
+ }
+ } else {
+ clean_post_cache($post_id);
+ }
+}