+
+ /**
+ * Make private properties readable for backwards compatibility.
+ *
+ * @since 4.0.0
+ * @access public
+ *
+ * @param string $name Property to get.
+ * @return mixed Property.
+ */
+ public function __get( $name ) {
+ if ( in_array( $name, $this->compat_fields ) ) {
+ return $this->$name;
+ }
+ }
+
+ /**
+ * Make private properties checkable for backwards compatibility.
+ *
+ * @since 4.0.0
+ * @access public
+ *
+ * @param string $name Property to check if set.
+ * @return bool Whether the property is set.
+ */
+ public function __isset( $name ) {
+ if ( in_array( $name, $this->compat_fields ) ) {
+ return isset( $this->$name );
+ }
+ }
+
+ /**
+ * Make private/protected methods readable for backwards compatibility.
+ *
+ * @since 4.0.0
+ * @access public
+ *
+ * @param callable $name Method to call.
+ * @param array $arguments Arguments to pass when calling.
+ * @return mixed|false Return value of the callback, false otherwise.
+ */
+ public function __call( $name, $arguments ) {
+ if ( in_array( $name, $this->compat_methods ) ) {
+ return call_user_func_array( array( $this, $name ), $arguments );
+ }
+ return false;
+ }
+
+ /**
+ * Is the query for an existing archive page?
+ *
+ * Month, Year, Category, Author, Post Type archive...
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_archive() {
+ return (bool) $this->is_archive;
+ }
+
+ /**
+ * Is the query for an existing post type archive page?
+ *
+ * @since 3.1.0
+ *
+ * @param mixed $post_types Optional. Post type or array of posts types to check against.
+ * @return bool
+ */
+ public function is_post_type_archive( $post_types = '' ) {
+ if ( empty( $post_types ) || ! $this->is_post_type_archive )
+ return (bool) $this->is_post_type_archive;
+
+ $post_type = $this->get( 'post_type' );
+ if ( is_array( $post_type ) )
+ $post_type = reset( $post_type );
+ $post_type_object = get_post_type_object( $post_type );
+
+ return in_array( $post_type_object->name, (array) $post_types );
+ }
+
+ /**
+ * Is the query for an existing attachment page?
+ *
+ * @since 3.1.0
+ *
+ * @param mixed $attachment Attachment ID, title, slug, or array of such.
+ * @return bool
+ */
+ public function is_attachment( $attachment = '' ) {
+ if ( ! $this->is_attachment ) {
+ return false;
+ }
+
+ if ( empty( $attachment ) ) {
+ return true;
+ }
+
+ $attachment = (array) $attachment;
+
+ $post_obj = $this->get_queried_object();
+
+ if ( in_array( (string) $post_obj->ID, $attachment ) ) {
+ return true;
+ } elseif ( in_array( $post_obj->post_title, $attachment ) ) {
+ return true;
+ } elseif ( in_array( $post_obj->post_name, $attachment ) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Is the query for an existing author archive page?
+ *
+ * If the $author parameter is specified, this function will additionally
+ * check if the query is for one of the authors specified.
+ *
+ * @since 3.1.0
+ *
+ * @param mixed $author Optional. User ID, nickname, nicename, or array of User IDs, nicknames, and nicenames
+ * @return bool
+ */
+ public function is_author( $author = '' ) {
+ if ( !$this->is_author )
+ return false;
+
+ if ( empty($author) )
+ return true;
+
+ $author_obj = $this->get_queried_object();
+
+ $author = (array) $author;
+
+ if ( in_array( (string) $author_obj->ID, $author ) )
+ return true;
+ elseif ( in_array( $author_obj->nickname, $author ) )
+ return true;
+ elseif ( in_array( $author_obj->user_nicename, $author ) )
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Is the query for an existing category archive page?
+ *
+ * If the $category parameter is specified, this function will additionally
+ * check if the query is for one of the categories specified.
+ *
+ * @since 3.1.0
+ *
+ * @param mixed $category Optional. Category ID, name, slug, or array of Category IDs, names, and slugs.
+ * @return bool
+ */
+ public function is_category( $category = '' ) {
+ if ( !$this->is_category )
+ return false;
+
+ if ( empty($category) )
+ return true;
+
+ $cat_obj = $this->get_queried_object();
+
+ $category = (array) $category;
+
+ if ( in_array( (string) $cat_obj->term_id, $category ) )
+ return true;
+ elseif ( in_array( $cat_obj->name, $category ) )
+ return true;
+ elseif ( in_array( $cat_obj->slug, $category ) )
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Is the query for an existing tag archive page?
+ *
+ * If the $tag parameter is specified, this function will additionally
+ * check if the query is for one of the tags specified.
+ *
+ * @since 3.1.0
+ *
+ * @param mixed $tag Optional. Tag ID, name, slug, or array of Tag IDs, names, and slugs.
+ * @return bool
+ */
+ public function is_tag( $tag = '' ) {
+ if ( ! $this->is_tag )
+ return false;
+
+ if ( empty( $tag ) )
+ return true;
+
+ $tag_obj = $this->get_queried_object();
+
+ $tag = (array) $tag;
+
+ if ( in_array( (string) $tag_obj->term_id, $tag ) )
+ return true;
+ elseif ( in_array( $tag_obj->name, $tag ) )
+ return true;
+ elseif ( in_array( $tag_obj->slug, $tag ) )
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Is the query for an existing taxonomy archive page?
+ *
+ * If the $taxonomy parameter is specified, this function will additionally
+ * check if the query is for that specific $taxonomy.
+ *
+ * If the $term parameter is specified in addition to the $taxonomy parameter,
+ * this function will additionally check if the query is for one of the terms
+ * specified.
+ *
+ * @since 3.1.0
+ *
+ * @global array $wp_taxonomies
+ *
+ * @param mixed $taxonomy Optional. Taxonomy slug or slugs.
+ * @param mixed $term Optional. Term ID, name, slug or array of Term IDs, names, and slugs.
+ * @return bool
+ */
+ public function is_tax( $taxonomy = '', $term = '' ) {
+ global $wp_taxonomies;
+
+ if ( !$this->is_tax )
+ return false;
+
+ if ( empty( $taxonomy ) )
+ return true;
+
+ $queried_object = $this->get_queried_object();
+ $tax_array = array_intersect( array_keys( $wp_taxonomies ), (array) $taxonomy );
+ $term_array = (array) $term;
+
+ // Check that the taxonomy matches.
+ if ( ! ( isset( $queried_object->taxonomy ) && count( $tax_array ) && in_array( $queried_object->taxonomy, $tax_array ) ) )
+ return false;
+
+ // Only a Taxonomy provided.
+ if ( empty( $term ) )
+ return true;
+
+ return isset( $queried_object->term_id ) &&
+ count( array_intersect(
+ array( $queried_object->term_id, $queried_object->name, $queried_object->slug ),
+ $term_array
+ ) );
+ }
+
+ /**
+ * Whether the current URL is within the comments popup window.
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_comments_popup() {
+ return (bool) $this->is_comments_popup;
+ }
+
+ /**
+ * Is the query for an existing date archive?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_date() {
+ return (bool) $this->is_date;
+ }
+
+ /**
+ * Is the query for an existing day archive?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_day() {
+ return (bool) $this->is_day;
+ }
+
+ /**
+ * Is the query for a feed?
+ *
+ * @since 3.1.0
+ *
+ * @param string|array $feeds Optional feed types to check.
+ * @return bool
+ */
+ public function is_feed( $feeds = '' ) {
+ if ( empty( $feeds ) || ! $this->is_feed )
+ return (bool) $this->is_feed;
+ $qv = $this->get( 'feed' );
+ if ( 'feed' == $qv )
+ $qv = get_default_feed();
+ return in_array( $qv, (array) $feeds );
+ }
+
+ /**
+ * Is the query for a comments feed?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_comment_feed() {
+ return (bool) $this->is_comment_feed;
+ }
+
+ /**
+ * Is the query for the front page of the site?
+ *
+ * This is for what is displayed at your site's main URL.
+ *
+ * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_on_front'.
+ *
+ * If you set a static page for the front page of your site, this function will return
+ * true when viewing that page.
+ *
+ * Otherwise the same as @see WP_Query::is_home()
+ *
+ * @since 3.1.0
+ *
+ * @return bool True, if front of site.
+ */
+ public function is_front_page() {
+ // most likely case
+ if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
+ return true;
+ elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Is the query for the blog homepage?
+ *
+ * This is the page which shows the time based blog content of your site.
+ *
+ * Depends on the site's "Front page displays" Reading Settings 'show_on_front' and 'page_for_posts'.
+ *
+ * If you set a static page for the front page of your site, this function will return
+ * true only on the page you set as the "Posts page".
+ *
+ * @see WP_Query::is_front_page()
+ *
+ * @since 3.1.0
+ *
+ * @return bool True if blog view homepage.
+ */
+ public function is_home() {
+ return (bool) $this->is_home;
+ }
+
+ /**
+ * Is the query for an existing month archive?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_month() {
+ return (bool) $this->is_month;
+ }
+
+ /**
+ * Is the query for an existing single page?
+ *
+ * If the $page parameter is specified, this function will additionally
+ * check if the query is for one of the pages specified.
+ *
+ * @see WP_Query::is_single()
+ * @see WP_Query::is_singular()
+ *
+ * @since 3.1.0
+ *
+ * @param int|string|array $page Optional. Page ID, title, slug, path, or array of such. Default empty.
+ * @return bool Whether the query is for an existing single page.
+ */
+ public function is_page( $page = '' ) {
+ if ( !$this->is_page )
+ return false;
+
+ if ( empty( $page ) )
+ return true;
+
+ $page_obj = $this->get_queried_object();
+
+ $page = (array) $page;
+
+ if ( in_array( (string) $page_obj->ID, $page ) ) {
+ return true;
+ } elseif ( in_array( $page_obj->post_title, $page ) ) {
+ return true;
+ } elseif ( in_array( $page_obj->post_name, $page ) ) {
+ return true;
+ } else {
+ foreach ( $page as $pagepath ) {
+ if ( ! strpos( $pagepath, '/' ) ) {
+ continue;
+ }
+ $pagepath_obj = get_page_by_path( $pagepath );
+
+ if ( $pagepath_obj && ( $pagepath_obj->ID == $page_obj->ID ) ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Is the query for paged result and not for the first page?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_paged() {
+ return (bool) $this->is_paged;
+ }
+
+ /**
+ * Is the query for a post or page preview?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_preview() {
+ return (bool) $this->is_preview;
+ }
+
+ /**
+ * Is the query for the robots file?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_robots() {
+ return (bool) $this->is_robots;
+ }
+
+ /**
+ * Is the query for a search?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_search() {
+ return (bool) $this->is_search;
+ }
+
+ /**
+ * Is the query for an existing single post?
+ *
+ * Works for any post type, except attachments and pages
+ *
+ * If the $post parameter is specified, this function will additionally
+ * check if the query is for one of the Posts specified.
+ *
+ * @see WP_Query::is_page()
+ * @see WP_Query::is_singular()
+ *
+ * @since 3.1.0
+ *
+ * @param int|string|array $post Optional. Post ID, title, slug, path, or array of such. Default empty.
+ * @return bool Whether the query is for an existing single post.
+ */
+ public function is_single( $post = '' ) {
+ if ( !$this->is_single )
+ return false;
+
+ if ( empty($post) )
+ return true;
+
+ $post_obj = $this->get_queried_object();
+
+ $post = (array) $post;
+
+ if ( in_array( (string) $post_obj->ID, $post ) ) {
+ return true;
+ } elseif ( in_array( $post_obj->post_title, $post ) ) {
+ return true;
+ } elseif ( in_array( $post_obj->post_name, $post ) ) {
+ return true;
+ } else {
+ foreach ( $post as $postpath ) {
+ if ( ! strpos( $postpath, '/' ) ) {
+ continue;
+ }
+ $postpath_obj = get_page_by_path( $postpath, OBJECT, $post_obj->post_type );
+
+ if ( $postpath_obj && ( $postpath_obj->ID == $post_obj->ID ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Is the query for an existing single post of any post type (post, attachment, page, ... )?
+ *
+ * If the $post_types parameter is specified, this function will additionally
+ * check if the query is for one of the Posts Types specified.
+ *
+ * @see WP_Query::is_page()
+ * @see WP_Query::is_single()
+ *
+ * @since 3.1.0
+ *
+ * @param string|array $post_types Optional. Post type or array of post types. Default empty.
+ * @return bool Whether the query is for an existing single post of any of the given post types.
+ */
+ public function is_singular( $post_types = '' ) {
+ if ( empty( $post_types ) || !$this->is_singular )
+ return (bool) $this->is_singular;
+
+ $post_obj = $this->get_queried_object();
+
+ return in_array( $post_obj->post_type, (array) $post_types );
+ }
+
+ /**
+ * Is the query for a specific time?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_time() {
+ return (bool) $this->is_time;
+ }
+
+ /**
+ * Is the query for a trackback endpoint call?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_trackback() {
+ return (bool) $this->is_trackback;
+ }
+
+ /**
+ * Is the query for an existing year archive?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_year() {
+ return (bool) $this->is_year;
+ }
+
+ /**
+ * Is the query a 404 (returns no results)?
+ *
+ * @since 3.1.0
+ *
+ * @return bool
+ */
+ public function is_404() {
+ return (bool) $this->is_404;
+ }
+
+ /**
+ * 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;
+ }