user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); user The user helper. * @param Permalink_Helper $permalink_helper The permalink helper. * @param Indexable_Helper $indexable_helper The indexable helper. * @param Indexable_Repository $indexable_repository The indexable repository. */ public function __construct( Options_Helper $options, Url_Helper $url, Image_Helper $image, ID_Helper $id_helper, WPSEO_Replace_Vars $replace_vars, Site_Helper $site, User_Helper $user, Permalink_Helper $permalink_helper, Indexable_Helper $indexable_helper, Indexable_Repository $indexable_repository ) { $this->options = $options; $this->url = $url; $this->image = $image; $this->id_helper = $id_helper; $this->replace_vars = $replace_vars; $this->site = $site; $this->user = $user; $this->permalink_helper = $permalink_helper; $this->indexable_helper = $indexable_helper; $this->indexable_repository = $indexable_repository; } /** * Generates the title. * * @return string the title */ public function generate_title() { return $this->replace_vars->replace( $this->presentation->title, $this->presentation->source ); } /** * Generates the description. * * @return string the description */ public function generate_description() { return $this->replace_vars->replace( $this->presentation->meta_description, $this->presentation->source ); } /** * Generates the canonical. * * @return string the canonical */ public function generate_canonical() { return $this->presentation->canonical; } /** * Generates the permalink. * * @return string */ public function generate_permalink() { if ( ! \is_search() ) { return $this->presentation->permalink; } return \add_query_arg( 's', \rawurlencode( \get_search_query() ), \trailingslashit( $this->site_url ) ); } /** * Generates the id. * * @return string the id */ public function generate_id() { return $this->indexable->object_id; } /** * Generates the site name. * * @return string The site name. */ public function generate_site_name() { $site_name = $this->options->get( 'website_name', '' ); if ( $site_name !== '' ) { return $site_name; } return \get_bloginfo( 'name' ); } /** * Generates the alternate site name. * * @return string The alternate site name. */ public function generate_alternate_site_name() { return (string) $this->options->get( 'alternate_website_name', '' ); } /** * Generates the site name from the WordPress options. * * @return string The site name from the WordPress options. */ public function generate_wordpress_site_name() { return $this->site->get_site_name(); } /** * Generates the site url. * * @return string The site url. */ public function generate_site_url() { $home_page_indexable = $this->indexable_repository->find_for_home_page(); if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { return \trailingslashit( $this->permalink_helper->get_permalink_for_indexable( $home_page_indexable ) ); } return \trailingslashit( $home_page_indexable->permalink ); } /** * Generates the company name. * * @return string The company name. */ public function generate_company_name() { /** * Filter: 'wpseo_schema_company_name' - Allows filtering company name * * @param string $company_name. */ $company_name = \apply_filters( 'wpseo_schema_company_name', $this->options->get( 'company_name' ) ); if ( empty( $company_name ) ) { $company_name = $this->site_name; } return $company_name; } /** * Generates the alternate company name. * * @return string */ public function generate_company_alternate_name() { return (string) $this->options->get( 'company_alternate_name' ); } /** * Generates the person logo id. * * @return int|bool The company logo id. */ public function generate_person_logo_id() { $person_logo_id = $this->image->get_attachment_id_from_settings( 'person_logo' ); if ( empty( $person_logo_id ) ) { $person_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_person_logo_id' - Allows filtering person logo id. * * @param int $person_logo_id. */ return \apply_filters( 'wpseo_schema_person_logo_id', $person_logo_id ); } /** * Retrieve the person logo meta. * * @return array>|bool */ public function generate_person_logo_meta() { $person_logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' ); if ( empty( $person_logo_meta ) ) { $person_logo_id = $this->fallback_to_site_logo(); $person_logo_meta = $this->image->get_best_attachment_variation( $person_logo_id ); } /** * Filter: 'wpseo_schema_person_logo_meta' - Allows filtering person logo meta. * * @param string $person_logo_meta. */ return \apply_filters( 'wpseo_schema_person_logo_meta', $person_logo_meta ); } /** * Generates the company logo id. * * @return int|bool The company logo id. */ public function generate_company_logo_id() { $company_logo_id = $this->image->get_attachment_id_from_settings( 'company_logo' ); if ( empty( $company_logo_id ) ) { $company_logo_id = $this->fallback_to_site_logo(); } /** * Filter: 'wpseo_schema_company_logo_id' - Allows filtering company logo id. * * @param int $company_logo_id. */ return \apply_filters( 'wpseo_schema_company_logo_id', $company_logo_id ); } /** * Retrieve the company logo meta. * * @return array>|bool */ public function generate_company_logo_meta() { $company_logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' ); /** * Filter: 'wpseo_schema_company_logo_meta' - Allows filtering company logo meta. * * @param string $company_logo_meta. */ return \apply_filters( 'wpseo_schema_company_logo_meta', $company_logo_meta ); } /** * Generates the site user id. * * @return int The site user id. */ public function generate_site_user_id() { return (int) $this->options->get( 'company_or_person_user_id', false ); } /** * Determines what our site represents, and grabs their values. * * @return string|false Person or company. False if invalid value. */ public function generate_site_represents() { switch ( $this->options->get( 'company_or_person', false ) ) { case 'company': // Do not use a non-named company. if ( empty( $this->company_name ) ) { return false; } /* * Do not use a company without a logo. * The logic check is on `< 1` instead of `false` due to how `get_attachment_id_from_settings` works. */ if ( $this->company_logo_id < 1 ) { return false; } return 'company'; case 'person': // Do not use a non-existing user. if ( $this->site_user_id !== false && \get_user_by( 'id', $this->site_user_id ) === false ) { return false; } return 'person'; } return false; } /** * Returns the site represents reference. * * @return array|bool The site represents reference. False if none. */ public function generate_site_represents_reference() { if ( $this->site_represents === 'person' ) { return [ '@id' => $this->id_helper->get_user_schema_id( $this->site_user_id, $this ) ]; } if ( $this->site_represents === 'company' ) { return [ '@id' => $this->site_url . Schema_IDs::ORGANIZATION_HASH ]; } return false; } /** * Returns whether or not open graph is enabled. * * @return bool Whether or not open graph is enabled. */ public function generate_open_graph_enabled() { return $this->options->get( 'opengraph' ) === true; } /** * Returns the open graph publisher. * * @return string The open graph publisher. */ public function generate_open_graph_publisher() { if ( $this->site_represents === 'company' ) { return $this->options->get( 'facebook_site', '' ); } if ( $this->site_represents === 'person' ) { return $this->user->get_the_author_meta( 'facebook', $this->site_user_id ); } return $this->options->get( 'facebook_site', '' ); } /** * Returns the twitter card type. * * @return string The twitter card type. */ public function generate_twitter_card() { return 'summary_large_image'; } /** * Returns the schema page type. * * @return string|array The schema page type. */ public function generate_schema_page_type() { switch ( $this->indexable->object_type ) { case 'system-page': switch ( $this->indexable->object_sub_type ) { case 'search-result': $type = [ 'CollectionPage', 'SearchResultsPage' ]; break; default: $type = 'WebPage'; } break; case 'user': $type = 'ProfilePage'; break; case 'home-page': case 'date-archive': case 'term': case 'post-type-archive': $type = 'CollectionPage'; break; default: $additional_type = $this->indexable->schema_page_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-page-type-' . $this->indexable->object_sub_type ); } $type = [ 'WebPage', $additional_type ]; // Is this indexable set as a page for posts, e.g. in the WordPress reading settings as a static homepage? if ( (int) \get_option( 'page_for_posts' ) === $this->indexable->object_id ) { $type[] = 'CollectionPage'; } // Ensure we get only unique values, and remove any null values and the index. $type = \array_filter( \array_values( \array_unique( $type ) ) ); } /** * Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type. * * @param string|array $type The WebPage type. */ return \apply_filters( 'wpseo_schema_webpage_type', $type ); } /** * Returns the schema article type. * * @return string|array The schema article type. */ public function generate_schema_article_type() { $additional_type = $this->indexable->schema_article_type; if ( $additional_type === null ) { $additional_type = $this->options->get( 'schema-article-type-' . $this->indexable->object_sub_type ); } /** This filter is documented in inc/options/class-wpseo-option-titles.php */ $allowed_article_types = \apply_filters( 'wpseo_schema_article_types', Schema_Types::ARTICLE_TYPES ); if ( ! \array_key_exists( $additional_type, $allowed_article_types ) ) { $additional_type = $this->options->get_title_default( 'schema-article-type-' . $this->indexable->object_sub_type ); } // If the additional type is a subtype of Article, we're fine, and we can bail here. if ( \stripos( $additional_type, 'Article' ) !== false ) { /** * Filter: 'wpseo_schema_article_type' - Allow changing the Article type. * * @param string|string[] $type The Article type. * @param Indexable $indexable The indexable. */ return \apply_filters( 'wpseo_schema_article_type', $additional_type, $this->indexable ); } $type = 'Article'; /* * If `None` is set (either on the indexable or as a default), set type to 'None'. * This simplifies is_needed checks downstream. */ if ( $additional_type === 'None' ) { $type = $additional_type; } if ( $additional_type !== $type ) { $type = [ $type, $additional_type ]; } // Filter documented on line 499 above. return \apply_filters( 'wpseo_schema_article_type', $type, $this->indexable ); } /** * Returns the main schema id. * * The main schema id. * * @return string */ public function generate_main_schema_id() { return $this->permalink; } /** * Retrieves the main image URL. This is the featured image by default. * * @return string|null The main image URL. */ public function generate_main_image_url() { if ( $this->main_image_id !== null ) { return $this->image->get_attachment_image_url( $this->main_image_id, 'full' ); } if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_url_for_rest_request(); } if ( ! \is_singular() ) { return null; } $url = $this->image->get_post_content_image( $this->id ); if ( $url === '' ) { return null; } return $url; } /** * Generates the main image ID. * * @return int|null The main image ID. */ public function generate_main_image_id() { if ( \wp_is_serving_rest_request() ) { return $this->get_main_image_id_for_rest_request(); } switch ( true ) { case \is_singular(): return $this->get_singular_post_image( $this->id ); case \is_author(): case \is_tax(): case \is_tag(): case \is_category(): case \is_search(): case \is_date(): case \is_post_type_archive(): if ( ! empty( $GLOBALS['wp_query']->posts ) ) { if ( $GLOBALS['wp_query']->get( 'fields', 'all' ) === 'ids' ) { return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0] ); } return $this->get_singular_post_image( $GLOBALS['wp_query']->posts[0]->ID ); } return null; default: return null; } } /** * Determines whether the current indexable has an image. * * @return bool Whether the current indexable has an image. */ public function generate_has_image() { return $this->main_image_url !== null; } /** * Strips all nested dependencies from the debug info. * * @return array */ public function __debugInfo() { return [ 'indexable' => $this->indexable, 'presentation' => $this->presentation, ]; } /** * Retrieve the site logo ID from WordPress settings. * * @return int|false */ public function fallback_to_site_logo() { $logo_id = \get_option( 'site_logo' ); if ( ! $logo_id ) { $logo_id = \get_theme_mod( 'custom_logo', false ); } return $logo_id; } /** * Get the ID for a post's featured image. * * @param int $id Post ID. * * @return int|null */ private function get_singular_post_image( $id ) { if ( \has_post_thumbnail( $id ) ) { $thumbnail_id = \get_post_thumbnail_id( $id ); // Prevent returning something else than an int or null. if ( \is_int( $thumbnail_id ) && $thumbnail_id > 0 ) { return $thumbnail_id; } } if ( \is_singular( 'attachment' ) ) { return \get_query_var( 'attachment_id' ); } return null; } /** * Gets the main image ID for REST requests. * * @return int|null The main image ID. */ private function get_main_image_id_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { return $this->get_singular_post_image( $this->post->ID ); } return null; default: return null; } } /** * Gets the main image URL for REST requests. * * @return string|null The main image URL. */ private function get_main_image_url_for_rest_request() { switch ( $this->page_type ) { case 'Post_Type': if ( $this->post instanceof WP_Post ) { $url = $this->image->get_post_content_image( $this->post->ID ); if ( $url === '' ) { return null; } return $url; } return null; default: return null; } } } \class_alias( Meta_Tags_Context::class, 'WPSEO_Schema_Context' ); Nos Rayons – Superette Antonia

No products in the cart.

Nos Rayons

Show

APÉROL 1L

CFA 18.600

APEROL 70CL

CFA 14.900

BAILEYS 750 ML

CFA 19.800

COURVOISIER 70CL

CFA 52.700

Dattes Sultana 1kg

CFA 3.400

FERRERO ROCHER TABLETTE NOISETTE NOIRE

CFA 2.200

JACK DANIEL’S HONEY

CFA 21.200

LINGETTE MOLFIX 60PCS

CFA 1.300

LINGETTE SOFTCARE 80PCS

CFA 1.300

MARTELL 70CL

CFA 40.400

NUTRIBOM AVOINE 350G

CFA 1.650
Showing 12 of 19 items
Load More