+
+ /**
+ * Is the query for an embedded post?
+ *
+ * @since 4.4.0
+ *
+ * @return bool
+ */
+ public function is_embed() {
+ return (bool) $this->is_embed;
+ }
+
+ /**
+ * Is the query the main query?
+ *
+ * @since 3.3.0
+ *
+ * @global WP_Query $wp_query Global WP_Query instance.
+ *
+ * @return bool
+ */
+ public function is_main_query() {
+ global $wp_the_query;
+ return $wp_the_query === $this;
+ }
+
+ /**
+ * Set up global post data.
+ *
+ * @since 4.1.0
+ * @since 4.4.0 Added the ability to pass a post ID to `$post`.
+ *
+ * @global int $id
+ * @global WP_User $authordata
+ * @global string|int|bool $currentday
+ * @global string|int|bool $currentmonth
+ * @global int $page
+ * @global array $pages
+ * @global int $multipage
+ * @global int $more
+ * @global int $numpages
+ *
+ * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
+ * @return true True when finished.
+ */
+ public function setup_postdata( $post ) {
+ global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
+
+ if ( ! ( $post instanceof WP_Post ) ) {
+ $post = get_post( $post );
+ }
+
+ if ( ! $post ) {
+ return;
+ }
+
+ $id = (int) $post->ID;
+
+ $authordata = get_userdata($post->post_author);
+
+ $currentday = mysql2date('d.m.y', $post->post_date, false);
+ $currentmonth = mysql2date('m', $post->post_date, false);
+ $numpages = 1;
+ $multipage = 0;
+ $page = $this->get( 'page' );
+ if ( ! $page )
+ $page = 1;
+
+ /*
+ * Force full post content when viewing the permalink for the $post,
+ * or when on an RSS feed. Otherwise respect the 'more' tag.
+ */
+ if ( $post->ID === get_queried_object_id() && ( $this->is_page() || $this->is_single() ) ) {
+ $more = 1;
+ } elseif ( $this->is_feed() ) {
+ $more = 1;
+ } else {
+ $more = 0;
+ }
+
+ $content = $post->post_content;
+ if ( false !== strpos( $content, '<!--nextpage-->' ) ) {
+ $content = str_replace( "\n<!--nextpage-->\n", '<!--nextpage-->', $content );
+ $content = str_replace( "\n<!--nextpage-->", '<!--nextpage-->', $content );
+ $content = str_replace( "<!--nextpage-->\n", '<!--nextpage-->', $content );
+
+ // Ignore nextpage at the beginning of the content.
+ if ( 0 === strpos( $content, '<!--nextpage-->' ) )
+ $content = substr( $content, 15 );
+
+ $pages = explode('<!--nextpage-->', $content);
+ } else {
+ $pages = array( $post->post_content );
+ }
+
+ /**
+ * Filter the "pages" derived from splitting the post content.
+ *
+ * "Pages" are determined by splitting the post content based on the presence
+ * of `<!-- nextpage -->` tags.
+ *
+ * @since 4.4.0
+ *
+ * @param array $pages Array of "pages" derived from the post content.
+ * of `<!-- nextpage -->` tags..
+ * @param WP_Post $post Current post object.
+ */
+ $pages = apply_filters( 'content_pagination', $pages, $post );
+
+ $numpages = count( $pages );
+
+ if ( $numpages > 1 ) {
+ if ( $page > 1 ) {
+ $more = 1;
+ }
+ $multipage = 1;
+ } else {
+ $multipage = 0;
+ }
+
+ /**
+ * Fires once the post data has been setup.
+ *
+ * @since 2.8.0
+ * @since 4.1.0 Introduced `$this` parameter.
+ *
+ * @param WP_Post &$post The Post object (passed by reference).
+ * @param WP_Query &$this The current Query object (passed by reference).
+ */
+ do_action_ref_array( 'the_post', array( &$post, &$this ) );
+
+ return true;
+ }
+ /**
+ * After looping through a nested query, this function
+ * restores the $post global to the current post in this query.
+ *
+ * @since 3.7.0
+ *
+ * @global WP_Post $post
+ */
+ public function reset_postdata() {
+ if ( ! empty( $this->post ) ) {
+ $GLOBALS['post'] = $this->post;
+ $this->setup_postdata( $this->post );
+ }
+ }
+
+ /**
+ * Lazy-loads termmeta for located posts.
+ *
+ * As a rule, term queries (`get_terms()` and `wp_get_object_terms()`) prime the metadata cache for matched
+ * terms by default. However, this can cause a slight performance penalty, especially when that metadata is
+ * not actually used. In the context of a `WP_Query` instance, we're able to avoid this potential penalty.
+ * `update_object_term_cache()`, called from `update_post_caches()`, does not 'update_term_meta_cache'.
+ * Instead, the first time `get_term_meta()` is called from within a `WP_Query` loop, the current method
+ * detects the fact, and then primes the metadata cache for all terms attached to all posts in the loop,
+ * with a single database query.
+ *
+ * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it
+ * directly, from either inside or outside the `WP_Query` object.
+ *
+ * @since 4.4.0
+ * @access public
+ *
+ * @param mixed $check The `$check` param passed from the 'get_term_metadata' hook.
+ * @param int $term_id ID of the term whose metadata is being cached.
+ * @return mixed In order not to short-circuit `get_metadata()`. Generally, this is `null`, but it could be
+ * another value if filtered by a plugin.
+ */
+ public function lazyload_term_meta( $check, $term_id ) {
+ /*
+ * We only do this once per `WP_Query` instance.
+ * Can't use `remove_filter()` because of non-unique object hashes.
+ */
+ if ( $this->updated_term_meta_cache ) {
+ return $check;
+ }
+
+ // We can only lazyload if the entire post object is present.
+ $posts = array();
+ foreach ( $this->posts as $post ) {
+ if ( $post instanceof WP_Post ) {
+ $posts[] = $post;
+ }
+ }
+
+ if ( ! empty( $posts ) ) {
+ // Fetch cached term_ids for each post. Keyed by term_id for faster lookup.
+ $term_ids = array();
+ foreach ( $posts as $post ) {
+ $taxonomies = get_object_taxonomies( $post->post_type );
+ foreach ( $taxonomies as $taxonomy ) {
+ // Term cache should already be primed by 'update_post_term_cache'.
+ $terms = get_object_term_cache( $post->ID, $taxonomy );
+ if ( false !== $terms ) {
+ foreach ( $terms as $term ) {
+ if ( ! isset( $term_ids[ $term->term_id ] ) ) {
+ $term_ids[ $term->term_id ] = 1;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Only update the metadata cache for terms belonging to these posts if the term_id passed
+ * to `get_term_meta()` matches one of those terms. This prevents a single call to
+ * `get_term_meta()` from priming metadata for all `WP_Query` objects.
+ */
+ if ( isset( $term_ids[ $term_id ] ) ) {
+ update_termmeta_cache( array_keys( $term_ids ) );
+ $this->updated_term_meta_cache = true;
+ }
+ }
+
+ // If no terms were found, there's no need to run this again.
+ if ( empty( $term_ids ) ) {
+ $this->updated_term_meta_cache = true;
+ }
+
+ return $check;
+ }
+
+ /**
+ * Lazy-load comment meta when inside of a `WP_Query` loop.
+ *
+ * This method is public so that it can be used as a filter callback. As a rule, there is no need to invoke it
+ * directly, from either inside or outside the `WP_Query` object.
+ *
+ * @since 4.4.0
+ *
+ * @param mixed $check The `$check` param passed from the 'get_comment_metadata' hook.
+ * @param int $comment_id ID of the comment whose metadata is being cached.
+ * @return mixed The original value of `$check`, to not affect 'get_comment_metadata'.
+ */
+ public function lazyload_comment_meta( $check, $comment_id ) {
+ /*
+ * We only do this once per `WP_Query` instance.
+ * Can't use `remove_filter()` because of non-unique object hashes.
+ */
+ if ( $this->updated_comment_meta_cache ) {
+ return $check;
+ }
+
+ // Don't use `wp_list_pluck()` to avoid by-reference manipulation.
+ $comment_ids = array();
+ if ( is_array( $this->comments ) ) {
+ foreach ( $this->comments as $comment ) {
+ $comment_ids[] = $comment->comment_ID;
+ }
+ }
+
+ /*
+ * Only update the metadata cache for comments belonging to these posts if the comment_id passed
+ * to `get_comment_meta()` matches one of those comments. This prevents a single call to
+ * `get_comment_meta()` from priming metadata for all `WP_Query` objects.
+ */
+ if ( in_array( $comment_id, $comment_ids ) ) {
+ update_meta_cache( 'comment', $comment_ids );
+ $this->updated_comment_meta_cache = true;
+ } elseif ( empty( $comment_ids ) ) {
+ $this->updated_comment_meta_cache = true;
+ }
+
+ return $check;
+ }