Файловый менеджер - Редактировать - /home/kunzqhe/photostocker/2/helpers.tar
Ðазад
input-helper.php 0000644 00000001226 15154553720 0007701 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the filter_input. */ class Input_Helper { /** * Returns the result of the filter_input. This is mostly a wrapper so we can test. * * @param int $input_type The type of input constant (e.g. INPUT_POST, INPUT_GET ). * @param string $search_string The property to get from the input. * @param int $filter Optional. The constant that defines the sanitization. * * @return string The result of the get input. */ public function filter( $input_type, $search_string, $filter = \FILTER_DEFAULT ) { return \filter_input( $input_type, $search_string, $filter ); } } product-helper.php 0000644 00000001223 15154553720 0010217 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the Yoast products. */ class Product_Helper { /** * Gets the product name. * * @return string */ public function get_product_name() { if ( $this->is_premium() ) { return 'Yoast SEO Premium'; } return 'Yoast SEO'; } /** * Gets the product name in the head section. * * @return string */ public function get_name() { return $this->get_product_name() . ' plugin'; } /** * Checks if the installed version is Yoast SEO Premium. * * @return bool True when is premium. */ public function is_premium() { return \defined( 'WPSEO_PREMIUM_FILE' ); } } primary-term-helper.php 0000644 00000002567 15154553720 0011203 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use stdClass; /** * A helper object for primary terms. */ class Primary_Term_Helper { /** * Generate the primary term taxonomies. * * @param int $post_id ID of the post. * * @return array The taxonomies. */ public function get_primary_term_taxonomies( $post_id ) { $post_type = \get_post_type( $post_id ); $all_taxonomies = \get_object_taxonomies( $post_type, 'objects' ); $all_taxonomies = \array_filter( $all_taxonomies, [ $this, 'filter_hierarchical_taxonomies' ] ); /** * Filters which taxonomies for which the user can choose the primary term. * * @api array $taxonomies An array of taxonomy objects that are primary_term enabled. * * @param string $post_type The post type for which to filter the taxonomies. * @param array $all_taxonomies All taxonomies for this post types, even ones that don't have primary term * enabled. */ $taxonomies = (array) \apply_filters( 'wpseo_primary_term_taxonomies', $all_taxonomies, $post_type, $all_taxonomies ); return $taxonomies; } /** * Returns whether or not a taxonomy is hierarchical. * * @param stdClass $taxonomy Taxonomy object. * * @return bool True for hierarchical taxonomy. */ protected function filter_hierarchical_taxonomies( $taxonomy ) { return (bool) $taxonomy->hierarchical; } } schema/html-helper.php 0000644 00000002511 15154553720 0010744 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; /** * Class HTML_Helper. */ class HTML_Helper { /** * Sanitizes a HTML string by stripping all tags except headings, breaks, lists, links, paragraphs and formatting. * * @param string $html The original HTML. * * @return string The sanitized HTML. */ public function sanitize( $html ) { return \strip_tags( $html, '<h1><h2><h3><h4><h5><h6><br><ol><ul><li><a><p><b><strong><i><em>' ); } /** * Strips the tags in a smart way. * * @param string $html The original HTML. * * @return string The sanitized HTML. */ public function smart_strip_tags( $html ) { // Replace all new lines with spaces. $html = \preg_replace( '/(\r|\n)/', ' ', $html ); // Replace <br> tags with spaces. $html = \preg_replace( '/<br(\s*)?\/?>/i', ' ', $html ); // Replace closing </p> and other tags with the same tag with a space after it, so we don't end up connecting words when we remove them later. $html = \preg_replace( '/<\/(p|div|h\d)>/i', '</$1> ', $html ); // Replace list items with list identifiers so it still looks natural. $html = \preg_replace( '/(<li[^>]*>)/i', '$1• ', $html ); // Strip tags. $html = \wp_strip_all_tags( $html ); // Replace multiple spaces with one space. $html = \preg_replace( '!\s+!', ' ', $html ); return \trim( $html ); } } schema/image-helper.php 0000644 00000012417 15154553720 0011070 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; use Yoast\WP\SEO\Helpers\Image_Helper as Main_Image_Helper; /** * Class Image_Helper. */ class Image_Helper { /** * The HTML helper. * * @var HTML_Helper */ private $html; /** * The language helper. * * @var Language_Helper */ private $language; /** * Represents the main image helper. * * @var Main_Image_Helper */ private $image; /** * Image_Helper constructor. * * @codeCoverageIgnore It handles dependencies. * * @param HTML_Helper $html The HTML helper. * @param Language_Helper $language The language helper. * @param Main_Image_Helper $image The 'main' image helper. */ public function __construct( HTML_Helper $html, Language_Helper $language, Main_Image_Helper $image ) { $this->html = $html; $this->language = $language; $this->image = $image; } /** * Find an image based on its URL and generate a Schema object for it. * * @param string $schema_id The `@id` to use for the returned image. * @param string $url The image URL to base our object on. * @param string $caption An optional caption. * * @return array Schema ImageObject array. */ public function generate_from_url( $schema_id, $url, $caption = '' ) { $attachment_id = $this->image->get_attachment_by_url( $url ); if ( $attachment_id > 0 ) { return $this->generate_from_attachment_id( $schema_id, $attachment_id, $caption ); } return $this->simple_image_object( $schema_id, $url, $caption ); } /** * Retrieve data about an image from the database and use it to generate a Schema object. * * @param string $schema_id The `@id` to use for the returned image. * @param int $attachment_id The attachment to retrieve data from. * @param string $caption The caption string, if there is one. * * @return array Schema ImageObject array. */ public function generate_from_attachment_id( $schema_id, $attachment_id, $caption = '' ) { $data = $this->generate_object( $schema_id ); $data['url'] = $this->image->get_attachment_image_url( $attachment_id, 'full' ); $data['contentUrl'] = $data['url']; $data = $this->add_image_size( $data, $attachment_id ); $data = $this->add_caption( $data, $attachment_id, $caption ); return $data; } /** * Retrieve data about an image from the database and use it to generate a Schema object. * * @param string $schema_id The `@id` to use for the returned image. * @param array $attachment_meta The attachment metadata. * @param string $caption The caption string, if there is one. * * @return array Schema ImageObject array. */ public function generate_from_attachment_meta( $schema_id, $attachment_meta, $caption = '' ) { $data = $this->generate_object( $schema_id ); $data['url'] = $attachment_meta['url']; $data['contentUrl'] = $data['url']; $data['width'] = $attachment_meta['width']; $data['height'] = $attachment_meta['height']; if ( ! empty( $caption ) ) { $data['caption'] = $this->html->smart_strip_tags( $caption ); } return $data; } /** * If we can't find $url in our database, we output a simple ImageObject. * * @param string $schema_id The `@id` to use for the returned image. * @param string $url The image URL. * @param string $caption A caption, if set. * * @return array Schema ImageObject array. */ public function simple_image_object( $schema_id, $url, $caption = '' ) { $data = $this->generate_object( $schema_id ); $data['url'] = $url; $data['contentUrl'] = $url; if ( ! empty( $caption ) ) { $data['caption'] = $this->html->smart_strip_tags( $caption ); } return $data; } /** * Retrieves an image's caption if set, or uses the alt tag if that's set. * * @param array $data An ImageObject Schema array. * @param int $attachment_id Attachment ID. * @param string $caption The caption string, if there is one. * * @return array An imageObject with width and height set if available. */ private function add_caption( $data, $attachment_id, $caption = '' ) { if ( $caption !== '' ) { $data['caption'] = $caption; return $data; } $caption = $this->image->get_caption( $attachment_id ); if ( ! empty( $caption ) ) { $data['caption'] = $this->html->smart_strip_tags( $caption ); return $data; } return $data; } /** * Generates our bare bone ImageObject. * * @param string $schema_id The `@id` to use for the returned image. * * @return array an empty ImageObject */ private function generate_object( $schema_id ) { $data = [ '@type' => 'ImageObject', '@id' => $schema_id, ]; $data = $this->language->add_piece_language( $data ); return $data; } /** * Adds image's width and height. * * @param array $data An ImageObject Schema array. * @param int $attachment_id Attachment ID. * * @return array An imageObject with width and height set if available. */ private function add_image_size( $data, $attachment_id ) { $image_meta = $this->image->get_metadata( $attachment_id ); if ( empty( $image_meta['width'] ) || empty( $image_meta['height'] ) ) { return $data; } $data['width'] = $image_meta['width']; $data['height'] = $image_meta['height']; return $data; } } schema/language-helper.php 0000644 00000001462 15154553720 0011567 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; /** * Class Language_Helper. */ class Language_Helper { /** * Adds the `inLanguage` property to a Schema piece. * * Must use one of the language codes from the IETF BCP 47 standard. The * language tag syntax is made of one or more subtags separated by a hyphen * e.g. "en", "en-US", "zh-Hant-CN". * * @param array $data The Schema piece data. * * @return array The Schema piece data with added language property */ public function add_piece_language( $data ) { /** * Filter: 'wpseo_schema_piece_language' - Allow changing the Schema piece language. * * @api string $type The Schema piece language. */ $data['inLanguage'] = \apply_filters( 'wpseo_schema_piece_language', \get_bloginfo( 'language' ), $data ); return $data; } } schema/id-helper.php 0000644 00000001263 15154553720 0010377 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; use Yoast\WP\SEO\Config\Schema_IDs; use Yoast\WP\SEO\Context\Meta_Tags_Context; /** * Schema utility functions. */ class ID_Helper { /** * Retrieve a users Schema ID. * * @param int $user_id The ID of the User you need a Schema ID for. * @param Meta_Tags_Context $context A value object with context variables. * * @return string The user's schema ID. */ public function get_user_schema_id( $user_id, $context ) { $user = \get_userdata( $user_id ); if ( \is_a( $user, 'WP_User' ) ) { return $context->site_url . Schema_IDs::PERSON_HASH . \wp_hash( $user->user_login . $user_id ); } return ''; } } schema/article-helper.php 0000644 00000002214 15154553720 0011423 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; /** * Class Article_Helper. */ class Article_Helper { /** * Determines whether a given post type should have Article schema. * * @param string|null $post_type Post type to check. * * @return bool True if it has Article schema, false if not. */ public function is_article_post_type( $post_type = null ) { if ( \is_null( $post_type ) ) { $post_type = \get_post_type(); } /** * Filter: 'wpseo_schema_article_post_types' - Allow changing for which post types we output Article schema. * * @api string[] $post_types The post types for which we output Article. */ $post_types = \apply_filters( 'wpseo_schema_article_post_types', [ 'post' ] ); return \in_array( $post_type, $post_types, true ); } /** * Checks whether author is supported for the passed object sub type. * * @param string $object_sub_type The sub type of the object to check author support for. * * @return bool True if author is supported for the passed object sub type. */ public function is_author_supported( $object_sub_type ) { return \post_type_supports( $object_sub_type, 'author' ); } } schema/replace-vars-helper.php 0000644 00000006764 15154553720 0012402 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Schema; use Closure; use WPSEO_Replace_Vars; use Yoast\WP\SEO\Conditionals\No_Conditionals; use Yoast\WP\SEO\Config\Schema_IDs; use Yoast\WP\SEO\Context\Meta_Tags_Context; use Yoast\WP\SEO\Helpers\Date_Helper; use Yoast\WP\SEO\Presentations\Indexable_Presentation; /** * Registers the Schema replace variables and exposes a method to replace variables on a Schema graph. */ class Replace_Vars_Helper { use No_Conditionals; /** * The replace vars. * * @var WPSEO_Replace_Vars */ protected $replace_vars; /** * The Schema ID helper. * * @var ID_Helper */ protected $id_helper; /** * The date helper. * * @var Date_Helper */ protected $date_helper; /** * Replace_Vars_Helper constructor. * * @param WPSEO_Replace_Vars $replace_vars The replace vars. * @param ID_Helper $id_helper The Schema ID helper. * @param Date_Helper $date_helper The date helper. */ public function __construct( WPSEO_Replace_Vars $replace_vars, ID_Helper $id_helper, Date_Helper $date_helper ) { $this->replace_vars = $replace_vars; $this->id_helper = $id_helper; $this->date_helper = $date_helper; } /** * Replaces the variables. * * @param array $schema_data The Schema data. * @param Indexable_Presentation $presentation The indexable presentation. * * @return array The array with replaced vars. */ public function replace( array $schema_data, Indexable_Presentation $presentation ) { foreach ( $schema_data as $key => $value ) { if ( \is_array( $value ) ) { $schema_data[ $key ] = $this->replace( $value, $presentation ); continue; } $schema_data[ $key ] = $this->replace_vars->replace( $value, $presentation->source ); } return $schema_data; } /** * Registers the Schema-related replace vars. * * @param Meta_Tags_Context $context The meta tags context. * * @return void */ public function register_replace_vars( $context ) { $replace_vars = [ 'main_schema_id' => $context->main_schema_id, 'author_id' => $this->id_helper->get_user_schema_id( $context->indexable->author_id, $context ), 'person_id' => $context->site_url . Schema_IDs::PERSON_HASH, 'primary_image_id' => $context->canonical . Schema_IDs::PRIMARY_IMAGE_HASH, 'webpage_id' => $context->canonical . Schema_IDs::WEBPAGE_HASH, 'website_id' => $context->site_url . Schema_IDs::WEBSITE_HASH, 'organization_id' => $context->site_url . Schema_IDs::ORGANIZATION_HASH, ]; if ( $context->post ) { // Post does not always exist, e.g. on term pages. $replace_vars['post_date'] = $this->date_helper->format( $context->post->post_date, \DATE_ATOM ); } foreach ( $replace_vars as $var => $value ) { $this->register_replacement( $var, $value ); } } /** * Registers a replace var and its value. * * @param string $variable The replace variable. * @param string $value The value that the variable should be replaced with. */ protected function register_replacement( $variable, $value ) { $this->replace_vars->safe_register_replacement( $variable, $this->get_identity_function( $value ) ); } /** * Returns an anonymous function that in turn just returns the given value. * * @param mixed $value The value that the function should return. * * @return Closure A function that returns the given value. */ protected function get_identity_function( $value ) { return static function() use ( $value ) { return $value; }; } } notification-helper.php 0000644 00000001042 15154553720 0011224 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast_Notification; use Yoast_Notification_Center; /** * A helper object for notifications. */ class Notification_Helper { /** * Restores a notification (wrapper function). * * @codeCoverageIgnore * * @param Yoast_Notification $notification The notification to restore. * * @return bool True if restored, false otherwise. */ public function restore_notification( Yoast_Notification $notification ) { return Yoast_Notification_Center::restore_notification( $notification ); } } post-helper.php 0000644 00000011702 15154553720 0007527 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WP_Post; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * A helper object for post related things. */ class Post_Helper { /** * Holds the String_Helper instance. * * @var String_Helper */ private $string; /** * Represents the indexables repository. * * @var Indexable_Repository */ private $repository; /** * Post_Helper constructor. * * @codeCoverageIgnore It only sets dependencies. * * @param String_Helper $string The string helper. */ public function __construct( String_Helper $string ) { $this->string = $string; } /** * Sets the indexable repository. Done to avoid circular dependencies. * * @required * * @param Indexable_Repository $repository The indexable repository. */ public function set_indexable_repository( Indexable_Repository $repository ) { $this->repository = $repository; } /** * Removes all shortcode tags from the given content. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $content Content to remove all the shortcode tags from. * * @return string Content without shortcode tags. */ public function strip_shortcodes( $content ) { return \strip_shortcodes( $content ); } /** * Retrieves the post excerpt (without tags). * * @codeCoverageIgnore It only wraps another helper method. * * @param int $post_id Post ID. * * @return string Post excerpt (without tags). */ public function get_the_excerpt( $post_id ) { return $this->string->strip_all_tags( \get_the_excerpt( $post_id ) ); } /** * Retrieves the post type of the current post. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param WP_Post|null $post The post. * * @return string|false Post type on success, false on failure. */ public function get_post_type( $post = null ) { return \get_post_type( $post ); } /** * Retrieves the post title with fallback to `No title`. * * @param int $post_id Optional. Post ID. * * @return string The post title with fallback to `No title`. */ public function get_post_title_with_fallback( $post_id = 0 ) { $post_title = \get_the_title( $post_id ); if ( $post_title ) { return $post_title; } return \__( 'No title', 'wordpress-seo' ); } /** * Retrieves post data given a post ID. * * @codeCoverageIgnore It wraps a WordPress function. * * @param int $post_id Post ID. * * @return WP_Post|null The post. */ public function get_post( $post_id ) { return \get_post( $post_id ); } /** * Updates the has_public_posts field on attachments for a post_parent. * * An attachment is represented by their post parent when: * - The attachment has a post parent. * - The attachment inherits the post status. * * @codeCoverageIgnore It relies too much on dependencies. * * @param int $post_parent Post ID. * @param int $has_public_posts Whether the parent is public. * * @return bool Whether the update was successful. */ public function update_has_public_posts_on_attachments( $post_parent, $has_public_posts ) { $query = $this->repository->query() ->select( 'id' ) ->where( 'object_type', 'post' ) ->where( 'object_sub_type', 'attachment' ) ->where( 'post_status', 'inherit' ) ->where( 'post_parent', $post_parent ); if ( $has_public_posts !== null ) { $query->where_raw( '( has_public_posts IS NULL OR has_public_posts <> %s )', [ $has_public_posts ] ); } else { $query->where_not_null( 'has_public_posts' ); } $results = $query->find_array(); if ( empty( $results ) ) { return true; } $updated = $this->repository->query() ->set( 'has_public_posts', $has_public_posts ) ->where_id_in( \wp_list_pluck( $results, 'id' ) ) ->update_many(); return $updated !== false; } /** * Determines if the post can be indexed. * * @param int $post_id Post ID to check. * * @return bool True if the post can be indexed. */ public function is_post_indexable( $post_id ) { // Don't index excluded post statuses. if ( \in_array( \get_post_status( $post_id ), $this->get_excluded_post_statuses(), true ) ) { return false; } // Don't index revisions of posts. if ( \wp_is_post_revision( $post_id ) ) { return false; } // Don't index autosaves that are not caught by the auto-draft check. if ( \wp_is_post_autosave( $post_id ) ) { return false; } return true; } /** * Retrieves the list of excluded post statuses. * * @return array The excluded post statuses. */ public function get_excluded_post_statuses() { return [ 'auto-draft' ]; } /** * Retrieves the list of public posts statuses. * * @return array The public post statuses. */ public function get_public_post_statuses() { /** * Filter: 'wpseo_public_post_statuses' - List of public post statuses. * * @api array $post_statuses Post status list, defaults to array( 'publish' ). */ return \apply_filters( 'wpseo_public_post_statuses', [ 'publish' ] ); } } site-helper.php 0000644 00000001066 15154553720 0007510 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for site options. */ class Site_Helper { /** * Retrieves the site name. * * @return string */ public function get_site_name() { return \wp_strip_all_tags( \get_bloginfo( 'name' ), true ); } /** * Checks if the current installation is a multisite and there has been a switch * between the set multisites. * * @return bool True when there was a switch between the multisites. */ public function is_multisite_and_switched() { return \is_multisite() && \ms_is_switched(); } } permalink-helper.php 0000644 00000002406 15154553720 0010525 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\SEO\Models\Indexable; /** * A helper object for permalinks. */ class Permalink_Helper { /** * Retrieves the permalink for an indexable. * * @param Indexable $indexable The indexable. * * @return string|null The permalink. */ public function get_permalink_for_indexable( $indexable ) { switch ( true ) { case $indexable->object_type === 'post': if ( $indexable->object_sub_type === 'attachment' ) { return \wp_get_attachment_url( $indexable->object_id ); } return \get_permalink( $indexable->object_id ); case $indexable->object_type === 'home-page': return \home_url( '/' ); case $indexable->object_type === 'term': $term = \get_term( $indexable->object_id ); if ( $term === null || \is_wp_error( $term ) ) { return null; } return \get_term_link( $term, $term->taxonomy ); case $indexable->object_type === 'system-page' && $indexable->object_sub_type === 'search-page': return \get_search_link(); case $indexable->object_type === 'post-type-archive': return \get_post_type_archive_link( $indexable->object_sub_type ); case $indexable->object_type === 'user': return \get_author_posts_url( $indexable->object_id ); } return null; } } pagination-helper.php 0000644 00000006745 15154553720 0010706 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\SEO\Wrappers\WP_Query_Wrapper; use Yoast\WP\SEO\Wrappers\WP_Rewrite_Wrapper; /** * A helper object for pagination. * * Used for the canonical URL and the rel "next" and "prev" meta tags. */ class Pagination_Helper { /** * Holds the WP rewrite wrapper instance. * * @var WP_Rewrite_Wrapper WP_Rewrite wrapper. */ protected $wp_rewrite_wrapper; /** * Holds the WP query wrapper instance. * * @var WP_Query_Wrapper WP_Query wrapper. */ protected $wp_query_wrapper; /** * Pagination_Helper constructor. * * @param WP_Rewrite_Wrapper $wp_rewrite_wrapper The rewrite wrapper. * @param WP_Query_Wrapper $wp_query_wrapper The query wrapper. */ public function __construct( WP_Rewrite_Wrapper $wp_rewrite_wrapper, WP_Query_Wrapper $wp_query_wrapper ) { $this->wp_rewrite_wrapper = $wp_rewrite_wrapper; $this->wp_query_wrapper = $wp_query_wrapper; } /** * Checks whether adjacent rel links are disabled. * * @return bool Whether adjacent rel links are disabled or not. */ public function is_rel_adjacent_disabled() { /** * Filter: 'wpseo_disable_adjacent_rel_links' - Allows disabling of Yoast adjacent links if this is being handled by other code. * * @api bool $links_generated Indicates if other code has handled adjacent links. */ return \apply_filters( 'wpseo_disable_adjacent_rel_links', false ); } /** * Builds a paginated URL. * * @param string $url The un-paginated URL of the current archive. * @param string $page The page number to add on to $url for the $link tag. * @param bool $add_pagination_base Optional. Whether to add the pagination base (`page`) to the url. * @param string $pagination_query_name Optional. The name of the query argument that holds the current page. * * @return string The paginated URL. */ public function get_paginated_url( $url, $page, $add_pagination_base = true, $pagination_query_name = 'page' ) { $wp_rewrite = $this->wp_rewrite_wrapper->get(); if ( $wp_rewrite->using_permalinks() ) { $url = \trailingslashit( $url ); if ( $add_pagination_base ) { $url .= \trailingslashit( $wp_rewrite->pagination_base ); } return \user_trailingslashit( $url . $page ); } return \add_query_arg( $pagination_query_name, $page, \user_trailingslashit( $url ) ); } /** * Gets the number of archive pages. * * @return int The number of archive pages. */ public function get_number_of_archive_pages() { $wp_query = $this->wp_query_wrapper->get_query(); return (int) $wp_query->max_num_pages; } /** * Returns the current page for paged archives. * * @return int The current archive page. */ public function get_current_archive_page_number() { $wp_query = $this->wp_query_wrapper->get_main_query(); return (int) $wp_query->get( 'paged' ); } /** * Returns the current page for paged post types. * * @return int The current post page. */ public function get_current_post_page_number() { $wp_query = $this->wp_query_wrapper->get_main_query(); return (int) $wp_query->get( 'page' ); } /** * Returns the current page number. * * @return int The current page number. */ public function get_current_page_number() { // Get the page number for an archive page. $page_number = \get_query_var( 'paged', 1 ); if ( $page_number > 1 ) { return $page_number; } // Get the page number for a page in a paginated post. return \get_query_var( 'page', 1 ); } } woocommerce-helper.php 0000644 00000001557 15154553720 0011070 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * Represents helper methods for WooCommerce. */ class Woocommerce_Helper { /** * Checks if WooCommerce is active. * * @return bool Is WooCommerce active. */ public function is_active() { return \class_exists( 'WooCommerce' ); } /** * Returns the id of the set WooCommerce shop page. * * @return int The ID of the set page. */ public function get_shop_page_id() { if ( ! \function_exists( 'wc_get_page_id' ) ) { return -1; } return \wc_get_page_id( 'shop' ); } /** * Checks if the current page is a WooCommerce shop page. * * @return bool True when the page is a shop page. */ public function is_shop_page() { if ( ! \function_exists( 'is_shop' ) ) { return false; } if ( ! \is_shop() ) { return false; } if ( \is_search() ) { return false; } return true; } } open-graph/image-helper.php 0000644 00000005541 15154553720 0011670 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Open_Graph; use Yoast\WP\SEO\Helpers\Image_Helper as Base_Image_Helper; use Yoast\WP\SEO\Helpers\Url_Helper; /** * A helper object for Open Graph images. */ class Image_Helper { /** * The URL helper. * * @var Url_Helper */ private $url; /** * The base image helper. * * @var Base_Image_Helper */ private $image; /** * Image_Helper constructor. * * @codeCoverageIgnore * * @param Url_Helper $url The url helper. * @param Base_Image_Helper $image The image helper. */ public function __construct( Url_Helper $url, Base_Image_Helper $image ) { $this->url = $url; $this->image = $image; } /** * Determines whether the passed URL is considered valid. * * @param array $image The image array. * * @return bool Whether or not the URL is a valid image. */ public function is_image_url_valid( array $image ) { if ( empty( $image['url'] ) || ! \is_string( $image['url'] ) ) { return false; } $image_extension = $this->url->get_extension_from_url( $image['url'] ); $is_valid = $this->image->is_extension_valid( $image_extension ); /** * Filter: 'wpseo_opengraph_is_valid_image_url' - Allows extra validation for an image url. * * @api bool - Current validation result. * * @param string $url The image url to validate. */ return (bool) \apply_filters( 'wpseo_opengraph_is_valid_image_url', $is_valid, $image['url'] ); } /** * Retrieves the overridden image size value. * * @return string|null The image size when overriden by filter or null when not. */ public function get_override_image_size() { /** * Filter: 'wpseo_opengraph_image_size' - Allow overriding the image size used * for Open Graph sharing. If this filter is used, the defined size will always be * used for the og:image. The image will still be rejected if it is too small. * * Only use this filter if you manually want to determine the best image size * for the `og:image` tag. * * Use the `wpseo_image_sizes` filter if you want to use our logic. That filter * can be used to add an image size that needs to be taken into consideration * within our own logic. * * @api string|false $size Size string. */ return \apply_filters( 'wpseo_opengraph_image_size', null ); } /** * Retrieves the image data by a given attachment id. * * @param int $attachment_id The attachment id. * * @return array|false The image data when found, `false` when not. */ public function get_image_by_id( $attachment_id ) { if ( ! $this->image->is_valid_attachment( $attachment_id ) ) { return false; } $override_image_size = $this->get_override_image_size(); if ( $override_image_size ) { return $this->image->get_image( $attachment_id, $override_image_size ); } return $this->image->get_best_attachment_variation( $attachment_id ); } } open-graph/values-helper.php 0000644 00000005134 15154553720 0012103 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Open_Graph; /** * A helper object for the filtering of values. */ class Values_Helper { /** * Filters the Open Graph title. * * @param string $title The default title. * @param string $object_type The object type. * @param string $object_subtype The object subtype. * * @return string The open graph title. */ public function get_open_graph_title( $title, $object_type, $object_subtype ) { /** * Allow changing the Open Graph title. * * @param string $title The default title. * @param string $object_subtype The object subtype. */ return \apply_filters( 'Yoast\WP\SEO\open_graph_title_' . $object_type, $title, $object_subtype ); } /** * Filters the Open Graph description. * * @param string $description The default description. * @param string $object_type The object type. * @param string $object_subtype The object subtype. * * @return string The open graph description. */ public function get_open_graph_description( $description, $object_type, $object_subtype ) { /** * Allow changing the Open Graph description. * * @param string $description The default description. * @param string $object_subtype The object subtype. */ return \apply_filters( 'Yoast\WP\SEO\open_graph_description_' . $object_type, $description, $object_subtype ); } /** * Filters the Open Graph image ID. * * @param int $image_id The default image ID. * @param string $object_type The object type. * @param string $object_subtype The object subtype. * * @return string The open graph image ID. */ public function get_open_graph_image_id( $image_id, $object_type, $object_subtype ) { /** * Allow changing the Open Graph image ID. * * @param int $image_id The default image ID. * @param string $object_subtype The object subtype. */ return \apply_filters( 'Yoast\WP\SEO\open_graph_image_id_' . $object_type, $image_id, $object_subtype ); } /** * Filters the Open Graph image URL. * * @param string $image The default image URL. * @param string $object_type The object type. * @param string $object_subtype The object subtype. * * @return string The open graph image URL. */ public function get_open_graph_image( $image, $object_type, $object_subtype ) { /** * Allow changing the Open Graph image URL. * * @param string $image The default image URL. * @param string $object_subtype The object subtype. */ return \apply_filters( 'Yoast\WP\SEO\open_graph_image_' . $object_type, $image, $object_subtype ); } } redirect-helper.php 0000644 00000002662 15154553720 0010350 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for redirects. */ class Redirect_Helper { /** * Wraps wp_redirect to allow testing for redirects. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $location The path to redirect to. * @param int $status The status code to use. */ public function do_unsafe_redirect( $location, $status = 302 ) { // phpcs:ignore WordPress.Security.SafeRedirect -- intentional, function has been renamed to make unsafe more clear. \wp_redirect( $location, $status, 'Yoast SEO' ); exit; } /** * Wraps wp_safe_redirect to allow testing for safe redirects. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $location The path to redirect to. * @param int $status The status code to use. */ public function do_safe_redirect( $location, $status = 302 ) { \wp_safe_redirect( $location, $status, 'Yoast SEO' ); exit; } /** * Wraps wp_redirect to allow testing for redirects. * * @deprecated 16.x * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $location The path to redirect to. * @param int $status The status code to use. */ public function do_redirect( $location, $status = 302 ) { \_deprecated_function( __METHOD__, 'WPSEO 16.x', 'Yoast\WP\SEO\Helpers\Redirect_Helper::do_unsafe_redirect' ); $this->do_unsafe_redirect( $location, $status ); } } language-helper.php 0000644 00000005621 15154553720 0010330 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WPSEO_Language_Utils; use Yoast\WP\SEO\Conditionals\Japanese_Support_Conditional; use Yoast\WP\SEO\Config\Researcher_Languages; /** * A helper object for language features. */ class Language_Helper { /** * Represents the Japanese support conditional. * * @var Japanese_Support_Conditional */ protected $japanese_conditional; /** * Language_Helper constructor. * * @param Japanese_Support_Conditional $japanese_conditional The Japanese support conditional. */ public function __construct( Japanese_Support_Conditional $japanese_conditional ) { $this->japanese_conditional = $japanese_conditional; } /** * Checks whether word form recognition is active for the used language. * * @param string $language The used language. * * @return bool Whether word form recognition is active for the used language. */ public function is_word_form_recognition_active( $language ) { $supported_languages = [ 'de', 'en', 'es', 'fr', 'it', 'nl', 'ru', 'id', 'pt', 'pl', 'ar', 'sv', 'he', 'hu', 'nb', 'tr', 'cs', 'sk', 'el' ]; // If JAPANESE_SUPPORT feature is enabled, push Japanese to the array of the supported languages. if ( $this->japanese_conditional->is_met() ) { \array_push( $supported_languages, 'ja' ); } return \in_array( $language, $supported_languages, true ); } /** * Checks whether the given language has function word support. * (E.g. function words are used or filtered out for this language when doing some SEO and readability assessments). * * @param string $language The language to check. * * @return bool Whether the language has function word support. */ public function has_function_word_support( $language ) { $supported_languages = [ 'en', 'de', 'nl', 'fr', 'es', 'it', 'pt', 'ru', 'pl', 'sv', 'id', 'he', 'ar', 'hu', 'nb', 'tr', 'cs', 'sk', 'fa', 'el' ]; // If JAPANESE_SUPPORT feature is enabled, push Japanese to the array of the supported languages. if ( $this->japanese_conditional->is_met() ) { \array_push( $supported_languages, 'ja' ); } return \in_array( $language, $supported_languages, true ); } /** * Checks whether we have a specific researcher for the current locale and returns that language. * If there is no researcher for the current locale, returns default as the researcher. * * @return string The language to use to select a researcher. */ public function get_researcher_language() { $researcher_language = WPSEO_Language_Utils::get_language( \get_locale() ); $supported_languages = Researcher_Languages::SUPPORTED_LANGUAGES; // If JAPANESE_SUPPORT feature is enabled, push Japanese to the array of the supported languages. if ( $this->japanese_conditional->is_met() ) { \array_push( $supported_languages, 'ja' ); } if ( ! \in_array( $researcher_language, $supported_languages, true ) ) { $researcher_language = 'default'; } return $researcher_language; } } require-file-helper.php 0000644 00000000461 15154553720 0011133 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * Represents a file helper. */ class Require_File_Helper { /** * Activates the plugin based on the given plugin file. * * @param string $path The path to the required file. */ public function require_file_once( $path ) { require_once $path; } } home-url-helper.php 0000644 00000001402 15154553720 0010266 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the home URL. */ class Home_Url_Helper { /** * The home url. * * @var string */ protected static $home_url; /** * The parsed home url. * * @var array */ protected static $parsed_home_url; /** * Retrieves the home url. * * @return string The home url. */ public function get() { if ( static::$home_url === null ) { static::$home_url = \home_url(); } return static::$home_url; } /** * Retrieves the home url that has been parsed. * * @return array The parsed url. */ public function get_parsed() { if ( static::$parsed_home_url === null ) { static::$parsed_home_url = \wp_parse_url( $this->get() ); } return static::$parsed_home_url; } } robots-helper.php 0000644 00000001016 15154553720 0010047 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the robots meta tag. */ class Robots_Helper { /** * Sets the robots index to noindex. * * @param array $robots The current robots value. * * @return array The altered robots string. */ public function set_robots_no_index( $robots ) { if ( ! \is_array( $robots ) ) { \_deprecated_argument( __METHOD__, '14.1', '$robots has to be a key-value paired array.' ); return $robots; } $robots['index'] = 'noindex'; return $robots; } } post-type-helper.php 0000644 00000006701 15154553720 0010511 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for post types. */ class Post_Type_Helper { /** * The options helper. * * @var Options_Helper */ protected $options_helper; /** * Post_Type_Helper constructor. * * @param Options_Helper $options_helper The options helper. */ public function __construct( Options_Helper $options_helper ) { $this->options_helper = $options_helper; } /** * Checks if the request post type is public and indexable. * * @codeCoverageIgnore We have to write test when this method contains own code. * * @param string $post_type_name The name of the post type to lookup. * * @return bool True when post type is set to index. */ public function is_indexable( $post_type_name ) { if ( $this->options_helper->get( 'disable-' . $post_type_name, false ) ) { return false; } return ( $this->options_helper->get( 'noindex-' . $post_type_name, false ) === false ); } /** * Returns an array with the public post types. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $output The output type to use. * * @return array Array with all the public post_types. */ public function get_public_post_types( $output = 'names' ) { return \get_post_types( [ 'public' => true ], $output ); } /** * Returns an array with the accessible post types. * * An accessible post type is a post type that is public and isn't set as no-index (robots). * * @return array Array with all the accessible post_types. */ public function get_accessible_post_types() { $post_types = \get_post_types( [ 'public' => true ] ); $post_types = \array_filter( $post_types, 'is_post_type_viewable' ); /** * Filter: 'wpseo_accessible_post_types' - Allow changing the accessible post types. * * @api array $post_types The public post types. */ $post_types = \apply_filters( 'wpseo_accessible_post_types', $post_types ); // When the array gets messed up somewhere. if ( ! \is_array( $post_types ) ) { return []; } return $post_types; } /** * Returns an array of post types that are excluded from being indexed for the * indexables. * * @return array The excluded post types. */ public function get_excluded_post_types_for_indexables() { /** * Filter: 'wpseo_indexable_excluded_post_types' - Allow developers to prevent posts of a certain post * type from being saved to the indexable table. * * @param array $excluded_post_types The currently excluded post types. */ $excluded_post_types = \apply_filters( 'wpseo_indexable_excluded_post_types', [] ); // Failsafe, to always make sure that `excluded_post_types` is an array. if ( ! \is_array( $excluded_post_types ) ) { return []; } return $excluded_post_types; } /** * Checks if the post type is excluded. * * @param string $post_type The post type to check. * * @return bool If the post type is exclude. */ public function is_excluded( $post_type ) { return \in_array( $post_type, $this->get_excluded_post_types_for_indexables(), true ); } /** * Checks if the post type with the given name has an archive page. * * @param WP_Post_Type|string $post_type The name of the post type to check. * * @return bool True when the post type has an archive page. */ public function has_archive( $post_type ) { if ( \is_string( $post_type ) ) { $post_type = \get_post_type_object( $post_type ); } return ( ! empty( $post_type->has_archive ) ); } } capability-helper.php 0000644 00000004104 15154553720 0010661 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for user capabilities. */ class Capability_Helper { /** * Checks if the user has at least one of the proper capabilities. * * @param string $capability Capability to check. * * @return bool True if the user has at least one of the proper rights. */ public function current_user_can( $capability ) { if ( $capability === 'wpseo_manage_options' ) { return \current_user_can( $capability ); } return $this->has_any( [ 'wpseo_manage_options', $capability ] ); } /** * Retrieves the users that have the specified capability. * * @param string $capability The name of the capability. * * @return array The users that have the capability. */ public function get_applicable_users( $capability ) { $applicable_roles = $this->get_applicable_roles( $capability ); if ( $applicable_roles === [] ) { return []; } return \get_users( [ 'role__in' => $applicable_roles ] ); } /** * Retrieves the roles that have the specified capability. * * @param string $capability The name of the capability. * * @return array The names of the roles that have the capability. */ public function get_applicable_roles( $capability ) { $roles = \wp_roles(); $role_names = $roles->get_names(); $applicable_roles = []; foreach ( \array_keys( $role_names ) as $role_name ) { $role = $roles->get_role( $role_name ); if ( ! $role ) { continue; } // Add role if it has the capability. if ( \array_key_exists( $capability, $role->capabilities ) && $role->capabilities[ $capability ] === true ) { $applicable_roles[] = $role_name; } } return $applicable_roles; } /** * Checks if the current user has at least one of the supplied capabilities. * * @param array $capabilities Capabilities to check against. * * @return bool True if the user has at least one capability. */ private function has_any( array $capabilities ) { foreach ( $capabilities as $capability ) { if ( \current_user_can( $capability ) ) { return true; } } return false; } } blocks-helper.php 0000644 00000004415 15154553720 0010022 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WP_Block_Parser_Block; /** * A helper object for blocks. */ class Blocks_Helper { /** * Holds the Post_Helper instance. * * @var Post_Helper */ private $post; /** * Constructs a Blocks_Helper instance. * * @codeCoverageIgnore It handles dependencies. * * @param Post_Helper $post The post helper. */ public function __construct( Post_Helper $post ) { $this->post = $post; } /** * Returns all blocks in a given post. * * @param int $post_id The post id. * * @return array The blocks in a block-type => WP_Block_Parser_Block[] format. */ public function get_all_blocks_from_post( $post_id ) { if ( ! $this->has_blocks_support() ) { return []; } $post = $this->post->get_post( $post_id ); return $this->get_all_blocks_from_content( $post->post_content ); } /** * Returns all blocks in a given content. * * @param string $content The content. * * @return array The blocks in a block-type => WP_Block_Parser_Block[] format. */ public function get_all_blocks_from_content( $content ) { if ( ! $this->has_blocks_support() ) { return []; } $collection = []; $blocks = \parse_blocks( $content ); return $this->collect_blocks( $blocks, $collection ); } /** * Checks if the installation has blocks support. * * @codeCoverageIgnore It only checks if a WordPress function exists. * * @return bool True when function parse_blocks exists. */ protected function has_blocks_support() { return \function_exists( 'parse_blocks' ); } /** * Collects an array of blocks into an organised collection. * * @param WP_Block_Parser_Block[] $blocks The blocks. * @param array $collection The collection. * * @return array The blocks in a block-type => WP_Block_Parser_Block[] format. */ private function collect_blocks( $blocks, $collection ) { foreach ( $blocks as $block ) { if ( ! isset( $collection[ $block['blockName'] ] ) || ! \is_array( $collection[ $block['blockName'] ] ) ) { $collection[ $block['blockName'] ] = []; } $collection[ $block['blockName'] ][] = $block; if ( isset( $block['innerBlocks'] ) ) { $collection = $this->collect_blocks( $block['innerBlocks'], $collection ); } } return $collection; } } meta-helper.php 0000644 00000005065 15154553720 0007475 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WPSEO_Meta; use WPSEO_Taxonomy_Meta; /** * A helper object for meta. */ class Meta_Helper { /** * Get a custom post meta value. * * Returns the default value if the meta value has not been set. * * {@internal Unfortunately there isn't a filter available to hook into before returning * the results for get_post_meta(), get_post_custom() and the likes. That * would have been the preferred solution.}} * * @codeCoverageIgnore We have to write test when this method contains own code. * * @param string $key Internal key of the value to get (without prefix). * @param int $postid Post ID of the post to get the value for. * * @return string All 'normal' values returned from get_post_meta() are strings. * Objects and arrays are possible, but not used by this plugin * and therefore discarted (except when the special 'serialized' field def * value is set to true - only used by add-on plugins for now). * Will return the default value if no value was found. * Will return empty string if no default was found (not one of our keys) or * if the post does not exist. */ public function get_value( $key, $postid = 0 ) { return WPSEO_Meta::get_value( $key, $postid ); } /** * Retrieve a taxonomy term's meta value(s). * * @param mixed $term Term to get the meta value for * either (string) term name, (int) term id or (object) term. * @param string $taxonomy Name of the taxonomy to which the term is attached. * @param string|null $meta Optional. Meta value to get (without prefix). * * @return mixed|bool Value for the $meta if one is given, might be the default. * If no meta is given, an array of all the meta data for the term. * False if the term does not exist or the $meta provided is invalid. */ public function get_term_value( $term, $taxonomy, $meta = null ) { return WPSEO_Taxonomy_Meta::get_term_meta( $term, $taxonomy, $meta ); } /** * Set a custom post meta value. * * @param string $key Internal key of the value to set (without prefix). * @param mixed $meta_value The value to set the meta value to. * @param int $post_id Post ID of the post to set the value for. * * @return bool Whether the value was changed. */ public function set_value( $key, $meta_value, $post_id ) { return WPSEO_Meta::set_value( $key, $meta_value, $post_id ); } } date-helper.php 0000644 00000005436 15154553720 0007466 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use DateTime; use DateTimeZone; use Exception; /** * A helper object for dates. */ class Date_Helper { /** * Convert given date string to the W3C format. * * If $translate is true then the given date and format string will * be passed to date_i18n() for translation. * * @param string $date Date string to convert. * @param bool $translate Whether the return date should be translated. Default false. * * @return string Formatted date string. */ public function mysql_date_to_w3c_format( $date, $translate = false ) { return \mysql2date( \DATE_W3C, $date, $translate ); } /** * Formats a given date in UTC TimeZone format. * * @param string $date String representing the date / time. * @param string $format The format that the passed date should be in. * * @return string The formatted date. */ public function format( $date, $format = \DATE_W3C ) { $immutable_date = \date_create_immutable_from_format( 'Y-m-d H:i:s', $date, new DateTimeZone( 'UTC' ) ); if ( ! $immutable_date ) { return $date; } return $immutable_date->format( $format ); } /** * Formats the given timestamp to the needed format. * * @param int $timestamp The timestamp to use for the formatting. * @param string $format The format that the passed date should be in. * * @return string The formatted date. */ public function format_timestamp( $timestamp, $format = \DATE_W3C ) { $immutable_date = \date_create_immutable_from_format( 'U', $timestamp, new DateTimeZone( 'UTC' ) ); if ( ! $immutable_date ) { return $timestamp; } return $immutable_date->format( $format ); } /** * Formats a given date in UTC TimeZone format and translate it to the set language. * * @param string $date String representing the date / time. * @param string $format The format that the passed date should be in. * * @return string The formatted and translated date. */ public function format_translated( $date, $format = \DATE_W3C ) { return \date_i18n( $format, $this->format( $date, 'U' ) ); } /** * Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). * * @return int The current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). */ public function current_time() { return \time(); } /** * Check if a string is a valid datetime. * * @param string $datetime String input to check as valid input for DateTime class. * * @return bool True when datatime is valid. */ public function is_valid_datetime( $datetime ) { if ( \substr( $datetime, 0, 1 ) === '-' ) { return false; } try { return new DateTime( $datetime ) !== false; } catch ( Exception $exception ) { return false; } } } environment-helper.php 0000644 00000001124 15154553720 0011103 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for site environment. */ class Environment_Helper { /** * Determines if the site is running on production. * * @return bool True if WordPress is currently running on production, false for all other environments. */ public function is_production_mode() { return $this->get_wp_environment() === 'production'; } /** * Determines on which environment WordPress is running. * * @return string The current WordPress environment. */ public function get_wp_environment() { return \wp_get_environment_type(); } } taxonomy-helper.php 0000644 00000006045 15154553720 0010424 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WP_Taxonomy; use WP_Term; use WPSEO_Taxonomy_Meta; /** * A helper object for terms. */ class Taxonomy_Helper { /** * The options helper. * * @var Options_Helper */ private $options; /** * The string helper. * * @var String_Helper */ private $string; /** * Taxonomy_Helper constructor. * * @codeCoverageIgnore It only sets dependencies. * * @param Options_Helper $options The options helper. * @param String_Helper $string The string helper. */ public function __construct( Options_Helper $options, String_Helper $string ) { $this->options = $options; $this->string = $string; } /** * Checks if the requested term is indexable. * * @param string $taxonomy The taxonomy slug. * * @return bool True when taxonomy is set to index. */ public function is_indexable( $taxonomy ) { return ! $this->options->get( 'noindex-tax-' . $taxonomy, false ); } /** * Returns an array with the public taxonomies. * * @param string $output The output type to use. * * @return string[]|WP_Taxonomy[] Array with all the public taxonomies. * The type depends on the specified output variable. */ public function get_public_taxonomies( $output = 'names' ) { return \get_taxonomies( [ 'public' => true ], $output ); } /** * Retrieves the term description (without tags). * * @param int $term_id Term ID. * * @return string Term description (without tags). */ public function get_term_description( $term_id ) { return $this->string->strip_all_tags( \term_description( $term_id ) ); } /** * Retrieves the taxonomy term's meta values. * * @codeCoverageIgnore We have to write test when this method contains own code. * * @param WP_Term $term Term to get the meta value for. * * @return array|bool Array of all the meta data for the term. * False if the term does not exist or the $meta provided is invalid. */ public function get_term_meta( $term ) { return WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, null ); } /** * Gets the passed taxonomy's slug. * * @param string $taxonomy The name of the taxonomy. * * @return string The slug for the taxonomy. Returns the taxonomy's name if no slug could be found. */ public function get_taxonomy_slug( $taxonomy ) { $taxonomy_object = \get_taxonomy( $taxonomy ); if ( $taxonomy_object && \property_exists( $taxonomy_object, 'rewrite' ) && \is_array( $taxonomy_object->rewrite ) && isset( $taxonomy_object->rewrite['slug'] ) ) { return $taxonomy_object->rewrite['slug']; } return \strtolower( $taxonomy_object->name ); } /** * Returns an array with the custom taxonomies. * * @param string $output The output type to use. * * @return string[]|WP_Taxonomy[] Array with all the custom taxonomies. * The type depends on the specified output variable. */ public function get_custom_taxonomies( $output = 'names' ) { return \get_taxonomies( [ '_builtin' => false ], $output ); } } indexing-helper.php 0000644 00000022363 15154553720 0010354 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\SEO\Actions\Indexing\Indexable_General_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Type_Archive_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexable_Term_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexation_Action_Interface; use Yoast\WP\SEO\Actions\Indexing\Limited_Indexing_Action_Interface; use Yoast\WP\SEO\Actions\Indexing\Post_Link_Indexing_Action; use Yoast\WP\SEO\Actions\Indexing\Term_Link_Indexing_Action; use Yoast\WP\SEO\Config\Indexing_Reasons; use Yoast\WP\SEO\Integrations\Admin\Indexing_Notification_Integration; use Yoast_Notification_Center; /** * A helper object for indexing. */ class Indexing_Helper { /** * The options helper. * * @var Options_Helper */ protected $options_helper; /** * The date helper. * * @var Date_Helper */ protected $date_helper; /** * The notification center. * * @var Yoast_Notification_Center */ protected $notification_center; /** * The indexation actions. * * @var Indexation_Action_Interface[]|Limited_Indexing_Action_Interface[] */ protected $indexing_actions; /** * Indexing_Helper constructor. * * @param Options_Helper $options_helper The options helper. * @param Date_Helper $date_helper The date helper. * @param Yoast_Notification_Center $notification_center The notification center. */ public function __construct( Options_Helper $options_helper, Date_Helper $date_helper, Yoast_Notification_Center $notification_center ) { $this->options_helper = $options_helper; $this->date_helper = $date_helper; $this->notification_center = $notification_center; } /** * Sets the actions. * * @required * * @param Indexable_Post_Indexation_Action $post_indexation The post indexing action. * @param Indexable_Term_Indexation_Action $term_indexation The term indexing action. * @param Indexable_Post_Type_Archive_Indexation_Action $post_type_archive_indexation The posttype indexing action. * @param Indexable_General_Indexation_Action $general_indexation The general indexing (homepage etc) action. * @param Post_Link_Indexing_Action $post_link_indexing_action The post crosslink indexing action. * @param Term_Link_Indexing_Action $term_link_indexing_action The term crossling indexing action. */ public function set_indexing_actions( Indexable_Post_Indexation_Action $post_indexation, Indexable_Term_Indexation_Action $term_indexation, Indexable_Post_Type_Archive_Indexation_Action $post_type_archive_indexation, Indexable_General_Indexation_Action $general_indexation, Post_Link_Indexing_Action $post_link_indexing_action, Term_Link_Indexing_Action $term_link_indexing_action ) { $this->indexing_actions = [ $post_indexation, $term_indexation, $post_type_archive_indexation, $general_indexation, $post_link_indexing_action, $term_link_indexing_action, ]; } /** * Sets several database options when the indexing process is started. * * @deprecated 17.4 This method was renamed to prepare for internal consistency. * @codeCoverageIgnore * * @return void */ public function start() { $this->prepare(); } /** * Prepares the indexing process by setting several database options and removing the indexing notification. * * @return void */ public function prepare() { $this->set_first_time( false ); $this->set_started( $this->date_helper->current_time() ); $this->remove_indexing_notification(); // Do not set_reason here; if the process is cancelled, the reason to start indexing is still valid. } /** * Sets several database options when the indexing process is finished. * * @deprecated 17.4 This method was renamed to complete for internal consistency. * @codeCoverageIgnore * * @return void */ public function finish() { $this->complete(); } /** * Sets several database options when the indexing process is finished. * * @return void */ public function complete() { $this->set_reason( '' ); $this->set_started( null ); } /** * Sets appropriate flags when the indexing process fails. * * @return void */ public function indexing_failed() { $this->set_reason( Indexing_Reasons::REASON_INDEXING_FAILED ); $this->set_started( null ); } /** * Sets the indexing reason. * * @param string $reason The indexing reason. * * @return void */ public function set_reason( $reason ) { $this->options_helper->set( 'indexing_reason', $reason ); $this->remove_indexing_notification(); } /** * Removes any pre-existing notification, so that a new notification (with a possible new reason) can be added. */ protected function remove_indexing_notification() { $this->notification_center->remove_notification_by_id( Indexing_Notification_Integration::NOTIFICATION_ID ); } /** * Determines whether an indexing reason has been set in the options. * * @return bool Whether an indexing reason has been set in the options. */ public function has_reason() { $reason = $this->get_reason(); return ! empty( $reason ); } /** * Returns the indexing reason. The reason why the site-wide indexing process should be run. * * @return string The indexing reason, defaults to the empty string if no reason has been set. */ public function get_reason() { return $this->options_helper->get( 'indexing_reason', '' ); } /** * Sets the start time when the indexing process has started but not completed. * * @param int|bool $timestamp The start time when the indexing process has started but not completed, false otherwise. * * @return void */ public function set_started( $timestamp ) { $this->options_helper->set( 'indexing_started', $timestamp ); } /** * Gets the start time when the indexing process has started but not completed. * * @return int|bool The start time when the indexing process has started but not completed, false otherwise. */ public function get_started() { return $this->options_helper->get( 'indexing_started' ); } /** * Sets a boolean that indicates whether or not a site still has to be indexed for the first time. * * @param bool $is_first_time_indexing Whether or not a site still has to be indexed for the first time. * * @return void */ public function set_first_time( $is_first_time_indexing ) { $this->options_helper->set( 'indexing_first_time', $is_first_time_indexing ); } /** * Gets a boolean that indicates whether or not the site still has to be indexed for the first time. * * @return bool Whether the site still has to be indexed for the first time. */ public function is_initial_indexing() { return $this->options_helper->get( 'indexing_first_time', true ); } /** * Returns the total number of unindexed objects. * * @return int The total number of unindexed objects. */ public function get_unindexed_count() { $unindexed_count = 0; foreach ( $this->indexing_actions as $indexing_action ) { $unindexed_count += $indexing_action->get_total_unindexed(); } return $unindexed_count; } /** * Returns the total number of unindexed objects and applies a filter for third party integrations. * * @return int The total number of unindexed objects. */ public function get_filtered_unindexed_count() { $unindexed_count = $this->get_unindexed_count(); /** * Filter: 'wpseo_indexing_get_unindexed_count' - Allow changing the amount of unindexed objects. * * @param int $unindexed_count The amount of unindexed objects. */ return \apply_filters( 'wpseo_indexing_get_unindexed_count', $unindexed_count ); } /** * Returns a limited number of unindexed objects. * * @param int $limit Limit the number of unindexed objects that are counted. * * @return int The total number of unindexed objects. */ public function get_limited_unindexed_count( $limit ) { $unindexed_count = 0; foreach ( $this->indexing_actions as $indexing_action ) { $unindexed_count += $indexing_action->get_limited_unindexed_count( $limit - $unindexed_count + 1 ); if ( $unindexed_count > $limit ) { return $unindexed_count; } } return $unindexed_count; } /** * Returns the total number of unindexed objects and applies a filter for third party integrations. * * @param int $limit Limit the number of unindexed objects that are counted. * * @return int The total number of unindexed objects. */ public function get_limited_filtered_unindexed_count( $limit ) { $unindexed_count = $this->get_limited_unindexed_count( $limit ); if ( $unindexed_count > $limit ) { return $unindexed_count; } /** * Filter: 'wpseo_indexing_get_limited_unindexed_count' - Allow changing the amount of unindexed objects, * and allow for a maximum number of items counted to improve performance. * * @param int $unindexed_count The amount of unindexed objects. * @param int|false $limit Limit the number of unindexed objects that need to be counted. * False if it doesn't need to be limited. */ return \apply_filters( 'wpseo_indexing_get_limited_unindexed_count', $unindexed_count, $limit ); } } author-archive-helper.php 0000644 00000006713 15154553720 0011471 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\Lib\Model; /** * A helper object for author archives. */ class Author_Archive_Helper { /** * Gets the array of post types that are shown on an author's archive. * * @return array The post types that are shown on an author's archive. */ public function get_author_archive_post_types() { /** * Filters the array of post types that are shown on an author's archive. * * @param array $args The post types that are shown on an author archive. */ return \apply_filters( 'wpseo_author_archive_post_types', [ 'post' ] ); } /** * Returns whether the author has at least one public post. * * @param int $author_id The author ID. * * @return bool|null Whether the author has at least one public post. */ public function author_has_public_posts( $author_id ) { // First check if the author has at least one public post. $has_public_post = $this->author_has_a_public_post( $author_id ); if ( $has_public_post ) { return true; } // Then check if the author has at least one post where the status is the same as the global setting. $has_public_post_depending_on_the_global_setting = $this->author_has_a_post_with_is_public_null( $author_id ); if ( $has_public_post_depending_on_the_global_setting ) { return null; } return false; } /** * Returns whether the author has at least one public post. * * @codeCoverageIgnore It looks for the first ID through the ORM and converts it to a boolean. * * @param int $author_id The author ID. * * @return bool Whether the author has at least one public post. */ protected function author_has_a_public_post( $author_id ) { $cache_key = 'author_has_a_public_post_' . $author_id; $indexable_exists = \wp_cache_get( $cache_key ); if ( $indexable_exists === false ) { $indexable_exists = Model::of_type( 'Indexable' ) ->select( 'id' ) ->where( 'object_type', 'post' ) ->where_in( 'object_sub_type', $this->get_author_archive_post_types() ) ->where( 'author_id', $author_id ) ->where( 'is_public', 1 ) ->find_one(); if ( $indexable_exists === false ) { // Cache no results to prevent full table scanning on authors with no public posts. \wp_cache_set( $cache_key, 0, '', \wp_rand( ( 2 * \HOUR_IN_SECONDS ), ( 4 * \HOUR_IN_SECONDS ) ) ); } } return (bool) $indexable_exists; } /** * Returns whether the author has at least one post with the is public null. * * @codeCoverageIgnore It looks for the first ID through the ORM and converts it to a boolean. * * @param int $author_id The author ID. * * @return bool Whether the author has at least one post with the is public null. */ protected function author_has_a_post_with_is_public_null( $author_id ) { $cache_key = 'author_has_a_post_with_is_public_null_' . $author_id; $indexable_exists = \wp_cache_get( $cache_key ); if ( $indexable_exists === false ) { $indexable_exists = Model::of_type( 'Indexable' ) ->select( 'id' ) ->where( 'object_type', 'post' ) ->where_in( 'object_sub_type', $this->get_author_archive_post_types() ) ->where( 'author_id', $author_id ) ->where_null( 'is_public' ) ->find_one(); if ( $indexable_exists === false ) { // Cache no results to prevent full table scanning on authors with no is public null posts. \wp_cache_set( $cache_key, 0, '', \wp_rand( ( 2 * \HOUR_IN_SECONDS ), ( 4 * \HOUR_IN_SECONDS ) ) ); } } return (bool) $indexable_exists; } } image-helper.php 0000644 00000023767 15154553720 0007642 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WPSEO_Image_Utils; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * A helper object for images. */ class Image_Helper { /** * Image types that are supported by Open Graph. * * @var array */ protected static $valid_image_types = [ 'image/jpeg', 'image/gif', 'image/png' ]; /** * Image extensions that are supported by Open Graph. * * @var array */ protected static $valid_image_extensions = [ 'jpeg', 'jpg', 'gif', 'png' ]; /** * Represents the indexables repository. * * @var Indexable_Repository */ protected $indexable_repository; /** * The options helper. * * @var Options_Helper */ private $options; /** * Image_Helper constructor. * * @param Indexable_Repository $indexable_repository The indexable repository. * @param Options_Helper $options The options helper. */ public function __construct( Indexable_Repository $indexable_repository, Options_Helper $options ) { $this->indexable_repository = $indexable_repository; $this->options = $options; } /** * Determines whether or not the wanted attachment is considered valid. * * @param int $attachment_id The attachment ID to get the attachment by. * * @return bool Whether or not the attachment is valid. */ public function is_valid_attachment( $attachment_id ) { if ( ! \wp_attachment_is_image( $attachment_id ) ) { return false; } $post_mime_type = \get_post_mime_type( $attachment_id ); if ( $post_mime_type === false ) { return false; } return $this->is_valid_image_type( $post_mime_type ); } /** * Checks if the given extension is a valid extension * * @param string $image_extension The image extension. * * @return bool True when valid. */ public function is_extension_valid( $image_extension ) { return \in_array( $image_extension, static::$valid_image_extensions, true ); } /** * Determines whether the passed mime type is a valid image type. * * @param string $mime_type The detected mime type. * * @return bool Whether or not the attachment is a valid image type. */ public function is_valid_image_type( $mime_type ) { return \in_array( $mime_type, static::$valid_image_types, true ); } /** * Retrieves the image source for an attachment. * * @param int $attachment_id The attachment. * @param string $image_size The image size to retrieve. * * @return string The image url or an empty string when not found. */ public function get_attachment_image_source( $attachment_id, $image_size = 'full' ) { $attachment = \wp_get_attachment_image_src( $attachment_id, $image_size ); if ( ! $attachment ) { return ''; } return $attachment[0]; } /** * Retrieves the ID of the featured image. * * @param int $post_id The post id to get featured image id for. * * @return int|bool ID when found, false when not. */ public function get_featured_image_id( $post_id ) { if ( ! \has_post_thumbnail( $post_id ) ) { return false; } return \get_post_thumbnail_id( $post_id ); } /** * Gets the image url from the content. * * @param int $post_id The post id to extract the images from. * * @return string The image url or an empty string when not found. */ public function get_post_content_image( $post_id ) { $image_url = $this->get_first_usable_content_image_for_post( $post_id ); if ( $image_url === null ) { return ''; } return $image_url; } /** * Gets the first image url of a gallery. * * @param int $post_id Post ID to use. * * @return string The image url or an empty string when not found. */ public function get_gallery_image( $post_id ) { $post = \get_post( $post_id ); if ( \strpos( $post->post_content, '[gallery' ) === false ) { return ''; } $images = \get_post_gallery_images( $post ); if ( empty( $images ) ) { return ''; } return \reset( $images ); } /** * Gets the image url from the term content. * * @param int $term_id The term id to extract the images from. * * @return string The image url or an empty string when not found. */ public function get_term_content_image( $term_id ) { $image_url = $this->get_first_content_image_for_term( $term_id ); if ( $image_url === null ) { return ''; } return $image_url; } /** * Retrieves the caption for an attachment. * * @param int $attachment_id Attachment ID. * * @return string The caption when found, empty string when no caption is found. */ public function get_caption( $attachment_id ) { $caption = \wp_get_attachment_caption( $attachment_id ); if ( ! empty( $caption ) ) { return $caption; } $caption = \get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( ! empty( $caption ) ) { return $caption; } return ''; } /** * Retrieves the attachment metadata. * * @param int $attachment_id Attachment ID. * * @return array The metadata, empty array when no metadata is found. */ public function get_metadata( $attachment_id ) { $metadata = \wp_get_attachment_metadata( $attachment_id ); if ( ! $metadata || ! \is_array( $metadata ) ) { return []; } return $metadata; } /** * Retrieves the attachment image url. * * @param int $attachment_id Attachment ID. * @param string $size The size to get. * * @return string The url when found, empty string otherwise. */ public function get_attachment_image_url( $attachment_id, $size ) { $url = \wp_get_attachment_image_url( $attachment_id, $size ); if ( ! $url ) { return ''; } return $url; } /** * Find the right version of an image based on size. * * @codeCoverageIgnore - We have to write test when this method contains own code. * * @param int $attachment_id Attachment ID. * @param string $size Size name. * * @return array|false Returns an array with image data on success, false on failure. */ public function get_image( $attachment_id, $size ) { return WPSEO_Image_Utils::get_image( $attachment_id, $size ); } /** * Retrieves the best attachment variation for the given attachment. * * @codeCoverageIgnore - We have to write test when this method contains own code. * * @param int $attachment_id The attachment id. * * @return bool|string The attachment url or false when no variations found. */ public function get_best_attachment_variation( $attachment_id ) { $variations = WPSEO_Image_Utils::get_variations( $attachment_id ); $variations = WPSEO_Image_Utils::filter_usable_file_size( $variations ); // If we are left without variations, there is no valid variation for this attachment. if ( empty( $variations ) ) { return false; } // The variations are ordered so the first variations is by definition the best one. return \reset( $variations ); } /** * Find an attachment ID for a given URL. * * @param string $url The URL to find the attachment for. * * @return int The found attachment ID, or 0 if none was found. */ public function get_attachment_by_url( $url ) { // Strip out the size part of an image URL. $url = \preg_replace( '/(.*)-\d+x\d+\.(jpeg|jpg|png|gif)$/', '$1.$2', $url ); // Don't try to do this for external URLs. if ( \strpos( $url, \get_site_url() ) !== 0 ) { return 0; } $indexable = $this->indexable_repository->find_by_permalink( $url ); if ( $indexable && $indexable->object_type === 'post' && $indexable->object_sub_type === 'attachment' ) { return $indexable->object_id; } $post_id = WPSEO_Image_Utils::get_attachment_by_url( $url ); if ( $post_id !== 0 ) { // Find the indexable, this triggers creating it so it can be found next time. $this->indexable_repository->find_by_id_and_type( $post_id, 'post' ); } return $post_id; } /** * Retrieves an attachment ID for an image uploaded in the settings. * * Due to self::get_attachment_by_url returning 0 instead of false. * 0 is also a possibility when no ID is available. * * @codeCoverageIgnore - We have to write test when this method contains own code. * * @param string $setting The setting the image is stored in. * * @return int|bool The attachment id, or false or 0 if no ID is available. */ public function get_attachment_id_from_settings( $setting ) { return WPSEO_Image_Utils::get_attachment_id_from_settings( $setting ); } /** * Based on and image ID return array with the best variation of that image. If it's not saved to the DB, save it to an option. * * @param string $setting The setting name. Should be company or person. * * @return array|bool Array with image details when the image is found, boolean when it's not found. */ public function get_attachment_meta_from_settings( $setting ) { $image_meta = $this->options->get( $setting . '_meta', false ); if ( ! $image_meta ) { $image_id = $this->options->get( $setting . '_id', false ); if ( $image_id ) { // There is not an option to put a URL in an image field in the settings anymore, only to upload it through the media manager. // This means an attachment always exists, so doing this is only needed once. $image_meta = $this->get_best_attachment_variation( $image_id ); if ( $image_meta ) { $this->options->set( $setting . '_meta', $image_meta ); } } } return $image_meta; } /** * Retrieves the first usable content image for a post. * * @codeCoverageIgnore - We have to write test when this method contains own code. * * @param int $post_id The post id to extract the images from. * * @return string|null */ protected function get_first_usable_content_image_for_post( $post_id ) { return WPSEO_Image_Utils::get_first_usable_content_image_for_post( $post_id ); } /** * Gets the term's first usable content image. Null if none is available. * * @codeCoverageIgnore - We have to write test when this method contains own code. * * @param int $term_id The term id. * * @return string|null The image URL. */ protected function get_first_content_image_for_term( $term_id ) { return WPSEO_Image_Utils::get_first_content_image_for_term( $term_id ); } } string-helper.php 0000644 00000002322 15154553720 0010046 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for string operations. */ class String_Helper { /** * Strips all HTML tags including script and style. * * @param string $string The string to strip the tags from. * * @return string The processed string. */ public function strip_all_tags( $string ) { return \wp_strip_all_tags( $string ); } /** * Standardize whitespace in a string. * * Replace line breaks, carriage returns, tabs with a space, then remove double spaces. * * @param string $string String input to standardize. * * @return string */ public function standardize_whitespace( $string ) { return \trim( \str_replace( ' ', ' ', \str_replace( [ "\t", "\n", "\r", "\f" ], ' ', $string ) ) ); } /** * First strip out registered and enclosing shortcodes using native WordPress strip_shortcodes function. * Then strip out the shortcodes with a filthy regex, because people don't properly register their shortcodes. * * @param string $text Input string that might contain shortcodes. * * @return string String without shortcodes. */ public function strip_shortcode( $text ) { return \preg_replace( '`\[[^\]]+\]`s', '', \strip_shortcodes( $text ) ); } } indexable-helper.php 0000644 00000011141 15154553720 0010472 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexable_Post_Type_Archive_Indexation_Action; use Yoast\WP\SEO\Actions\Indexing\Indexable_Term_Indexation_Action; use Yoast\WP\SEO\Config\Indexing_Reasons; use Yoast\WP\SEO\Models\Indexable; use Yoast\WP\SEO\Repositories\Indexable_Repository; /** * A helper object for indexables. */ class Indexable_Helper { /** * Represents the indexable repository. * * @var Indexable_Repository */ protected $repository; /** * Represents the options helper. * * @var Options_Helper */ protected $options_helper; /** * Represents the environment helper. * * @var Environment_Helper */ protected $environment_helper; /** * Represents the indexing helper. * * @var Indexing_Helper */ protected $indexing_helper; /** * Indexable_Helper constructor. * * @param Options_Helper $options_helper The options helper. * @param Environment_Helper $environment_helper The environment helper. * @param Indexing_Helper $indexing_helper The indexing helper. */ public function __construct( Options_Helper $options_helper, Environment_Helper $environment_helper, Indexing_Helper $indexing_helper ) { $this->options_helper = $options_helper; $this->environment_helper = $environment_helper; $this->indexing_helper = $indexing_helper; } /** * Sets the indexable repository. Done to avoid circular dependencies. * * @required * * @param Indexable_Repository $repository The indexable repository. */ public function set_indexable_repository( Indexable_Repository $repository ) { $this->repository = $repository; } /** * Returns the page type of an indexable. * * @param Indexable $indexable The indexable. * * @return string|false The page type. False if it could not be determined. */ public function get_page_type_for_indexable( $indexable ) { switch ( $indexable->object_type ) { case 'post': $front_page_id = (int) \get_option( 'page_on_front' ); if ( $indexable->object_id === $front_page_id ) { return 'Static_Home_Page'; } $posts_page_id = (int) \get_option( 'page_for_posts' ); if ( $indexable->object_id === $posts_page_id ) { return 'Static_Posts_Page'; } return 'Post_Type'; case 'term': return 'Term_Archive'; case 'user': return 'Author_Archive'; case 'home-page': return 'Home_Page'; case 'post-type-archive': return 'Post_Type_Archive'; case 'date-archive': return 'Date_Archive'; case 'system-page': if ( $indexable->object_sub_type === 'search-result' ) { return 'Search_Result_Page'; } if ( $indexable->object_sub_type === '404' ) { return 'Error_Page'; } } return false; } /** * Resets the permalinks of the indexables. * * @param string|null $type The type of the indexable. * @param string|null $subtype The subtype. Can be null. * @param string $reason The reason that the permalink has been changed. */ public function reset_permalink_indexables( $type = null, $subtype = null, $reason = Indexing_Reasons::REASON_PERMALINK_SETTINGS ) { $result = $this->repository->reset_permalink( $type, $subtype ); $this->indexing_helper->set_reason( $reason ); if ( $result !== false && $result > 0 ) { \delete_transient( Indexable_Post_Indexation_Action::UNINDEXED_COUNT_TRANSIENT ); \delete_transient( Indexable_Post_Type_Archive_Indexation_Action::UNINDEXED_COUNT_TRANSIENT ); \delete_transient( Indexable_Term_Indexation_Action::UNINDEXED_COUNT_TRANSIENT ); } } /** * Determines whether indexing indexables is appropriate at this time. * * @return bool Whether or not the indexables should be indexed. */ public function should_index_indexables() { // Currently the only reason to index is when we're on a production website. return $this->environment_helper->is_production_mode(); } /** * Returns whether or not dynamic permalinks should be used. * * @return bool Whether or not the dynamic permalinks should be used. */ public function dynamic_permalinks_enabled() { /** * Filters the value of the `dynamic_permalinks` option. * * @param bool $value The value of the `dynamic_permalinks` option. */ return (bool) \apply_filters( 'wpseo_dynamic_permalinks_enabled', $this->options_helper->get( 'dynamic_permalinks', false ) ); } /** * Sets a boolean to indicate that the indexing of the indexables has completed. * * @return void */ public function finish_indexing() { $this->options_helper->set( 'indexables_indexing_completed', true ); } } twitter/image-helper.php 0000644 00000002200 15154553720 0011317 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers\Twitter; use Yoast\WP\SEO\Helpers\Image_Helper as Base_Image_Helper; /** * A helper object for Twitter images. */ class Image_Helper { /** * The base image helper. * * @var Base_Image_Helper */ private $image; /** * Image_Helper constructor. * * @codeCoverageIgnore * * @param Base_Image_Helper $image The image helper. */ public function __construct( Base_Image_Helper $image ) { $this->image = $image; } /** * The image size to use for Twitter. * * @return string Image size string. */ public function get_image_size() { /** * Filter: 'wpseo_twitter_image_size' - Allow changing the Twitter Card image size. * * @api string $featured_img Image size string. */ return (string) \apply_filters( 'wpseo_twitter_image_size', 'full' ); } /** * Retrieves an image url by its id. * * @codeCoverageIgnore It is a wrapper method. * * @param int $image_id The image id. * * @return string The image url. */ public function get_by_id( $image_id ) { return $this->image->get_attachment_image_source( $image_id, $this->get_image_size() ); } } url-helper.php 0000644 00000013556 15154553720 0007355 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use Yoast\WP\SEO\Models\SEO_Links; /** * A helper object for URLs. */ class Url_Helper { /** * Retrieve home URL with proper trailing slash. * * @param string $path Path relative to home URL. * @param string|null $scheme Scheme to apply. * * @return string Home URL with optional path, appropriately slashed if not. */ public function home( $path = '', $scheme = null ) { $home_url = \home_url( $path, $scheme ); if ( ! empty( $path ) ) { return $home_url; } $home_path = \wp_parse_url( $home_url, \PHP_URL_PATH ); if ( $home_path === '/' ) { // Home at site root, already slashed. return $home_url; } if ( \is_null( $home_path ) ) { // Home at site root, always slash. return \trailingslashit( $home_url ); } if ( \is_string( $home_path ) ) { // Home in subdirectory, slash if permalink structure has slash. return \user_trailingslashit( $home_url ); } return $home_url; } /** * Determines whether the plugin is active for the entire network. * * @return bool Whether or not the plugin is network-active. */ public function is_plugin_network_active() { static $network_active = null; if ( ! \is_multisite() ) { return false; } // If a cached result is available, bail early. if ( $network_active !== null ) { return $network_active; } $network_active_plugins = \wp_get_active_network_plugins(); // Consider MU plugins and network-activated plugins as network-active. $network_active = \strpos( \wp_normalize_path( \WPSEO_FILE ), \wp_normalize_path( \WPMU_PLUGIN_DIR ) ) === 0 || \in_array( \WP_PLUGIN_DIR . '/' . \WPSEO_BASENAME, $network_active_plugins, true ); return $network_active; } /** * Retrieve network home URL if plugin is network-activated, or home url otherwise. * * @return string Home URL with optional path, appropriately slashed if not. */ public function network_safe_home_url() { /** * Action: 'wpseo_home_url' - Allows overriding of the home URL. */ \do_action( 'wpseo_home_url' ); // If the plugin is network-activated, use the network home URL. if ( self::is_plugin_network_active() ) { return \network_home_url(); } return \home_url(); } /** * Check whether a url is relative. * * @param string $url URL string to check. * * @return bool True when url is relative. */ public function is_relative( $url ) { return ( \strpos( $url, 'http' ) !== 0 && \strpos( $url, '//' ) !== 0 ); } /** * Gets the path from the passed URL. * * @codeCoverageIgnore It only wraps a WordPress function. * * @param string $url The URL to get the path from. * * @return string The path of the URL. Returns an empty string if URL parsing fails. */ public function get_url_path( $url ) { return (string) \wp_parse_url( $url, \PHP_URL_PATH ); } /** * Determines the file extension of the given url. * * @param string $url The URL. * * @return string The extension. */ public function get_extension_from_url( $url ) { $path = $this->get_url_path( $url ); if ( $path === '' ) { return ''; } $parts = \explode( '.', $path ); if ( empty( $parts ) || \count( $parts ) === 1 ) { return ''; } return \end( $parts ); } /** * Ensures that the given url is an absolute url. * * @param string $url The url that needs to be absolute. * * @return string The absolute url. */ public function ensure_absolute_url( $url ) { if ( ! \is_string( $url ) || $url === '' ) { return $url; } if ( $this->is_relative( $url ) === true ) { return $this->build_absolute_url( $url ); } return $url; } /** * Parse the home URL setting to find the base URL for relative URLs. * * @param string|null $path Optional path string. * * @return string */ public function build_absolute_url( $path = null ) { $path = \wp_parse_url( $path, \PHP_URL_PATH ); $url_parts = \wp_parse_url( \home_url() ); $base_url = \trailingslashit( $url_parts['scheme'] . '://' . $url_parts['host'] ); if ( ! \is_null( $path ) ) { $base_url .= \ltrim( $path, '/' ); } return $base_url; } /** * Returns the link type. * * @param array $url The URL, as parsed by wp_parse_url. * @param array|null $home_url Optional. The home URL, as parsed by wp_parse_url. Used to avoid reparsing the home_url. * @param bool $is_image Whether or not the link is an image. * * @return string The link type. */ public function get_link_type( $url, $home_url = null, $is_image = false ) { // If there is no scheme and no host the link is always internal. // Beware, checking just the scheme isn't enough as a link can be //yoast.com for instance. if ( empty( $url['scheme'] ) && empty( $url['host'] ) ) { return ( $is_image ) ? SEO_Links::TYPE_INTERNAL_IMAGE : SEO_Links::TYPE_INTERNAL; } // If there is a scheme but it's not http(s) then the link is always external. if ( \array_key_exists( 'scheme', $url ) && ! \in_array( $url['scheme'], [ 'http', 'https' ], true ) ) { return ( $is_image ) ? SEO_Links::TYPE_EXTERNAL_IMAGE : SEO_Links::TYPE_EXTERNAL; } if ( \is_null( $home_url ) ) { $home_url = \wp_parse_url( \home_url() ); } // When the base host is equal to the host. if ( isset( $url['host'] ) && $url['host'] !== $home_url['host'] ) { return ( $is_image ) ? SEO_Links::TYPE_EXTERNAL_IMAGE : SEO_Links::TYPE_EXTERNAL; } // There is no base path and thus all URLs of the same domain are internal. if ( empty( $home_url['path'] ) ) { return ( $is_image ) ? SEO_Links::TYPE_INTERNAL_IMAGE : SEO_Links::TYPE_INTERNAL; } // When there is a path and it matches the start of the url. if ( isset( $url['path'] ) && \strpos( $url['path'], $home_url['path'] ) === 0 ) { return ( $is_image ) ? SEO_Links::TYPE_INTERNAL_IMAGE : SEO_Links::TYPE_INTERNAL; } return ( $is_image ) ? SEO_Links::TYPE_EXTERNAL_IMAGE : SEO_Links::TYPE_EXTERNAL; } } wordpress-helper.php 0000644 00000001000 15154553720 0010560 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; // phpcs:disable WordPress.WP.CapitalPDangit.MisspelledClassName -- It is spelled like `Wordpress_Helper` because of Yoast's naming conventions for classes, which would otherwise break dependency injection in some cases. /** * A helper object for WordPress matters. */ class Wordpress_Helper { /** * Returns the WordPress version. * * @return string The version. */ public function get_wordpress_version() { global $wp_version; return $wp_version; } } request-helper.php 0000644 00000000540 15154553720 0010230 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the request state. */ class Request_Helper { /** * Checks if the current request is a REST request. * * @return bool True when the current request is a REST request. */ public function is_rest_request() { return \defined( 'REST_REQUEST' ) && \REST_REQUEST === true; } } user-helper.php 0000644 00000007263 15154553720 0007527 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for the user. */ class User_Helper { /** * Retrieves user meta field for a user. * * @param int $user_id User ID. * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys. * @param bool $single Whether to return a single value. * * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true. */ public function get_meta( $user_id, $key = '', $single = false ) { return \get_user_meta( $user_id, $key, $single ); } /** * Counts the number of posts the user has written in this post type. * * @param int $user_id User ID. * @param array|string $post_type Optional. Single post type or array of post types to count the number of posts * for. Default 'post'. * * @return int The number of posts the user has written in this post type. */ public function count_posts( $user_id, $post_type = 'post' ) { return (int) \count_user_posts( $user_id, $post_type, true ); } /** * Retrieves the requested data of the author. * * @param string $field The user field to retrieve. * @param int|false $user_id User ID. * * @return string The author's field from the current author's DB object. */ public function get_the_author_meta( $field, $user_id ) { return \get_the_author_meta( $field, $user_id ); } /** * Retrieves the archive url of the user. * * @param int|false $user_id User ID. * * @return string The author's archive url. */ public function get_the_author_posts_url( $user_id ) { return \get_author_posts_url( $user_id ); } /** * Retrieves the current user ID. * * @return int The current user's ID, or 0 if no user is logged in. */ public function get_current_user_id() { return \get_current_user_id(); } /** * Updates user meta field for a user. * * Use the $prev_value parameter to differentiate between meta fields with the * same key and user ID. * * If the meta field for the user does not exist, it will be added. * * @param int $user_id User ID. * @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 updating. * If specified, only update existing metadata entries with * this value. Otherwise, update all entries. Default empty. * * @return int|bool Meta ID if the key didn't exist, true on successful update, * false on failure or if the value passed to the function * is the same as the one that is already in the database. */ public function update_meta( $user_id, $meta_key, $meta_value, $prev_value = '' ) { return \update_user_meta( $user_id, $meta_key, $meta_value, $prev_value ); } /** * Removes metadata matching criteria from a user. * * You can match based on the key, or key and value. Removing based on key and * value, will keep from removing duplicate metadata with the same key. It also * allows removing all metadata matching key, if needed. * * @param int $user_id User ID. * @param string $meta_key Metadata name. * @param mixed $meta_value Optional. Metadata value. If provided, * rows will only be removed that match the value. * Must be serializable if non-scalar. Default empty. * * @return bool True on success, false on failure. */ public function delete_meta( $user_id, $meta_key, $meta_value = '' ) { return \delete_user_meta( $user_id, $meta_key, $meta_value ); } } asset-helper.php 0000644 00000005024 15154553720 0007661 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * A helper object for author archives. */ class Asset_Helper { /** * Recursively retrieves all dependency urls of a given handle. * * @param string $handle The handle. * * @return string[] All dependency urls of the given handle. */ public function get_dependency_urls_by_handle( $handle ) { $urls = []; foreach ( $this->get_dependency_handles( $handle ) as $other_handle ) { $urls[ $other_handle ] = $this->get_asset_url( $other_handle ); } return $urls; } /** * Recursively retrieves all dependencies of a given handle. * * @param string $handle The handle. * * @return string[]|bool All dependencies of the given handle. */ public function get_dependency_handles( $handle ) { $scripts = \wp_scripts(); if ( ! isset( $scripts->registered[ $handle ] ) ) { return false; } $obj = $scripts->registered[ $handle ]; $deps = $obj->deps; foreach ( $obj->deps as $other_handle ) { $nested_deps = $this->get_dependency_handles( $other_handle ); if ( ! $nested_deps ) { continue; } // Place nested dependencies before primary dependencies, they need to be loaded first. $deps = \array_merge( $nested_deps, $deps ); } // Array unique keeps the first of each element so dependencies will be as early as they're required. return \array_values( \array_unique( $deps ) ); } /** * Gets the URL of a given asset. * * This logic is copied from WP_Scripts::do_item as unfortunately that logic is not properly isolated. * * @param string $handle The handle of the asset. * * @return string|false The URL of the asset or false if the asset does not exist. */ public function get_asset_url( $handle ) { $scripts = \wp_scripts(); if ( ! isset( $scripts->registered[ $handle ] ) ) { return false; } $obj = $scripts->registered[ $handle ]; if ( $obj->ver === null ) { $ver = ''; } else { $ver = ( $obj->ver ) ? $obj->ver : $scripts->default_version; } if ( isset( $scripts->args[ $handle ] ) ) { $ver = ( $ver ) ? $ver . '&' . $scripts->args[ $handle ] : $scripts->args[ $handle ]; } $src = $obj->src; if ( ! \preg_match( '|^(https?:)?//|', $src ) && ! ( $scripts->content_url && \strpos( $src, $scripts->content_url ) === 0 ) ) { $src = $scripts->base_url . $src; } if ( ! empty( $ver ) ) { $src = \add_query_arg( 'ver', $ver, $src ); } /** This filter is documented in wp-includes/class.wp-scripts.php */ return \esc_url( \apply_filters( 'script_loader_src', $src, $handle ) ); } } options-helper.php 0000644 00000006164 15154553720 0010243 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WPSEO_Option_Titles; use WPSEO_Options; /** * A helper object for options. */ class Options_Helper { /** * Retrieves a single field from any option for the SEO plugin. Keys are always unique. * * @codeCoverageIgnore We have to write test when this method contains own code. * * @param string $key The key it should return. * @param mixed $default The default value that should be returned if the key isn't set. * * @return mixed|null Returns value if found, $default if not. */ public function get( $key, $default = null ) { return WPSEO_Options::get( $key, $default ); } /** * Sets a single field to the options. * * @param string $key The key to set. * @param mixed $value The value to set. * * @return mixed|null Returns value if found. */ public function set( $key, $value ) { return WPSEO_Options::set( $key, $value ); } /** * Get a specific default value for an option. * * @param string $option_name The option for which you want to retrieve a default. * @param string $key The key within the option who's default you want. * * @return mixed The default value. */ public function get_default( $option_name, $key ) { return WPSEO_Options::get_default( $option_name, $key ); } /** * Retrieves the title separator. * * @return string The title separator. */ public function get_title_separator() { $default = $this->get_default( 'wpseo_titles', 'separator' ); // Get the titles option and the separator options. $separator = $this->get( 'separator' ); $seperator_options = $this->get_separator_options(); // This should always be set, but just to be sure. if ( isset( $seperator_options[ $separator ] ) ) { // Set the new replacement. $replacement = $seperator_options[ $separator ]; } elseif ( isset( $seperator_options[ $default ] ) ) { $replacement = $seperator_options[ $default ]; } else { $replacement = \reset( $seperator_options ); } /** * Filter: 'wpseo_replacements_filter_sep' - Allow customization of the separator character(s). * * @api string $replacement The current separator. */ return \apply_filters( 'wpseo_replacements_filter_sep', $replacement ); } /** * Retrieves a default value from the option titles. * * @param string $option_titles_key The key of the option title you wish to get. * * @return string The option title. */ public function get_title_default( $option_titles_key ) { $default_titles = $this->get_title_defaults(); if ( ! empty( $default_titles[ $option_titles_key ] ) ) { return $default_titles[ $option_titles_key ]; } return ''; } /** * Retrieves the default option titles. * * @codeCoverageIgnore We have to write test when this method contains own code. * * @return array The title defaults. */ protected function get_title_defaults() { return WPSEO_Option_Titles::get_instance()->get_defaults(); } /** * Get the available separator options. * * @return array */ protected function get_separator_options() { return WPSEO_Option_Titles::get_instance()->get_separator_options(); } } current-page-helper.php 0000644 00000027571 15154553720 0011151 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; use WP_Post; use Yoast\WP\SEO\Wrappers\WP_Query_Wrapper; /** * A helper object for WordPress posts. */ class Current_Page_Helper { /** * The WP Query wrapper. * * @var WP_Query_Wrapper */ private $wp_query_wrapper; /** * Current_Page_Helper constructor. * * @codeCoverageIgnore It only sets dependencies. * * @param WP_Query_Wrapper $wp_query_wrapper The wrapper for WP_Query. */ public function __construct( WP_Query_Wrapper $wp_query_wrapper ) { $this->wp_query_wrapper = $wp_query_wrapper; } /** * Returns the page type for the current request. * * @codeCoverageIgnore It just depends on other functions for its result. * * @return string Page type. */ public function get_page_type() { switch ( true ) { case $this->is_search_result(): return 'Search_Result_Page'; case $this->is_static_posts_page(): return 'Static_Posts_Page'; case $this->is_home_static_page(): return 'Static_Home_Page'; case $this->is_home_posts_page(): return 'Home_Page'; case $this->is_simple_page(): return 'Post_Type'; case $this->is_post_type_archive(): return 'Post_Type_Archive'; case $this->is_term_archive(): return 'Term_Archive'; case $this->is_author_archive(): return 'Author_Archive'; case $this->is_date_archive(): return 'Date_Archive'; case $this->is_404(): return 'Error_Page'; } return 'Fallback'; } /** * Checks if the currently opened page is a simple page. * * @return bool Whether the currently opened page is a simple page. */ public function is_simple_page() { return $this->get_simple_page_id() > 0; } /** * Returns the id of the currently opened page. * * @return int The id of the currently opened page. */ public function get_simple_page_id() { if ( \is_singular() ) { return \get_the_ID(); } if ( $this->is_posts_page() ) { return \get_option( 'page_for_posts' ); } /** * Filter: Allow changing the default page id. * * @api int $page_id The default page id. */ return \apply_filters( 'wpseo_frontend_page_type_simple_page_id', 0 ); } /** * Returns the id of the currently opened author archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return int The id of the currently opened author archive. */ public function get_author_id() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->get( 'author' ); } /** * Returns the id of the front page. * * @return int The id of the front page. 0 if the front page is not a static page. */ public function get_front_page_id() { if ( \get_option( 'show_on_front' ) !== 'page' ) { return 0; } return (int) \get_option( 'page_on_front' ); } /** * Returns the id of the currently opened term archive. * * @return int The id of the currently opened term archive. */ public function get_term_id() { $wp_query = $this->wp_query_wrapper->get_main_query(); if ( $wp_query->is_category() ) { return $wp_query->get( 'cat' ); } if ( $wp_query->is_tag() ) { return $wp_query->get( 'tag_id' ); } if ( $wp_query->is_tax() ) { $queried_object = $wp_query->get_queried_object(); if ( $queried_object && ! \is_wp_error( $queried_object ) ) { return $queried_object->term_id; } } return 0; } /** * Returns the post type of the main query. * * @return string The post type of the main query. */ public function get_queried_post_type() { $wp_query = $this->wp_query_wrapper->get_main_query(); $post_type = $wp_query->get( 'post_type' ); if ( \is_array( $post_type ) ) { $post_type = \reset( $post_type ); } return $post_type; } /** * Returns the permalink of the currently opened date archive. * If the permalink was cached, it returns this permalink. * If not, we call another function to get the permalink through wp_query. * * @return string The permalink of the currently opened date archive. */ public function get_date_archive_permalink() { static $date_archive_permalink; if ( isset( $date_archive_permalink ) ) { return $date_archive_permalink; } $date_archive_permalink = $this->get_non_cached_date_archive_permalink(); return $date_archive_permalink; } /** * Determine whether this is the homepage and shows posts. * * @return bool Whether or not the current page is the homepage that displays posts. */ public function is_home_posts_page() { $wp_query = $this->wp_query_wrapper->get_main_query(); if ( ! $wp_query->is_home() ) { return false; } /* * Whether the static page's `Homepage` option is actually not set to a page. * Otherwise WordPress proceeds to handle the homepage as a `Your latest posts` page. */ if ( (int) \get_option( 'page_on_front' ) === 0 ) { return true; } return \get_option( 'show_on_front' ) === 'posts'; } /** * Determine whether this is the static frontpage. * * @return bool Whether or not the current page is a static frontpage. */ public function is_home_static_page() { $wp_query = $this->wp_query_wrapper->get_main_query(); if ( ! $wp_query->is_front_page() ) { return false; } if ( \get_option( 'show_on_front' ) !== 'page' ) { return false; } return $wp_query->is_page( \get_option( 'page_on_front' ) ); } /** * Determine whether this is the static posts page. * * @return bool Whether or not the current page is a static posts page. */ public function is_static_posts_page() { $wp_query = $this->wp_query_wrapper->get_main_query(); $queried_object = $wp_query->get_queried_object(); return ( $wp_query->is_posts_page && \is_a( $queried_object, WP_Post::class ) && $queried_object->post_type === 'page' ); } /** * Determine whether this is the statically set posts page, when it's not the frontpage. * * @return bool Whether or not it's a non-frontpage, statically set posts page. */ public function is_posts_page() { $wp_query = $this->wp_query_wrapper->get_main_query(); if ( ! $wp_query->is_home() ) { return false; } return \get_option( 'show_on_front' ) === 'page'; } /** * Determine whether this is a post type archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is a post type archive. */ public function is_post_type_archive() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_post_type_archive(); } /** * Determine whether this is a term archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is a term archive. */ public function is_term_archive() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_tax || $wp_query->is_tag || $wp_query->is_category; } /** * Determine whether this is an attachment page. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is an attachment page. */ public function is_attachment() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_attachment; } /** * Determine whether this is an author archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is an author archive. */ public function is_author_archive() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_author(); } /** * Determine whether this is an date archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is an date archive. */ public function is_date_archive() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_date(); } /** * Determine whether this is a search result. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is a search result. */ public function is_search_result() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_search(); } /** * Determine whether this is a 404 page. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether nor not the current page is a 404 page. */ public function is_404() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_404(); } /** * Checks if the current page is the post format archive. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether or not the current page is the post format archive. */ public function is_post_format_archive() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_tax( 'post_format' ); } /** * Determine whether this page is an taxonomy archive page for multiple terms (url: /term-1,term2/). * * @return bool Whether or not the current page is an archive page for multiple terms. */ public function is_multiple_terms_page() { if ( ! $this->is_term_archive() ) { return false; } return $this->count_queried_terms() > 1; } /** * Checks whether the current page is paged. * * @codeCoverageIgnore This method only calls a WordPress function. * * @return bool Whether the current page is paged. */ public function is_paged() { return \is_paged(); } /** * Checks if the current page is the front page. * * @codeCoverageIgnore It wraps WordPress functionality. * * @return bool Whether or not the current page is the front page. */ public function is_front_page() { $wp_query = $this->wp_query_wrapper->get_main_query(); return $wp_query->is_front_page(); } /** * Retrieves the current admin page. * * @codeCoverageIgnore It only wraps a global WordPress variable. * * @return string The current page. */ public function get_current_admin_page() { global $pagenow; return $pagenow; } /** * Check if the current opened page is a Yoast SEO page. * * @return bool True when current page is a yoast seo plugin page. */ public function is_yoast_seo_page() { static $is_yoast_seo; if ( $is_yoast_seo === null ) { $current_page = \filter_input( \INPUT_GET, 'page' ); $is_yoast_seo = ( \strpos( $current_page, 'wpseo_' ) === 0 ); } return $is_yoast_seo; } /** * Returns the current Yoast SEO page. * (E.g. the `page` query variable in the URL). * * @return string The current Yoast SEO page. */ public function get_current_yoast_seo_page() { static $current_yoast_seo_page; if ( $current_yoast_seo_page === null ) { $current_yoast_seo_page = \filter_input( \INPUT_GET, 'page' ); } return $current_yoast_seo_page; } /** * Returns the permalink of the currently opened date archive. * * @return string The permalink of the currently opened date archive. */ protected function get_non_cached_date_archive_permalink() { $date_archive_permalink = ''; $wp_query = $this->wp_query_wrapper->get_main_query(); if ( $wp_query->is_day() ) { $date_archive_permalink = \get_day_link( $wp_query->get( 'year' ), $wp_query->get( 'monthnum' ), $wp_query->get( 'day' ) ); } if ( $wp_query->is_month() ) { $date_archive_permalink = \get_month_link( $wp_query->get( 'year' ), $wp_query->get( 'monthnum' ) ); } if ( $wp_query->is_year() ) { $date_archive_permalink = \get_year_link( $wp_query->get( 'year' ) ); } return $date_archive_permalink; } /** * Counts the total amount of queried terms. * * @codeCoverageIgnore This relies too much on WordPress dependencies. * * @return int The amoumt of queried terms. */ protected function count_queried_terms() { $wp_query = $this->wp_query_wrapper->get_main_query(); $term = $wp_query->get_queried_object(); $queried_terms = $wp_query->tax_query->queried_terms; if ( empty( $queried_terms[ $term->taxonomy ]['terms'] ) ) { return 0; } return \count( $queried_terms[ $term->taxonomy ]['terms'] ); } } short-link-helper.php 0000644 00000006457 15154553720 0010647 0 ustar 00 <?php namespace Yoast\WP\SEO\Helpers; /** * Helper to get shortlinks for Yoast SEO. */ class Short_Link_Helper { /** * The options helper. * * @var Options_Helper */ protected $options_helper; /** * The product helper. * * @var Product_Helper */ protected $product_helper; /** * Short_Link_Helper constructor. * * @param Options_Helper $options_helper The options helper. * @param Product_Helper $product_helper The product helper. */ public function __construct( Options_Helper $options_helper, Product_Helper $product_helper ) { $this->options_helper = $options_helper; $this->product_helper = $product_helper; } /** * Builds a URL to use in the plugin as shortlink. * * @param string $url The URL to build upon. * * @return string The final URL. */ public function build( $url ) { return \add_query_arg( $this->collect_additional_shortlink_data(), $url ); } /** * Returns a version of the URL with a utm_content with the current version. * * @param string $url The URL to build upon. * * @return string The final URL. */ public function get( $url ) { return $this->build( $url ); } /** * Echoes a version of the URL with a utm_content with the current version. * * @param string $url The URL to build upon. */ public function show( $url ) { echo \esc_url( $this->get( $url ) ); } /** * Gets the shortlink's query params. * * @return array The shortlink's query params. */ public function get_query_params() { return $this->collect_additional_shortlink_data(); } /** * Gets the current site's PHP version, without the extra info. * * @return string The PHP version. */ private function get_php_version() { $version = \explode( '.', \PHP_VERSION ); return (int) $version[0] . '.' . (int) $version[1]; } /** * Gets the current site's platform version. * * @return string The wp_version. */ protected function get_platform_version() { return $GLOBALS['wp_version']; } /** * Collects the additional data necessary for the shortlink. * * @return array The shortlink data. */ protected function collect_additional_shortlink_data() { return [ 'php_version' => $this->get_php_version(), 'platform' => 'wordpress', 'platform_version' => $this->get_platform_version(), 'software' => $this->get_software(), 'software_version' => \WPSEO_VERSION, 'days_active' => $this->get_days_active(), 'user_language' => \get_user_locale(), ]; } /** * Get our software and whether it's active or not. * * @return string The software name. */ protected function get_software() { if ( $this->product_helper->is_premium() ) { return 'premium'; } return 'free'; } /** * Gets the number of days the plugin has been active. * * @return int The number of days the plugin is active. */ protected function get_days_active() { $date_activated = $this->options_helper->get( 'first_activated_on' ); $datediff = ( \time() - $date_activated ); $days = (int) \round( $datediff / \DAY_IN_SECONDS ); switch ( $days ) { case 0: case 1: $cohort = '0-1'; break; case ( $days < 5 ): $cohort = '2-5'; break; case ( $days < 30 ): $cohort = '6-30'; break; default: $cohort = '30plus'; } return $cohort; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка