/
var
/
www
/
barefootlaw.org
/
wp-content
/
plugins
/
autodescription
/
inc
/
classes
/
builders
/
robots
/
Upload File
HOME
<?php /** * @package The_SEO_Framework\Classes\Builders\Robots\Query * @subpackage The_SEO_Framework\Getter\Robots */ namespace The_SEO_Framework\Builders\Robots; /** * The SEO Framework plugin * Copyright (C) 2021 - 2023 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ \defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die; /** * Engine for robots generator via query. * * @since 4.2.0 * @access private * Not part of the public API. * @final Can't be extended. */ final class Query extends Factory { // phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You don't love PHP7. // phpcs:disable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment -- You hate goto. // phpcs:disable, Generic.WhiteSpace.ScopeIndent.IncorrectExact -- You hate gotoo. /** * Generates robots assertions for no[index|archive|follow]. * * Yields true when "noindex/noarchive/nofollow", yields false when "index/archive/follow". * * @since 4.2.0 * @since 4.2.5 1. Removed needlessly duplicate homepage test. * 2. Moved archive pagination check to index_protection. * @generator * * @param string $type The robots generator type (noindex, nofollow...). */ protected static function assert_no( $type ) { // Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf hereinafter. $tsf = static::$tsf; $asserting_noindex = 'noindex' === $type; // We assert options here for a jump to meta_settings might be unaware. meta_settings: if ( ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS ) ) { $qubit = null; if ( $tsf->is_term_meta_capable() ) { $qubit = (int) $tsf->get_term_meta_item( $type ); } elseif ( $tsf->is_singular() ) { $qubit = (int) $tsf->get_post_meta_item( "_genesis_$type" ); } elseif ( \is_post_type_archive() ) { $qubit = (int) $tsf->get_post_type_archive_meta_item( $type ); } switch ( isset( $qubit ) ) : case false: // Page doesn't support metadata. break; case $qubit < -.33: // 'Force' index. yield 'meta_qubit_force' => false; // Override with index protection. goto index_protection; case $qubit > .33: // Force noindex. yield 'meta_qubit_force' => true; // We won't override this. Terminate generator. "goto end". // No break, generator stops here anyway. default: // qubit is (closer to) 0. Assert we use _default, albeit false. yield 'meta_qubit_default' => false; endswitch; } globals: yield 'globals_site' => (bool) $tsf->get_option( "site_$type" ); if ( $tsf->is_real_front_page() ) { yield 'globals_homepage' => (bool) $tsf->get_option( "homepage_$type" ); } else { $asserting_noindex and yield from static::assert_noindex_query_pass( '404' ); if ( $tsf->is_archive() ) { if ( $tsf->is_author() ) { yield 'globals_author' => (bool) $tsf->get_option( "author_$type" ); } elseif ( \is_date() ) { yield 'globals_date' => (bool) $tsf->get_option( "date_$type" ); } } elseif ( $tsf->is_search() ) { yield 'globals_search' => (bool) $tsf->get_option( "search_$type" ); } } // is_real_front_page() can still be singular or archive. Thus, this conditional block is split up. if ( $tsf->is_archive() ) { if ( $tsf->is_category() || $tsf->is_tag() || $tsf->is_tax() ) { yield 'globals_taxonomy' => $tsf->is_taxonomy_robots_set( $type, $tsf->get_current_taxonomy() ); // Store values from each post type bound to the taxonomy. foreach ( $tsf->get_post_types_from_taxonomy() as $post_type ) $_is_post_type_robots_set[] = $tsf->is_post_type_robots_set( $type, $post_type ); // Only enable if _all_ post types have been marked with 'no*'. Return false if no post types are found (corner case). yield 'globals_post_type_all' => isset( $_is_post_type_robots_set ) && ! \in_array( false, $_is_post_type_robots_set, true ); } elseif ( \is_post_type_archive() ) { yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, $tsf->get_current_post_type() ); } } elseif ( $tsf->is_singular() ) { yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, $tsf->get_current_post_type() ); } // We assert options here for a jump to index_protection might be unaware. index_protection: if ( $asserting_noindex && ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) ) { if ( $tsf->is_real_front_page() ) { yield from static::assert_noindex_query_pass( 'paged_home' ); } elseif ( $tsf->is_archive() || $tsf->is_singular_archive() ) { yield from static::assert_noindex_query_pass( 'paged' ); } if ( $tsf->is_singular() ) { yield from static::assert_noindex_query_pass( 'protected' ); /** * N.B. WordPress protects this query variable with options 'page_comments' * and 'default_comments_page' via `redirect_canonical()`, so we don't have to. * For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`; */ if ( (int) \get_query_var( 'cpage', 0 ) > 0 ) yield from static::assert_noindex_query_pass( 'cpage' ); } } exploit_protection: if ( $tsf->is_query_exploited() ) { if ( \in_array( $type, [ 'noindex', 'nofollow' ], true ) ) yield 'query_protection' => true; } end:; } // phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable // phpcs:enable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment // phpcs:enable, Generic.WhiteSpace.ScopeIndent.IncorrectExact /** * Generates robots assertions for noindex in passes. * * @since 4.2.0 * @generator * * @param string $pass The passage to assert. */ private static function assert_noindex_query_pass( $pass ) { // Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf hereinafter. $tsf = static::$tsf; switch ( $pass ) : case 'paged_home': yield 'paged_home' => ( $tsf->get_option( 'home_paged_noindex' ) && ( $tsf->page() > 1 || $tsf->paged() > 1 ) ); break; case '404': if ( $tsf->is_singular_archive() ) : /** * Pagination overflow protection via 404 test. * * When there are no posts, the first page will NOT relay 404; * which is exactly as intended. All other pages will relay 404. * * We do not test the post_count here, because we want to have * the first page indexable via user-intent only. Concordingly, too * because we cannot assert this via the administrative dashboard. */ yield '404' => \is_404(); else : /** * Check for 404, or if archive is empty: set noindex for those. * * Don't check this on the homepage. The homepage is sacred in this regard, * because page builders and templates can and will take over. * * Don't use empty(), null is regarded as indexable; it's why we coalesce to true whence null. * * @FIXME? In admin, this always yields "true" when trying query instead of args; ergo, noindex is set. * * post_count can be 0, which is false -> thus yield true -> noindex. * post_count can be null, which is true -> thus yield false -> index. * post count can be 5, which is true => thus yield false -> index. */ if ( $GLOBALS['wp_query']->post_count ?? true ) { yield '404' => false; } else { /** * We recommend using this filter ONLY for archives that have useful content but no "posts" attached. * For example: a specially custom-developed author page for an author that never published a post. * * This filter won't run when a few other conditions for noindex have been met. * * @since 4.1.4 * @link <https://github.com/sybrew/the-seo-framework/issues/194#issuecomment-864298702> * @param bool $noindex Whether to enable no posts protection. */ yield '404' => (bool) \apply_filters( 'the_seo_framework_enable_noindex_no_posts', true ); } endif; break; case 'paged': // Advanced Query Protection protects further against pagination attacks. No need to have that here. yield 'paged' => $tsf->get_option( 'paged_noindex' ) && $tsf->paged() > 1; break; case 'protected': // We get the "real ID" for WordPress might fault parsing a nefariously forged request. yield 'protected' => $tsf->is_protected( $tsf->get_the_real_ID() ); break; case 'cpage': /** * We do not recommend using this filter as it'll likely get those pages flagged as * duplicated by Google anyway; unless the theme strips or trims the content. * * This filter won't run when other conditions for noindex have been met. * * @since 4.0.5 * @param bool $noindex Whether to enable comment pagination protection. */ yield 'cpage' => \apply_filters( 'the_seo_framework_enable_noindex_comment_pagination', true ); break; endswitch; } }