]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/post.php
WordPress 3.9
[autoinstalls/wordpress.git] / wp-includes / post.php
index 857cd17a8eb4ba497f6c06f156a70408d4ce0983..d537148d29b157f855391c4a6a05eab35273c71b 100644 (file)
@@ -74,6 +74,8 @@ function create_initial_post_types() {
                'delete_with_user' => true,
                'supports' => array( 'title', 'author', 'comments' ),
        ) );
+       add_post_type_support( 'attachment:audio', 'thumbnail' );
+       add_post_type_support( 'attachment:video', 'thumbnail' );
 
        register_post_type( 'revision', array(
                'labels' => array(
@@ -189,6 +191,15 @@ function get_attached_file( $attachment_id, $unfiltered = false ) {
                $file = $uploads['basedir'] . "/$file";
        if ( $unfiltered )
                return $file;
+
+       /**
+        * Filter the attached file based on the given ID.
+        *
+        * @since 2.1.0
+        *
+        * @param string $file          Path to attached file.
+        * @param int    $attachment_id Attachment ID.
+        */
        return apply_filters( 'get_attached_file', $file, $attachment_id );
 }
 
@@ -199,7 +210,6 @@ function get_attached_file( $attachment_id, $unfiltered = false ) {
  * '_wp_attached_file' to store the path of the attachment.
  *
  * @since 2.1.0
- * @uses apply_filters() Calls 'update_attached_file' on file path and attachment ID.
  *
  * @param int $attachment_id Attachment ID
  * @param string $file File path for the attachment
@@ -209,7 +219,16 @@ function update_attached_file( $attachment_id, $file ) {
        if ( !get_post( $attachment_id ) )
                return false;
 
+       /**
+        * Filter the path to the attached file to update.
+        *
+        * @since 2.1.0
+        *
+        * @param string $file          Path to the attached file to update.
+        * @param int    $attachment_id Attachment ID.
+        */
        $file = apply_filters( 'update_attached_file', $file, $attachment_id );
+
        if ( $file = _wp_relative_upload_path( $file ) )
                return update_post_meta( $attachment_id, '_wp_attached_file', $file );
        else
@@ -222,7 +241,6 @@ function update_attached_file( $attachment_id, $file ) {
  * The path is relative to the current upload dir.
  *
  * @since 2.9.0
- * @uses apply_filters() Calls '_wp_relative_upload_path' on file path.
  *
  * @param string $path Full path to the file
  * @return string relative path on success, unchanged path on failure.
@@ -236,6 +254,14 @@ function _wp_relative_upload_path( $path ) {
                        $new_path = ltrim( $new_path, '/' );
        }
 
+       /**
+        * Filter the relative path to an uploaded file.
+        *
+        * @since 2.9.0
+        *
+        * @param string $new_path Relative path to the file.
+        * @param string $path     Full path to the file.
+        */
        return apply_filters( '_wp_relative_upload_path', $new_path, $path );
 }
 
@@ -380,7 +406,7 @@ function get_extended($post) {
  * @since 1.5.1
  * @link http://codex.wordpress.org/Function_Reference/get_post
  *
- * @param int|object $post Post ID or post object. Optional, default is the current post from the loop.
+ * @param int|WP_Post $post Optional. Post ID or post object.
  * @param string $output Optional, default is Object. Either OBJECT, ARRAY_A, or ARRAY_N.
  * @param string $filter Optional, default is raw.
  * @return WP_Post|null WP_Post on success or null on failure
@@ -710,7 +736,7 @@ final class WP_Post {
  *
  * @since 2.5.0
  *
- * @param int|object $post Post ID or post object
+ * @param int|WP_Post $post Post ID or post object.
  * @return array Ancestor IDs or empty array if none are found.
  */
 function get_post_ancestors( $post ) {
@@ -747,7 +773,7 @@ function get_post_ancestors( $post ) {
  * @uses sanitize_post_field() See for possible $context values.
  *
  * @param string $field Post field name.
- * @param int|object $post Post ID or post object.
+ * @param int|WP_Post $post Post ID or post object.
  * @param string $context Optional. How to filter the field. Default is 'display'.
  * @return string The value of the post field on success, empty string on failure.
  */
@@ -771,7 +797,7 @@ function get_post_field( $field, $post, $context = 'display' ) {
  *
  * @since 2.0.0
  *
- * @param int $ID Optional. Post ID. Default is the current post from the loop.
+ * @param int|WP_Post $ID Optional. Post ID or post object.
  * @return string|bool The mime type on success, false on failure.
  */
 function get_post_mime_type($ID = '') {
@@ -791,7 +817,7 @@ function get_post_mime_type($ID = '') {
  *
  * @since 2.0.0
  *
- * @param int $ID Optional. Post ID. Default is the current post from the loop.
+ * @param int|WP_Post $ID Optional. Post ID or post object.
  * @return string|bool Post status on success, false on failure.
  */
 function get_post_status($ID = '') {
@@ -876,8 +902,6 @@ function get_page_statuses() {
  *
  * Arguments prefixed with an _underscore shouldn't be used by plugins and themes.
  *
- * @package WordPress
- * @subpackage Post
  * @since 3.0.0
  * @uses $wp_post_statuses Inserts new post status object into the list
  *
@@ -951,8 +975,6 @@ function register_post_status($post_status, $args = array()) {
 /**
  * Retrieve a post status object by name
  *
- * @package WordPress
- * @subpackage Post
  * @since 3.0.0
  * @uses $wp_post_statuses
  * @see register_post_status
@@ -973,8 +995,6 @@ function get_post_status_object( $post_status ) {
 /**
  * Get a list of all registered post status objects.
  *
- * @package WordPress
- * @subpackage Post
  * @since 3.0.0
  * @uses $wp_post_statuses
  * @see register_post_status
@@ -1031,7 +1051,7 @@ function post_type_exists( $post_type ) {
  *
  * @since 2.1.0
  *
- * @param int|object $post Optional. Post ID or post object. Default is the current post from the loop.
+ * @param int|WP_Post $post Optional. Post ID or post object.
  * @return string|bool Post type on success, false on failure.
  */
 function get_post_type( $post = null ) {
@@ -1044,8 +1064,6 @@ function get_post_type( $post = null ) {
 /**
  * Retrieve a post type object by name
  *
- * @package WordPress
- * @subpackage Post
  * @since 3.0.0
  * @uses $wp_post_types
  * @see register_post_type
@@ -1066,8 +1084,6 @@ function get_post_type_object( $post_type ) {
 /**
  * Get a list of all registered post type objects.
  *
- * @package WordPress
- * @subpackage Post
  * @since 2.9.0
  * @uses $wp_post_types
  * @see register_post_type
@@ -1131,7 +1147,7 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' )
  * - menu_icon - The url to the icon to be used for this menu. Defaults to use the posts icon.
  *     * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme.
  *      This should begin with 'data:image/svg+xml;base64,'.
- *     * Pass the name of a Dashicons helper class to use a font icon, e.g. 'dashicons-piechart'.
+ *     * Pass the name of a Dashicons helper class to use a font icon, e.g. 'dashicons-chart-pie'.
  *     * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
  * - capability_type - The string to use to build the read, edit, and delete capabilities. Defaults to 'post'.
  *     * May be passed as an array to allow for alternative plurals when using this argument as a base to construct the
@@ -1335,6 +1351,14 @@ function register_post_type( $post_type, $args = array() ) {
                register_taxonomy_for_object_type( $taxonomy, $post_type );
        }
 
+       /**
+        * Fires after a post type is registered.
+        *
+        * @since 3.3.0
+        *
+        * @param string $post_type Post type.
+        * @param array  $args      Arguments used to register the post type.
+        */
        do_action( 'registered_post_type', $post_type, $args );
 
        return $args;
@@ -1501,6 +1525,19 @@ function get_post_type_labels( $post_type_object ) {
        $labels = _get_custom_object_labels( $post_type_object, $nohier_vs_hier_defaults );
 
        $post_type = $post_type_object->name;
+
+       /**
+        * Filter the labels of a specific post type.
+        *
+        * The dynamic portion of the hook name, $post_type, refers to
+        * the post type slug.
+        *
+        * @since 3.5.0
+        *
+        * @see get_post_type_labels() for the full list of labels.
+        *
+        * @param array $labels Array of labels for the given post type.
+        */
        return apply_filters( "post_type_labels_{$post_type}", $labels );
 }
 
@@ -1555,16 +1592,20 @@ add_action( 'admin_menu', '_add_post_type_submenus' );
 /**
  * Register support of certain features for a post type.
  *
- * All features are directly associated with a functional area of the edit screen, such as the
- * editor or a meta box: 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author',
- * 'excerpt', 'page-attributes', 'thumbnail', and 'custom-fields'.
+ * All core features are directly associated with a functional area of the edit
+ * screen, such as the editor or a meta box. Features include: 'title', 'editor',
+ * 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes',
+ * 'thumbnail', 'custom-fields', and 'post-formats'.
  *
- * Additionally, the 'revisions' feature dictates whether the post type will store revisions,
- * and the 'comments' feature dictates whether the comments count will show on the edit screen.
+ * Additionally, the 'revisions' feature dictates whether the post type will
+ * store revisions, and the 'comments' feature dictates whether the comments
+ * count will show on the edit screen.
  *
  * @since 3.0.0
- * @param string $post_type The post type for which to add the feature
- * @param string|array $feature the feature being added, can be an array of feature strings or a single string
+ *
+ * @param string       $post_type The post type for which to add the feature.
+ * @param string|array $feature   The feature being added, accpets an array of
+ *                                feature strings or a single string.
  */
 function add_post_type_support( $post_type, $feature ) {
        global $_wp_post_type_features;
@@ -1785,7 +1826,7 @@ function get_post_meta($post_id, $key = '', $single = false) {
  * @param string $meta_key Metadata key.
  * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
  * @param mixed $prev_value Optional. Previous value to check before removing.
- * @return bool True on success, false on failure.
+ * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
  */
 function update_post_meta($post_id, $meta_key, $meta_value, $prev_value = '') {
        // make sure meta is added to the post, not a revision
@@ -1941,17 +1982,6 @@ function sanitize_post($post, $context = 'display') {
  * when calling filters.
  *
  * @since 2.3.0
- * @uses apply_filters() Calls 'edit_$field' and '{$field_no_prefix}_edit_pre' passing $value and
- *  $post_id if $context == 'edit' and field name prefix == 'post_'.
- *
- * @uses apply_filters() Calls 'edit_post_$field' passing $value and $post_id if $context == 'db'.
- * @uses apply_filters() Calls 'pre_$field' passing $value if $context == 'db' and field name prefix == 'post_'.
- * @uses apply_filters() Calls '{$field}_pre' passing $value if $context == 'db' and field name prefix != 'post_'.
- *
- * @uses apply_filters() Calls '$field' passing $value, $post_id and $context if $context == anything
- *  other than 'raw', 'edit' and 'db' and field name prefix == 'post_'.
- * @uses apply_filters() Calls 'post_$field' passing $value if $context == anything other than 'raw',
- *  'edit' and 'db' and field name prefix != 'post_'.
  *
  * @param string $field The Post Object field name.
  * @param mixed $value The Post Object value.
@@ -1985,11 +2015,33 @@ function sanitize_post_field($field, $value, $post_id, $context) {
                $format_to_edit = array('post_content', 'post_excerpt', 'post_title', 'post_password');
 
                if ( $prefixed ) {
-                       $value = apply_filters("edit_{$field}", $value, $post_id);
-                       // Old school
-                       $value = apply_filters("{$field_no_prefix}_edit_pre", $value, $post_id);
+
+                       /**
+                        * Filter the value of a specific post field to edit.
+                        *
+                        * The dynamic portion of the hook name, $field, refers to the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed $value   Value of the post field.
+                        * @param int   $post_id Post ID.
+                        */
+                       $value = apply_filters( "edit_{$field}", $value, $post_id );
+
+                       /**
+                        * Filter the value of a specific post field to edit.
+                        *
+                        * The dynamic portion of the hook name, $field_no_prefix, refers to
+                        * the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed $value   Value of the post field.
+                        * @param int   $post_id Post ID.
+                        */
+                       $value = apply_filters( "{$field_no_prefix}_edit_pre", $value, $post_id );
                } else {
-                       $value = apply_filters("edit_post_{$field}", $value, $post_id);
+                       $value = apply_filters( "edit_post_{$field}", $value, $post_id );
                }
 
                if ( in_array($field, $format_to_edit) ) {
@@ -2002,18 +2054,65 @@ function sanitize_post_field($field, $value, $post_id, $context) {
                }
        } else if ( 'db' == $context ) {
                if ( $prefixed ) {
-                       $value = apply_filters("pre_{$field}", $value);
-                       $value = apply_filters("{$field_no_prefix}_save_pre", $value);
+
+                       /**
+                        * Filter the value of a specific post field before saving.
+                        *
+                        * The dynamic portion of the hook name, $field, refers to the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed $value Value of the post field.
+                        */
+                       $value = apply_filters( "pre_{$field}", $value );
+
+                       /**
+                        * Filter the value of a specific field before saving.
+                        *
+                        * The dynamic portion of the hook name, $field_no_prefix, refers
+                        * to the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed $value Value of the post field.
+                        */
+                       $value = apply_filters( "{$field_no_prefix}_save_pre", $value );
                } else {
-                       $value = apply_filters("pre_post_{$field}", $value);
-                       $value = apply_filters("{$field}_pre", $value);
+                       $value = apply_filters( "pre_post_{$field}", $value );
+
+                       /**
+                        * Filter the value of a specific post field before saving.
+                        *
+                        * The dynamic portion of the hook name, $field, refers to the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed $value Value of the post field.
+                        */
+                       $value = apply_filters( "{$field}_pre", $value );
                }
        } else {
+
                // Use display filters by default.
-               if ( $prefixed )
-                       $value = apply_filters($field, $value, $post_id, $context);
-               else
-                       $value = apply_filters("post_{$field}", $value, $post_id, $context);
+               if ( $prefixed ) {
+
+                       /**
+                        * Filter the value of a specific post field for display.
+                        *
+                        * The dynamic portion of the hook name, $field, refers to the post field name.
+                        *
+                        * @since 2.3.0
+                        *
+                        * @param mixed  $value   Value of the prefixed post field.
+                        * @param int    $post_id Post ID.
+                        * @param string $context Context for how to sanitize the field. Possible
+                        *                        values include 'raw', 'edit', 'db', 'display',
+                        *                        'attribute' and 'js'.
+                        */
+                       $value = apply_filters( $field, $value, $post_id, $context );
+               } else {
+                       $value = apply_filters( "post_{$field}", $value, $post_id, $context );
+               }
        }
 
        if ( 'attribute' == $context )
@@ -2072,6 +2171,26 @@ function unstick_post($post_id) {
        update_option('sticky_posts', $stickies);
 }
 
+/**
+ * Return the cache key for wp_count_posts() based on the passed arguments
+ *
+ * @since 3.9.0
+ *
+ * @param string $type Optional. Post type to retrieve count
+ * @param string $perm Optional. 'readable' or empty.
+ * @return string The cache key.
+ */
+function _count_posts_cache_key( $type = 'post', $perm = '' ) {
+       $cache_key = 'posts-' . $type;
+       if ( 'readable' == $perm && is_user_logged_in() ) {
+               $post_type_object = get_post_type_object( $type );
+               if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
+                       $cache_key .= '_' . $perm . '_' . get_current_user_id();
+               }
+       }
+       return $cache_key;
+}
+
 /**
  * Count number of posts of a post type and if user has permissions to view.
  *
@@ -2097,16 +2216,15 @@ function wp_count_posts( $type = 'post', $perm = '' ) {
        if ( ! post_type_exists( $type ) )
                return new stdClass;
 
-       $user = wp_get_current_user();
-
-       $cache_key = 'posts-' . $type;
+       $cache_key = _count_posts_cache_key( $type, $perm );
 
        $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
        if ( 'readable' == $perm && is_user_logged_in() ) {
                $post_type_object = get_post_type_object($type);
-               if ( !current_user_can( $post_type_object->cap->read_private_posts ) ) {
-                       $cache_key .= '_' . $perm . '_' . $user->ID;
-                       $query .= " AND (post_status != 'private' OR ( post_author = '$user->ID' AND post_status = 'private' ))";
+               if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
+                       $query .= $wpdb->prepare( " AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
+                               get_current_user_id()
+                       );
                }
        }
        $query .= ' GROUP BY post_status';
@@ -2128,9 +2246,11 @@ function wp_count_posts( $type = 'post', $perm = '' ) {
         *
         * @since 3.7.0
         *
-        * @param object $counts An object containing the current post_type's post counts by status.
-        * @param string $type   The post type.
-        * @param string $perm   The permission to determine if the posts are 'readable' by the current user.
+        * @param object $counts An object containing the current post_type's post
+        *                       counts by status.
+        * @param string $type   Post type.
+        * @param string $perm   The permission to determine if the posts are 'readable'
+        *                       by the current user.
         */
        return apply_filters( 'wp_count_posts', $counts, $type, $perm );
 }
@@ -2146,7 +2266,7 @@ function wp_count_posts( $type = 'post', $perm = '' ) {
  * @since 2.5.0
  *
  * @param string|array $mime_type Optional. Array or comma-separated list of MIME patterns.
- * @return array Number of posts for each mime type.
+ * @return object An object containing the attachment counts by mime type.
  */
 function wp_count_attachments( $mime_type = '' ) {
        global $wpdb;
@@ -2185,7 +2305,14 @@ function get_post_mime_types() {
                'video' => array(__('Video'), __('Manage Video'), _n_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
        );
 
-       return apply_filters('post_mime_types', $post_mime_types);
+       /**
+        * Filter the default list of post mime types.
+        *
+        * @since 2.5.0
+        *
+        * @param array $post_mime_types Default list of post mime types.
+        */
+       return apply_filters( 'post_mime_types', $post_mime_types );
 }
 
 /**
@@ -2282,8 +2409,7 @@ function wp_post_mime_type_where($post_mime_types, $table_alias = '') {
  * disabled, item is already in the trash, or $force_delete is true.
  *
  * @since 1.0.0
- * @uses do_action() on 'delete_post' before deletion unless post type is 'attachment'.
- * @uses do_action() on 'deleted_post' after deletion unless post type is 'attachment'.
+ *
  * @uses wp_delete_attachment() if post type is 'attachment'.
  * @uses wp_trash_post() if item should be trashed.
  *
@@ -2303,7 +2429,16 @@ function wp_delete_post( $postid = 0, $force_delete = false ) {
        if ( $post->post_type == 'attachment' )
                return wp_delete_attachment( $postid, $force_delete );
 
-       do_action('before_delete_post', $postid);
+       /**
+        * Fires before a post is deleted, at the start of wp_delete_post().
+        *
+        * @since 3.2.0
+        *
+        * @see wp_delete_post()
+        *
+        * @param int $postid Post ID.
+        */
+       do_action( 'before_delete_post', $postid );
 
        delete_post_meta($postid,'_wp_trash_meta_status');
        delete_post_meta($postid,'_wp_trash_meta_time');
@@ -2338,11 +2473,26 @@ function wp_delete_post( $postid = 0, $force_delete = false ) {
        foreach ( $post_meta_ids as $mid )
                delete_metadata_by_mid( 'post', $mid );
 
+       /**
+        * Fires immediately before a post is deleted from the database.
+        *
+        * @since 1.2.0
+        *
+        * @param int $postid Post ID.
+        */
        do_action( 'delete_post', $postid );
        $result = $wpdb->delete( $wpdb->posts, array( 'ID' => $postid ) );
        if ( ! $result ) {
                return false;
        }
+
+       /**
+        * Fires immediately after a post is deleted from the database.
+        *
+        * @since 2.2.0
+        *
+        * @param int $postid Post ID.
+        */
        do_action( 'deleted_post', $postid );
 
        clean_post_cache( $post );
@@ -2354,7 +2504,16 @@ function wp_delete_post( $postid = 0, $force_delete = false ) {
 
        wp_clear_scheduled_hook('publish_future_post', array( $postid ) );
 
-       do_action('after_delete_post', $postid);
+       /**
+        * Fires after a post is deleted, at the conclusion of wp_delete_post().
+        *
+        * @since 3.2.0
+        *
+        * @see wp_delete_post()
+        *
+        * @param int $postid Post ID.
+        */
+       do_action( 'after_delete_post', $postid );
 
        return $post;
 }
@@ -2393,8 +2552,7 @@ add_action( 'wp_trash_post',      '_reset_front_page_settings_for_post' );
  * If trash is disabled, the post or page is permanently deleted.
  *
  * @since 2.9.0
- * @uses do_action() on 'trash_post' before trashing
- * @uses do_action() on 'trashed_post' after trashing
+ *
  * @uses wp_delete_post() if trash is disabled
  *
  * @param int $post_id Post ID.
@@ -2410,7 +2568,14 @@ function wp_trash_post($post_id = 0) {
        if ( $post['post_status'] == 'trash' )
                return false;
 
-       do_action('wp_trash_post', $post_id);
+       /**
+        * Fires before a post is sent to the trash.
+        *
+        * @since 3.3.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'wp_trash_post', $post_id );
 
        add_post_meta($post_id,'_wp_trash_meta_status', $post['post_status']);
        add_post_meta($post_id,'_wp_trash_meta_time', time());
@@ -2420,7 +2585,14 @@ function wp_trash_post($post_id = 0) {
 
        wp_trash_post_comments($post_id);
 
-       do_action('trashed_post', $post_id);
+       /**
+        * Fires after a post is sent to the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'trashed_post', $post_id );
 
        return $post;
 }
@@ -2429,8 +2601,6 @@ function wp_trash_post($post_id = 0) {
  * Restores a post or page from the Trash
  *
  * @since 2.9.0
- * @uses do_action() on 'untrash_post' before undeletion
- * @uses do_action() on 'untrashed_post' after undeletion
  *
  * @param int $post_id Post ID.
  * @return mixed False on failure
@@ -2442,7 +2612,14 @@ function wp_untrash_post($post_id = 0) {
        if ( $post['post_status'] != 'trash' )
                return false;
 
-       do_action('untrash_post', $post_id);
+       /**
+        * Fires before a post is restored from the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'untrash_post', $post_id );
 
        $post_status = get_post_meta($post_id, '_wp_trash_meta_status', true);
 
@@ -2455,7 +2632,14 @@ function wp_untrash_post($post_id = 0) {
 
        wp_untrash_post_comments($post_id);
 
-       do_action('untrashed_post', $post_id);
+       /**
+        * Fires after a post is restored from the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'untrashed_post', $post_id );
 
        return $post;
 }
@@ -2464,10 +2648,8 @@ function wp_untrash_post($post_id = 0) {
  * Moves comments for a post to the trash
  *
  * @since 2.9.0
- * @uses do_action() on 'trash_post_comments' before trashing
- * @uses do_action() on 'trashed_post_comments' after trashing
  *
- * @param int|object $post Post ID or object.
+ * @param int|WP_Post $post Optional. Post ID or post object.
  * @return mixed False on failure
  */
 function wp_trash_post_comments($post = null) {
@@ -2479,7 +2661,14 @@ function wp_trash_post_comments($post = null) {
 
        $post_id = $post->ID;
 
-       do_action('trash_post_comments', $post_id);
+       /**
+        * Fires before comments are sent to the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'trash_post_comments', $post_id );
 
        $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_ID, comment_approved FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id) );
        if ( empty($comments) )
@@ -2496,7 +2685,15 @@ function wp_trash_post_comments($post = null) {
 
        clean_comment_cache( array_keys($statuses) );
 
-       do_action('trashed_post_comments', $post_id, $statuses);
+       /**
+        * Fires after comments are sent to the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int   $post_id  Post ID.
+        * @param array $statuses Array of comment statuses.
+        */
+       do_action( 'trashed_post_comments', $post_id, $statuses );
 
        return $result;
 }
@@ -2505,10 +2702,8 @@ function wp_trash_post_comments($post = null) {
  * Restore comments for a post from the trash
  *
  * @since 2.9.0
- * @uses do_action() on 'untrash_post_comments' before trashing
- * @uses do_action() on 'untrashed_post_comments' after trashing
  *
- * @param int|object $post Post ID or object.
+ * @param int|WP_Post $post Optional. Post ID or post object.
  * @return mixed False on failure
  */
 function wp_untrash_post_comments($post = null) {
@@ -2525,7 +2720,14 @@ function wp_untrash_post_comments($post = null) {
        if ( empty($statuses) )
                return true;
 
-       do_action('untrash_post_comments', $post_id);
+       /**
+        * Fires before comments are restored for a post from the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'untrash_post_comments', $post_id );
 
        // Restore each comment to its original status
        $group_by_status = array();
@@ -2544,7 +2746,14 @@ function wp_untrash_post_comments($post = null) {
 
        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
 
-       do_action('untrashed_post_comments', $post_id);
+       /**
+        * Fires after comments are restored for a post from the trash.
+        *
+        * @since 2.9.0
+        *
+        * @param int $post_id Post ID.
+        */
+       do_action( 'untrashed_post_comments', $post_id );
 }
 
 /**
@@ -2578,8 +2787,6 @@ function wp_get_post_categories( $post_id = 0, $args = array() ) {
  * is set to 'all'. There are other defaults that can be overridden in
  * {@link wp_get_object_terms()}.
  *
- * @package WordPress
- * @subpackage Post
  * @since 2.3.0
  *
  * @uses wp_get_object_terms() Gets the tags for returning. Args can be found here
@@ -2599,8 +2806,6 @@ function wp_get_post_tags( $post_id = 0, $args = array() ) {
  * is set to 'all'. There are other defaults that can be overridden in
  * {@link wp_get_object_terms()}.
  *
- * @package WordPress
- * @subpackage Post
  * @since 2.8.0
  *
  * @uses wp_get_object_terms() Gets the tags for returning. Args can be found here
@@ -2682,21 +2887,21 @@ function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) {
  * @param array $postarr {
  *     An array of elements that make up a post to update or insert.
  *
- *     @type int    'ID'                    The post ID. If equal to something other than 0, the post with that ID will
- *                                          be updated. Default 0.
- *     @type string 'post_status'           The post status. Default 'draft'.
- *     @type string 'post_type'             The post type. Default 'post'.
- *     @type int    'post_author'           The ID of the user who added the post. Default the current user ID.
- *     @type bool   'ping_status'           Whether the post can accept pings. Default value of 'default_ping_status' option.
- *     @type int    'post_parent'           Set this for the post it belongs to, if any. Default 0.
- *     @type int    'menu_order'            The order it is displayed. Default 0.
- *     @type string 'to_ping'               Space or carriage return-separated list of URLs to ping. Default empty string.
- *     @type string 'pinged'                Space or carriage return-separated list of URLs that have been pinged.
- *                                          Default empty string.
- *     @type string 'post_password          The password to access the post. Default empty string.
- *     @type string 'guid'                  Global Unique ID for referencing the post.
- *     @type string 'post_content_filtered' The filtered post content. Default empty string.
- *     @type string 'post_excerpt'          The post excerpt. Default empty string.
+ *     @type int    $ID                    The post ID. If equal to something other than 0, the post with that ID will
+ *                                         be updated. Default 0.
+ *     @type string $post_status           The post status. Default 'draft'.
+ *     @type string $post_type             The post type. Default 'post'.
+ *     @type int    $post_author           The ID of the user who added the post. Default the current user ID.
+ *     @type bool   $ping_status           Whether the post can accept pings. Default value of 'default_ping_status' option.
+ *     @type int    $post_parent           Set this for the post it belongs to, if any. Default 0.
+ *     @type int    $menu_order            The order it is displayed. Default 0.
+ *     @type string $to_ping               Space or carriage return-separated list of URLs to ping. Default empty string.
+ *     @type string $pinged                Space or carriage return-separated list of URLs that have been pinged.
+ *                                         Default empty string.
+ *     @type string $post_password         The password to access the post. Default empty string.
+ *     @type string $guid'                 Global Unique ID for referencing the post.
+ *     @type string $post_content_filtered The filtered post content. Default empty string.
+ *     @type string $post_excerpt          The post excerpt. Default empty string.
  * }
  * @param bool  $wp_error Optional. Allow return of WP_Error on failure.
  * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
@@ -2745,6 +2950,22 @@ function wp_insert_post( $postarr, $wp_error = false ) {
        $maybe_empty = ! $post_content && ! $post_title && ! $post_excerpt && post_type_supports( $post_type, 'editor' )
                && post_type_supports( $post_type, 'title' ) && post_type_supports( $post_type, 'excerpt' );
 
+       /**
+        * Filter whether the post should be considered "empty".
+        *
+        * The post is considered "empty" if both:
+        * 1. The post type supports the title, editor, and excerpt fields
+        * 2. The title, editor, and excerpt fields are all empty
+        *
+        * Returning a truthy value to the filter will effectively short-circuit
+        * the new post being inserted, returning 0. If $wp_error is true, a WP_Error
+        * will be returned instead.
+        *
+        * @since 3.3.0
+        *
+        * @param bool  $maybe_empty Whether the post should be considered "empty".
+        * @param array $postarr     Array of post data.
+        */
        if ( apply_filters( 'wp_insert_post_empty_content', $maybe_empty, $postarr ) ) {
                if ( $wp_error )
                        return new WP_Error( 'empty_content', __( 'Content, title, and excerpt are empty.' ) );
@@ -2856,7 +3077,16 @@ function wp_insert_post( $postarr, $wp_error = false ) {
        else
                $post_parent = 0;
 
-       // Check the post_parent to see if it will cause a hierarchy loop
+       /**
+        * Filter the post parent -- used to check for and prevent hierarchy loops.
+        *
+        * @since 3.1.0
+        *
+        * @param int   $post_parent Post parent ID.
+        * @param int   $post_ID     Post ID.
+        * @param array $new_postarr Array of parsed post data.
+        * @param array $postarr     Array of sanitized, but otherwise unmodified post data.
+        */
        $post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr ) ), $postarr );
 
        if ( isset($menu_order) )
@@ -2871,11 +3101,28 @@ function wp_insert_post( $postarr, $wp_error = false ) {
 
        // 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', 'guid' ) );
-       $data = apply_filters('wp_insert_post_data', $data, $postarr);
+
+       /**
+        * Filter slashed post data just before it is inserted into the database.
+        *
+        * @since 2.7.0
+        *
+        * @param array $data    Array of slashed post data.
+        * @param array $postarr Array of sanitized, but otherwise unmodified post data.
+        */
+       $data = apply_filters( 'wp_insert_post_data', $data, $postarr );
        $data = wp_unslash( $data );
        $where = array( 'ID' => $post_ID );
 
        if ( $update ) {
+               /**
+                * Fires immediately before an existing post is updated in the database.
+                *
+                * @since 2.5.0
+                *
+                * @param int   $post_ID Post ID.
+                * @param array $data    Array of unslashed post data.
+                */
                do_action( 'pre_post_update', $post_ID, $data );
                if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
                        if ( $wp_error )
@@ -2939,7 +3186,7 @@ function wp_insert_post( $postarr, $wp_error = false ) {
 
        if ( !empty($page_template) && 'page' == $data['post_type'] ) {
                $post->page_template = $page_template;
-               $page_templates = wp_get_theme()->get_page_templates();
+               $page_templates = wp_get_theme()->get_page_templates( $post );
                if ( 'default' != $page_template && ! isset( $page_templates[ $page_template ] ) ) {
                        if ( $wp_error )
                                return new WP_Error('invalid_page_template', __('The page template is invalid.'));
@@ -2952,13 +3199,63 @@ function wp_insert_post( $postarr, $wp_error = false ) {
        wp_transition_post_status($data['post_status'], $previous_status, $post);
 
        if ( $update ) {
-               do_action('edit_post', $post_ID, $post);
+               /**
+                * Fires once an existing post has been updated.
+                *
+                * @since 1.2.0
+                *
+                * @param int     $post_ID Post ID.
+                * @param WP_Post $post    Post object.
+                */
+               do_action( 'edit_post', $post_ID, $post );
                $post_after = get_post($post_ID);
+
+               /**
+                * Fires once an existing post has been updated.
+                *
+                * @since 3.0.0
+                *
+                * @param int     $post_ID      Post ID.
+                * @param WP_Post $post_after   Post object following the update.
+                * @param WP_Post $post_before  Post object before the update.
+                */
                do_action( 'post_updated', $post_ID, $post_after, $post_before);
        }
 
+       /**
+        * Fires once a post has been saved.
+        *
+        * The dynamic portion of the hook name, $post->post_type, refers to
+        * the post type slug.
+        *
+        * @since 3.7.0
+        *
+        * @param int     $post_ID Post ID.
+        * @param WP_Post $post    Post object.
+        * @param bool    $update  Whether this is an existing post being updated or not.
+        */
        do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
+
+       /**
+        * Fires once a post has been saved.
+        *
+        * @since 1.5.0
+        *
+        * @param int     $post_ID Post ID.
+        * @param WP_Post $post    Post object.
+        * @param bool    $update  Whether this is an existing post being updated or not.
+        */
        do_action( 'save_post', $post_ID, $post, $update );
+
+       /**
+        * Fires once a post has been saved.
+        *
+        * @since 2.0.0
+        *
+        * @param int     $post_ID Post ID.
+        * @param WP_Post $post    Post object.
+        * @param bool    $update  Whether this is an existing post being updated or not.
+        */
        do_action( 'wp_insert_post', $post_ID, $post, $update );
 
        return $post_ID;
@@ -3028,9 +3325,8 @@ function wp_update_post( $postarr = array(), $wp_error = false ) {
  *
  * @since 2.1.0
  * @uses $wpdb
- * @uses do_action() Calls 'edit_post', 'save_post_{$post_type}', 'save_post' and 'wp_insert_post' on post_id and post data.
  *
- * @param int|object $post Post ID or object.
+ * @param int|WP_Post $post Post ID or post object.
  */
 function wp_publish_post( $post ) {
        global $wpdb;
@@ -3049,9 +3345,13 @@ function wp_publish_post( $post ) {
        $post->post_status = 'publish';
        wp_transition_post_status( 'publish', $old_status, $post );
 
+       /** This action is documented in wp-includes/post.php */
        do_action( 'edit_post', $post->ID, $post );
+       /** This action is documented in wp-includes/post.php */
        do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
+       /** This action is documented in wp-includes/post.php */
        do_action( 'save_post', $post->ID, $post, true );
+       /** This action is documented in wp-includes/post.php */
        do_action( 'wp_insert_post', $post->ID, $post, true );
 }
 
@@ -3063,7 +3363,7 @@ function wp_publish_post( $post ) {
  *
  * @since 2.5.0
  *
- * @param int $post_id Post ID.
+ * @param int|WP_Post $post_id Post ID or post object.
  * @return null Nothing is returned. Which can mean that no action is required or post was published.
  */
 function check_and_publish_future_post($post_id) {
@@ -3119,6 +3419,14 @@ function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_p
                $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
                $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );
 
+               /**
+                * Filter whether the post slug would make a bad attachment slug.
+                *
+                * @since 3.1.0
+                *
+                * @param bool   $bad_slug Whether the slug would be bad as an attachment slug.
+                * @param string $slug     The post slug.
+                */
                if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug ) ) {
                        $suffix = 2;
                        do {
@@ -3131,11 +3439,24 @@ function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_p
        } elseif ( in_array( $post_type, $hierarchical_post_types ) ) {
                if ( 'nav_menu_item' == $post_type )
                        return $slug;
-               // Page slugs must be unique within their own trees. Pages are in a separate
-               // namespace than posts so page slugs are allowed to overlap post slugs.
+
+               /*
+                * Page slugs must be unique within their own trees. Pages are in a separate
+                * namespace than posts so page slugs are allowed to overlap post slugs.
+                */
                $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( '" . implode( "', '", esc_sql( $hierarchical_post_types ) ) . "' ) AND ID != %d AND post_parent = %d LIMIT 1";
                $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID, $post_parent ) );
 
+               /**
+                * Filter whether the post slug would make a bad hierarchical post slug.
+                *
+                * @since 3.1.0
+                *
+                * @param bool   $bad_slug    Whether the post slug would be bad in a hierarchical post context.
+                * @param string $slug        The post slug.
+                * @param string $post_type   Post type.
+                * @param int    $post_parent Post parent ID.
+                */
                if ( $post_name_check || in_array( $slug, $feeds ) || preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug )  || apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent ) ) {
                        $suffix = 2;
                        do {
@@ -3150,6 +3471,15 @@ function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_p
                $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
                $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
 
+               /**
+                * Filter whether the post slug would be bad as a flat slug.
+                *
+                * @since 3.1.0
+                *
+                * @param bool   $bad_slug  Whether the post slug would be bad as a flat slug.
+                * @param string $slug      The post slug.
+                * @param string $post_type Post type.
+                */
                if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
                        $suffix = 2;
                        do {
@@ -3161,6 +3491,18 @@ function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_p
                }
        }
 
+       /**
+        * Filter the unique post slug.
+        *
+        * @since 3.3.0
+        *
+        * @param string $slug          The post slug.
+        * @param int    $post_ID       Post ID.
+        * @param string $post_status   The post status.
+        * @param string $post_type     Post type.
+        * @param int    $post_parent   Post parent ID
+        * @param string $original_slug The original post slug.
+        */
        return apply_filters( 'wp_unique_post_slug', $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug );
 }
 
@@ -3192,8 +3534,6 @@ function _truncate_post_slug( $slug, $length = 200 ) {
  *
  * @uses wp_set_post_tags() Same first two parameters, but the last parameter is always set to true.
  *
- * @package WordPress
- * @subpackage Post
  * @since 2.3.0
  *
  * @param int $post_id Post ID
@@ -3304,21 +3644,49 @@ function wp_set_post_categories( $post_ID = 0, $post_categories = array(), $appe
  * parameter and POSTTYPE is post_type post data.
  *
  * @since 2.3.0
- * @link http://codex.wordpress.org/Post_Status_Transitions
  *
- * @uses do_action() Calls 'transition_post_status' on $new_status, $old_status and
- *  $post if there is a status change.
- * @uses do_action() Calls '{$old_status}_to_{$new_status}' on $post if there is a status change.
- * @uses do_action() Calls '{$new_status}_{$post->post_type}' on post ID and $post.
+ * @link http://codex.wordpress.org/Post_Status_Transitions
  *
  * @param string $new_status Transition to this post status.
  * @param string $old_status Previous post status.
  * @param object $post Post data.
  */
 function wp_transition_post_status($new_status, $old_status, $post) {
-       do_action('transition_post_status', $new_status, $old_status, $post);
-       do_action("{$old_status}_to_{$new_status}", $post);
-       do_action("{$new_status}_{$post->post_type}", $post->ID, $post);
+       /**
+        * Fires when a post is transitioned from one status to another.
+        *
+        * @since 2.3.0
+        *
+        * @param string  $new_status New post status.
+        * @param string  $old_status Old post status.
+        * @param WP_Post $post       Post object.
+        */
+       do_action( 'transition_post_status', $new_status, $old_status, $post );
+
+       /**
+        * Fires when a post is transitioned from one status to another.
+        *
+        * The dynamic portions of the hook name, $new_status and $old status,
+        * refer to the old and new post statuses, respectively.
+        *
+        * @since 2.3.0
+        *
+        * @param WP_Post $post Post object.
+        */
+       do_action( "{$old_status}_to_{$new_status}", $post );
+
+       /**
+        * Fires when a post is transitioned from one status to another.
+        *
+        * The dynamic portions of the hook name, $new_status and $post->post_type,
+        * refer to the new post status and post type, respectively.
+        *
+        * @since 2.3.0
+        *
+        * @param int     $post_id Post ID.
+        * @param WP_Post $post    Post object.
+        */
+       do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );
 }
 
 //
@@ -3342,7 +3710,16 @@ function add_ping($post_id, $uri) {
        $pung = preg_split('/\s/', $pung);
        $pung[] = $uri;
        $new = implode("\n", $pung);
-       $new = apply_filters('add_ping', $new);
+
+       /**
+        * Filter the new ping URL to add for the given post.
+        *
+        * @since 2.0.0
+        *
+        * @param string $new New ping URL to add.
+        */
+       $new = apply_filters( 'add_ping', $new );
+
        // expected_slashed ($new)
        $new = wp_unslash($new);
        return $wpdb->update( $wpdb->posts, array( 'pinged' => $new ), array( 'ID' => $post_id ) );
@@ -3370,7 +3747,16 @@ function get_enclosed($post_id) {
                        $pung[] = trim( $enclosure[ 0 ] );
                }
        }
-       $pung = apply_filters('get_enclosed', $pung, $post_id);
+
+       /**
+        * Filter the list of enclosures already enclosed for the given post.
+        *
+        * @since 2.0.0
+        *
+        * @param array $pung    Array of enclosures for the given post.
+        * @param int   $post_id Post ID.
+        */
+       $pung = apply_filters( 'get_enclosed', $pung, $post_id );
        return $pung;
 }
 
@@ -3388,7 +3774,15 @@ function get_pung($post_id) {
        $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);
+
+       /**
+        * Filter the list of already-pinged URLs for the given post.
+        *
+        * @since 2.0.0
+        *
+        * @param array $pung Array of URLs already pinged for the given post.
+        */
+       $pung = apply_filters( 'get_pung', $pung );
        return $pung;
 }
 
@@ -3406,7 +3800,15 @@ function get_to_ping($post_id) {
        $to_ping = $wpdb->get_var( $wpdb->prepare( "SELECT to_ping FROM $wpdb->posts WHERE ID = %d", $post_id ));
        $to_ping = sanitize_trackback_urls( $to_ping );
        $to_ping = preg_split('/\s/', $to_ping, -1, PREG_SPLIT_NO_EMPTY);
-       $to_ping = apply_filters('get_to_ping',  $to_ping);
+
+       /**
+        * Filter the list of URLs yet to ping for the given post.
+        *
+        * @since 2.0.0
+        *
+        * @param array $to_ping List of URLs yet to ping.
+        */
+       $to_ping = apply_filters( 'get_to_ping', $to_ping );
        return $to_ping;
 }
 
@@ -3490,10 +3892,10 @@ function get_page( $page, $output = OBJECT, $filter = 'raw') {
  *
  * @param string $page_path Page path
  * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
- * @param string $post_type Optional. Post type. Default page.
+ * @param string|array $post_type Optional. Post type or array of post types. Default page.
  * @return WP_Post|null WP_Post on success or null on failure
  */
-function get_page_by_path($page_path, $output = OBJECT, $post_type = 'page') {
+function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
        global $wpdb;
 
        $page_path = rawurlencode(urldecode($page_path));
@@ -3503,9 +3905,24 @@ function get_page_by_path($page_path, $output = OBJECT, $post_type = 'page') {
        $parts = esc_sql( $parts );
        $parts = array_map( 'sanitize_title_for_query', $parts );
 
-       $in_string = "'". implode( "','", $parts ) . "'";
-       $post_type_sql = esc_sql( $post_type );
-       $pages = $wpdb->get_results( "SELECT ID, post_name, post_parent, post_type FROM $wpdb->posts WHERE post_name IN ($in_string) AND (post_type = '$post_type_sql' OR post_type = 'attachment')", OBJECT_K );
+       $in_string = "'" . implode( "','", $parts ) . "'";
+
+       if ( is_array( $post_type ) ) {
+               $post_types = $post_type;
+       } else {
+               $post_types = array( $post_type, 'attachment' );
+       }
+
+       $post_types = esc_sql( $post_types );
+       $post_type_in_string = "'" . implode( "','", $post_types ) . "'";
+       $sql = "
+               SELECT ID, post_name, post_parent, post_type
+               FROM $wpdb->posts
+               WHERE post_name IN ($in_string)
+               AND post_type IN ($post_type_in_string)
+       ";
+
+       $pages = $wpdb->get_results( $sql, OBJECT_K );
 
        $revparts = array_reverse( $parts );
 
@@ -3544,12 +3961,32 @@ function get_page_by_path($page_path, $output = OBJECT, $post_type = 'page') {
  *
  * @param string $page_title Page title
  * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT.
- * @param string $post_type Optional. Post type. Default page.
+ * @param string|array $post_type Optional. Post type or array of post types. Default page.
  * @return WP_Post|null WP_Post on success or null on failure
  */
-function get_page_by_title($page_title, $output = OBJECT, $post_type = 'page' ) {
+function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
        global $wpdb;
-       $page = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type= %s", $page_title, $post_type ) );
+
+       if ( is_array( $post_type ) ) {
+               $post_type = esc_sql( $post_type );
+               $post_type_in_string = "'" . implode( "','", $post_type ) . "'";
+               $sql = $wpdb->prepare( "
+                       SELECT ID
+                       FROM $wpdb->posts
+                       WHERE post_title = %s
+                       AND post_type IN ($post_type_in_string)
+               ", $page_title );
+       } else {
+               $sql = $wpdb->prepare( "
+                       SELECT ID
+                       FROM $wpdb->posts
+                       WHERE post_title = %s
+                       AND post_type = %s
+               ", $page_title, $post_type );
+       }
+
+       $page = $wpdb->get_var( $sql );
+
        if ( $page )
                return get_post( $page, $output );
 
@@ -3698,7 +4135,7 @@ function get_pages( $args = array() ) {
                'sort_column' => 'post_title', 'hierarchical' => 1,
                'exclude' => array(), 'include' => array(),
                'meta_key' => '', 'meta_value' => '',
-               'authors' => '', 'parent' => -1, 'exclude_tree' => '',
+               'authors' => '', 'parent' => -1, 'exclude_tree' => array(),
                'number' => '', 'offset' => 0,
                'post_type' => 'page', 'post_status' => 'publish',
        );
@@ -3734,7 +4171,8 @@ function get_pages( $args = array() ) {
        if ( $cache = wp_cache_get( $cache_key, 'posts' ) ) {
                // Convert to WP_Post instances
                $pages = array_map( 'get_post', $cache );
-               $pages = apply_filters('get_pages', $pages, $r);
+               /** This filter is documented in wp-includes/post.php */
+               $pages = apply_filters( 'get_pages', $pages, $r );
                return $pages;
        }
 
@@ -3864,7 +4302,8 @@ function get_pages( $args = array() ) {
        $pages = $wpdb->get_results($query);
 
        if ( empty($pages) ) {
-               $pages = apply_filters('get_pages', array(), $r);
+               /** This filter is documented in wp-includes/post.php */
+               $pages = apply_filters( 'get_pages', array(), $r );
                return $pages;
        }
 
@@ -3880,17 +4319,20 @@ function get_pages( $args = array() ) {
        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);
+       if ( ! empty( $exclude_tree ) ) {
+               $exclude = wp_parse_id_list( $exclude_tree );
+               foreach( $exclude as $id ) {
+                       $children = get_page_children( $id, $pages );
+                       foreach ( $children as $child ) {
+                               $exclude[] = $child->ID;
+                       }
+               }
+
+               $num_pages = count( $pages );
                for ( $i = 0; $i < $num_pages; $i++ ) {
-                       if ( in_array($pages[$i]->ID, $excludes) )
-                               unset($pages[$i]);
+                       if ( in_array( $pages[$i]->ID, $exclude ) ) {
+                               unset( $pages[$i] );
+                       }
                }
        }
 
@@ -3903,7 +4345,15 @@ function get_pages( $args = array() ) {
        // Convert to WP_Post instances
        $pages = array_map( 'get_post', $pages );
 
-       $pages = apply_filters('get_pages', $pages, $r);
+       /**
+        * Filter the retrieved list of pages.
+        *
+        * @since 2.1.0
+        *
+        * @param array $pages List of pages to retrieve.
+        * @param array $r     Array of get_pages() arguments.
+        */
+       $pages = apply_filters( 'get_pages', $pages, $r );
 
        return $pages;
 }
@@ -3965,8 +4415,6 @@ function is_local_attachment($url) {
  *
  * @since 2.0.0
  * @uses $wpdb
- * @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.
@@ -4070,6 +4518,17 @@ function wp_insert_attachment($object, $file = false, $parent = 0) {
 
        // 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' ) );
+
+       /**
+        * Filter attachment post data before it is updated in or added
+        * to the database.
+        *
+        * @since 3.9.0
+        *
+        * @param array $data   Array of sanitized attachment post data.
+        * @param array $object Array of un-sanitized attachment post data.
+        */
+       $data = apply_filters( 'wp_insert_attachment_data', $data, $object );
        $data = wp_unslash( $data );
 
        if ( $update ) {
@@ -4118,9 +4577,24 @@ function wp_insert_attachment($object, $file = false, $parent = 0) {
                add_post_meta( $post_ID, '_wp_attachment_context', $context, true );
 
        if ( $update) {
-               do_action('edit_attachment', $post_ID);
+               /**
+                * Fires once an existing attachment has been updated.
+                *
+                * @since 2.0.0
+                *
+                * @param int $post_ID Attachment ID.
+                */
+               do_action( 'edit_attachment', $post_ID );
        } else {
-               do_action('add_attachment', $post_ID);
+
+               /**
+                * Fires once an attachment has been added.
+                *
+                * @since 2.0.0
+                *
+                * @param int $post_ID Attachment ID.
+                */
+               do_action( 'add_attachment', $post_ID );
        }
 
        return $post_ID;
@@ -4138,7 +4612,6 @@ function wp_insert_attachment($object, $file = false, $parent = 0) {
  *
  * @since 2.0.0
  * @uses $wpdb
- * @uses do_action() Calls 'delete_attachment' hook on Attachment ID.
  *
  * @param int $post_id Attachment ID.
  * @param bool $force_delete Whether to bypass trash and force deletion. Defaults to false.
@@ -4172,7 +4645,14 @@ function wp_delete_attachment( $post_id, $force_delete = false ) {
        if ( is_multisite() )
                delete_transient( 'dirsize_cache' );
 
-       do_action('delete_attachment', $post_id);
+       /**
+        * Fires before an attachment is deleted, at the start of wp_delete_attachment().
+        *
+        * @since 2.0.0
+        *
+        * @param int $post_id Attachment 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));
@@ -4187,11 +4667,13 @@ function wp_delete_attachment( $post_id, $force_delete = false ) {
        foreach ( $post_meta_ids as $mid )
                delete_metadata_by_mid( 'post', $mid );
 
+       /** This action is documented in wp-includes/post.php */
        do_action( 'delete_post', $post_id );
        $result = $wpdb->delete( $wpdb->posts, array( 'ID' => $post_id ) );
        if ( ! $result ) {
                return false;
        }
+       /** This action is documented in wp-includes/post.php */
        do_action( 'deleted_post', $post_id );
 
        $uploadpath = wp_upload_dir();
@@ -4201,7 +4683,7 @@ function wp_delete_attachment( $post_id, $force_delete = false ) {
                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);
                        /** This filter is documented in wp-admin/custom-header.php */
-                       $thumbfile = apply_filters('wp_delete_file', $thumbfile);
+                       $thumbfile = apply_filters( 'wp_delete_file', $thumbfile );
                        @ unlink( path_join($uploadpath['basedir'], $thumbfile) );
                }
        }
@@ -4217,13 +4699,13 @@ function wp_delete_attachment( $post_id, $force_delete = false ) {
                foreach ( $backup_sizes as $size ) {
                        $del_file = path_join( dirname($meta['file']), $size['file'] );
                        /** This filter is documented in wp-admin/custom-header.php */
-                       $del_file = apply_filters('wp_delete_file', $del_file);
+                       $del_file = apply_filters( 'wp_delete_file', $del_file );
                        @ unlink( path_join($uploadpath['basedir'], $del_file) );
                }
        }
 
        /** This filter is documented in wp-admin/custom-header.php */
-       $file = apply_filters('wp_delete_file', $file);
+       $file = apply_filters( 'wp_delete_file', $file );
 
        if ( ! empty($file) )
                @ unlink($file);
@@ -4252,6 +4734,15 @@ function wp_get_attachment_metadata( $post_id = 0, $unfiltered = false ) {
        if ( $unfiltered )
                return $data;
 
+       /**
+        * Filter the attachment meta data.
+        *
+        * @since 2.1.0
+        *
+        * @param array|bool $data    Array of meta data for the given attachment, or false
+        *                            if the object does not exist.
+        * @param int        $post_id Attachment ID.
+        */
        return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
 }
 
@@ -4269,6 +4760,14 @@ function wp_update_attachment_metadata( $post_id, $data ) {
        if ( !$post = get_post( $post_id ) )
                return false;
 
+       /**
+        * Filter the updated attachment meta data.
+        *
+        * @since 2.1.0
+        *
+        * @param array $data    Array of updated attachment meta data.
+        * @param int   $post_id Attachment ID.
+        */
        if ( $data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID ) )
                return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
        else
@@ -4306,6 +4805,14 @@ function wp_get_attachment_url( $post_id = 0 ) {
        if ( empty($url) ) //If any of the above options failed, Fallback on the GUID as used pre-2.7, not recommended to rely upon this.
                $url = get_the_guid( $post->ID );
 
+       /**
+        * Filter the attachment URL.
+        *
+        * @since 2.1.0
+        *
+        * @param string $url     URL for the given attachment.
+        * @param int    $post_id Attachment ID.
+        */
        $url = apply_filters( 'wp_get_attachment_url', $url, $post->ID );
 
        if ( empty( $url ) )
@@ -4331,8 +4838,17 @@ function wp_get_attachment_thumb_file( $post_id = 0 ) {
 
        $file = get_attached_file( $post->ID );
 
-       if ( !empty($imagedata['thumb']) && ($thumbfile = str_replace(basename($file), $imagedata['thumb'], $file)) && file_exists($thumbfile) )
+       if ( !empty($imagedata['thumb']) && ($thumbfile = str_replace(basename($file), $imagedata['thumb'], $file)) && file_exists($thumbfile) ) {
+               /**
+                * Filter the attachment thumbnail file path.
+                *
+                * @since 2.1.0
+                *
+                * @param string $thumbfile File path to the attachment thumbnail.
+                * @param int    $post_id   Attachment ID.
+                */
                return apply_filters( 'wp_get_attachment_thumb_file', $thumbfile, $post->ID );
+       }
        return false;
 }
 
@@ -4360,6 +4876,14 @@ function wp_get_attachment_thumb_url( $post_id = 0 ) {
 
        $url = str_replace(basename($url), basename($thumb), $url);
 
+       /**
+        * Filter the attachment thumbnail URL.
+        *
+        * @since 2.1.0
+        *
+        * @param string $url     URL for the attachment thumbnail.
+        * @param int    $post_id Attachment ID.
+        */
        return apply_filters( 'wp_get_attachment_thumb_url', $url, $post->ID );
 }
 
@@ -4424,9 +4948,32 @@ function wp_mime_type_icon( $mime = 0 ) {
                $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) );
+                       /**
+                        * Filter the icon directory path.
+                        *
+                        * @since 2.0.0
+                        *
+                        * @param string $path Icon directory absolute path.
+                        */
+                       $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
+
+                       /**
+                        * Filter the icon directory URI.
+                        *
+                        * @since 2.0.0
+                        *
+                        * @param string $uri Icon directory URI.
+                        */
+                       $icon_dir_uri = apply_filters( 'icon_dir_uri', includes_url( 'images/media' ) );
+
+                       /**
+                        * Filter the list of icon directory URIs.
+                        *
+                        * @since 2.5.0
+                        *
+                        * @param array $uris List of icon directory URIs.
+                        */
+                       $dirs = apply_filters( 'icon_dirs', array( $icon_dir => $icon_dir_uri ) );
                        $icon_files = array();
                        while ( $dirs ) {
                                $keys = array_keys( $dirs );
@@ -4473,7 +5020,17 @@ function wp_mime_type_icon( $mime = 0 ) {
                }
        }
 
-       return apply_filters( 'wp_mime_type_icon', $icon, $mime, $post_id ); // Last arg is 0 if function pass mime type.
+       /**
+        * Filter the mime type icon.
+        *
+        * @since 2.1.0
+        *
+        * @param string $icon    Path to the mime type icon.
+        * @param string $mime    Mime type.
+        * @param int    $post_id Attachment ID. Will equal 0 if the function passed
+        *                        the mime type.
+        */
+       return apply_filters( 'wp_mime_type_icon', $icon, $mime, $post_id );
 }
 
 /**
@@ -4553,9 +5110,18 @@ function get_posts_by_author_sql( $post_type, $full = true, $post_author = null,
        if ( ! $post_type_obj )
                return $full ? 'WHERE 1 = 0' : ' 1 = 0 ';
 
-       // This hook is deprecated. Why you'd want to use it, I dunno.
-       if ( ! $cap = apply_filters( 'pub_priv_sql_capability', '' ) )
+       /**
+        * Filter the capability to read private posts for a custom post type
+        * when generating SQL for getting posts by author.
+        *
+        * @since 2.2.0
+        * @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
+        *
+        * @param string $cap Capability.
+        */
+       if ( ! $cap = apply_filters( 'pub_priv_sql_capability', '' ) ) {
                $cap = $post_type_obj->cap->read_private_posts;
+       }
 
        if ( $full ) {
                if ( null === $post_author ) {
@@ -4599,12 +5165,19 @@ function get_posts_by_author_sql( $post_type, $full = true, $post_author = null,
  *
  * @since 0.71
  *
- * @uses apply_filters() Calls 'get_lastpostdate' filter
- *
  * @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') {
+       /**
+        * Filter the date the last post was published.
+        *
+        * @since 2.3.0
+        *
+        * @param string $date     Date the last post was published. Likely values are 'gmt',
+        *                         'blog', or 'server'.
+        * @param string $timezone Location to use for getting the post published date.
+        */
        return apply_filters( 'get_lastpostdate', _get_last_post_time( $timezone, 'date' ), $timezone );
 }
 
@@ -4616,7 +5189,6 @@ function get_lastpostdate($timezone = 'server') {
  * 'gmt' is when the last post was modified in GMT time.
  *
  * @since 1.2.0
- * @uses apply_filters() Calls 'get_lastpostmodified' filter
  *
  * @param string $timezone The location to get the time. Can be 'gmt', 'blog', or 'server'.
  * @return string The date the post was last modified.
@@ -4628,6 +5200,14 @@ function get_lastpostmodified($timezone = 'server') {
        if ( $lastpostdate > $lastpostmodified )
                $lastpostmodified = $lastpostdate;
 
+       /**
+        * Filter the date the last post was modified.
+        *
+        * @since 2.3.0
+        *
+        * @param string $lastpostmodified Date the last post was modified.
+        * @param string $timezone         Location to use for getting the post modified date.
+        */
        return apply_filters( 'get_lastpostmodified', $lastpostmodified, $timezone );
 }
 
@@ -4682,8 +5262,6 @@ function _get_last_post_time( $timezone, $field ) {
 /**
  * Updates posts in cache.
  *
- * @package WordPress
- * @subpackage Cache
  * @since 1.5.1
  *
  * @param array $posts Array of post objects
@@ -4705,13 +5283,9 @@ function update_post_cache( &$posts ) {
  * 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|object $post Post ID or object to remove from the cache
+ * @param int|WP_Post $post Post ID or post object to remove from the cache.
  */
 function clean_post_cache( $post ) {
        global $_wp_suspend_cache_invalidation, $wpdb;
@@ -4730,6 +5304,14 @@ function clean_post_cache( $post ) {
 
        wp_cache_delete( 'wp_get_archives', 'general' );
 
+       /**
+        * Fires immediately after the given post's cache is cleaned.
+        *
+        * @since 2.5.0
+        *
+        * @param int     $post_id Post ID.
+        * @param WP_Post $post    Post object.
+        */
        do_action( 'clean_post_cache', $post->ID, $post );
 
        if ( is_post_type_hierarchical( $post->post_type ) )
@@ -4737,6 +5319,14 @@ function clean_post_cache( $post ) {
 
        if ( 'page' == $post->post_type ) {
                wp_cache_delete( 'all_page_ids', 'posts' );
+
+               /**
+                * Fires immediately after the given page's cache is cleaned.
+                *
+                * @since 2.5.0
+                *
+                * @param int $post_id Post ID.
+                */
                do_action( 'clean_page_cache', $post->ID );
        }
 
@@ -4746,8 +5336,6 @@ function clean_post_cache( $post ) {
 /**
  * Call major cache updating functions for list of Post objects.
  *
- * @package WordPress
- * @subpackage Cache
  * @since 1.5.0
  *
  * @uses update_post_cache()
@@ -4800,8 +5388,6 @@ function update_post_caches(&$posts, $post_type = 'post', $update_term_cache = t
  * 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
  *
  * @param array $post_ids List of post IDs.
@@ -4820,12 +5406,8 @@ function update_postmeta_cache($post_ids) {
  * This function will not run if $_wp_suspend_cache_invalidation is not empty. See
  * wp_suspend_cache_invalidation().
  *
- * @package WordPress
- * @subpackage Cache
  * @since 3.0.0
  *
- * @uses do_action() Calls 'clean_attachment_cache' on $id.
- *
  * @param int $id The attachment ID in the cache to clean
  * @param bool $clean_terms optional. Whether to clean terms cache
  */
@@ -4843,7 +5425,14 @@ function clean_attachment_cache($id, $clean_terms = false) {
        if ( $clean_terms )
                clean_object_term_cache($id, 'attachment');
 
-       do_action('clean_attachment_cache', $id);
+       /**
+        * Fires after the given attachment's cache is cleaned.
+        *
+        * @since 3.0.0
+        *
+        * @param int $id Attachment ID.
+        */
+       do_action( 'clean_attachment_cache', $id );
 }
 
 //
@@ -4856,7 +5445,6 @@ function clean_attachment_cache($id, $clean_terms = false) {
  * @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
@@ -4870,7 +5458,16 @@ function _transition_post_status($new_status, $old_status, $post) {
                // 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
+
+               /**
+                * Fires when a post's status is transitioned from private to published.
+                *
+                * @since 1.5.0
+                * @deprecated 2.3.0 Use 'private_to_publish' instead.
+                *
+                * @param int $post_id Post ID.
+                */
+               do_action('private_to_published', $post->ID);
        }
 
        // If published posts changed clear the lastpostmodified cache
@@ -4881,6 +5478,11 @@ function _transition_post_status($new_status, $old_status, $post) {
                }
        }
 
+       if ( $new_status !== $old_status ) {
+               wp_cache_delete( _count_posts_cache_key( $post->post_type ), 'counts' );
+               wp_cache_delete( _count_posts_cache_key( $post->post_type, 'readable' ), 'counts' );
+       }
+
        // Always clears the hook in case the post status bounced from future to draft.
        wp_clear_scheduled_hook('publish_future_post', array( $post->ID ) );
 }
@@ -4909,13 +5511,20 @@ function _future_post_hook( $deprecated, $post ) {
  * @since 2.3.0
  * @access private
  * @uses XMLRPC_REQUEST and WP_IMPORTING constants.
- * @uses do_action() Calls 'xmlrpc_publish_post' on post ID if XMLRPC_REQUEST is defined.
  *
  * @param int $post_id The ID in the database table of the post being published
  */
 function _publish_post_hook($post_id) {
-       if ( defined('XMLRPC_REQUEST') )
-               do_action('xmlrpc_publish_post', $post_id);
+       if ( defined( 'XMLRPC_REQUEST' ) ) {
+               /**
+                * Fires when _publish_post_hook() is called during an XML-RPC request.
+                *
+                * @since 2.1.0
+                *
+                * @param int $post_id Post ID.
+                */
+               do_action( 'xmlrpc_publish_post', $post_id );
+       }
 
        if ( defined('WP_IMPORTING') )
                return;
@@ -4991,7 +5600,7 @@ function wp_check_post_hierarchy_for_loops( $post_parent, $post_ID ) {
  *
  * @since 3.1.0
  *
- * @param int|object $post Post ID or object where thumbnail should be attached.
+ * @param int|WP_Post $post Post ID or post object where thumbnail should be attached.
  * @param int $thumbnail_id Thumbnail to attach.
  * @return bool True on success, false on failure.
  */
@@ -5012,7 +5621,7 @@ function set_post_thumbnail( $post, $thumbnail_id ) {
  *
  * @since 3.3.0
  *
- * @param int|object $post Post ID or object where thumbnail should be removed from.
+ * @param int|WP_Post $post Post ID or post object where thumbnail should be removed from.
  * @return bool True on success, false on failure.
  */
 function delete_post_thumbnail( $post ) {