* @param string $id Control ID.
* @param array $args Control arguments. Only the new fields you want to update.
* @param array $options Optional. Some additional options.
*/
public function update_control( $id, $args, array $options = [] ) {
$args['condition']['_skin'] = $this->get_id();
parent::update_control( $id, $args, $options );
}
/**
* Add new responsive skin control.
*
* Register a set of controls to allow editing based on user screen size.
*
* @param string $id Responsive control ID.
* @param array $args Responsive control arguments.
* @param array $options
*
* @since 1.0.5
* @access public
*
*/
public function add_responsive_control( $id, $args, $options = [] ) {
$args['condition']['_skin'] = $this->get_id();
parent::add_responsive_control( $id, $args );
}
/**
* Start skin controls tab.
*
* Used to add a new tab inside a group of tabs.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments.
*/
public function start_controls_tab( $id, $args ) {
$args['condition']['_skin'] = $this->get_id();
parent::start_controls_tab( $id, $args );
}
/**
* Start skin controls tabs.
*
* Used to add a new set of tabs inside a section.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
*/
public function start_controls_tabs( $id ) {
$args['condition']['_skin'] = $this->get_id();
parent::start_controls_tabs( $id );
}
/**
* Add new group control.
*
* Register a set of related controls grouped together as a single unified
* control.
*
* @param string $group_name Group control name.
* @param array $args Group control arguments. Default is an empty array.
* @param array $options
*
* @since 1.0.0
* @access public
*
*/
final public function add_group_control( $group_name, $args = [], $options = [] ) {
$args['condition']['_skin'] = $this->get_id();
parent::add_group_control( $group_name, $args );
}
/**
* Set parent widget.
*
* Used to define the parent widget of the skin.
*
* @since 1.0.0
* @access public
*
* @param Widget_Base $parent Parent widget.
*/
public function set_parent( $parent ) {
$this->parent = $parent;
}
}
y', wp_generate_password( 32, false ) );
$settings['siteVisibilitySettings'] = array(
'shop_permalink' => get_permalink( wc_get_page_id( 'shop' ) ),
'woocommerce_coming_soon' => get_option( 'woocommerce_coming_soon' ),
'woocommerce_store_pages_only' => get_option( 'woocommerce_store_pages_only' ),
'woocommerce_private_link' => get_option( 'woocommerce_private_link' ),
'woocommerce_share_key' => get_option( 'woocommerce_share_key' ),
);
}
return $settings;
}
/**
* User must be an admin or editor.
*
* @return bool
*/
private function is_manager_or_admin() {
// phpcs:ignore
if ( ! current_user_can( 'shop_manager' ) && ! current_user_can( 'administrator' ) ) {
return false;
}
return true;
}
/**
* Add 'coming soon' banner on the frontend when the following conditions met.
*
* - User must be either an admin or store editor (must be logged in).
* - 'woocommerce_coming_soon' option value must be 'yes'
* - The page must not be the Coming soon page itself.
*/
public function maybe_add_coming_soon_banner_on_frontend() {
// Do not show the banner if the site is being previewed.
if ( isset( $_GET['site-preview'] ) ) { // @phpcs:ignore
return false;
}
$current_user_id = get_current_user_id();
if ( ! $current_user_id ) {
return false;
}
$has_dismissed_banner = WCAdminUser::get_user_data_field( $current_user_id, self::BANNER_DISMISS_USER_META_KEY )
// Remove this check in WC 9.4.
|| get_user_meta( $current_user_id, 'woocommerce_' . self::BANNER_DISMISS_USER_META_KEY, true ) === 'yes';
if ( $has_dismissed_banner ) {
return false;
}
if ( ! $this->is_manager_or_admin() ) {
return false;
}
// 'woocommerce_coming_soon' must be 'yes'
if ( get_option( 'woocommerce_coming_soon', 'no' ) !== 'yes' ) {
return false;
}
$store_pages_only = get_option( 'woocommerce_store_pages_only' ) === 'yes';
if ( $store_pages_only && ! WCAdminHelper::is_store_page() ) {
return false;
}
$link = admin_url( 'admin.php?page=wc-settings&tab=site-visibility' );
$rest_url = rest_url( 'wp/v2/users/' . $current_user_id );
$rest_nonce = wp_create_nonce( 'wp_rest' );
$text = sprintf(
// translators: no need to translate it. It's a link.
__(
"
This page is in \"Coming soon\" mode and is only visible to you and those who have permission. To make it public to everyone, change visibility settings
",
'woocommerce'
),
$link
);
// phpcs:ignore
echo "";
}
/**
* Register user meta fields for Launch Your Store.
*
* This should be removed in WC 9.4.
*/
public function register_launch_your_store_user_meta_fields() {
if ( ! $this->is_manager_or_admin() ) {
return;
}
register_meta(
'user',
'woocommerce_launch_your_store_tour_hidden',
array(
'type' => 'string',
'description' => 'Indicate whether the user has dismissed the site visibility tour on the home screen.',
'single' => true,
'show_in_rest' => true,
)
);
register_meta(
'user',
'woocommerce_coming_soon_banner_dismissed',
array(
'type' => 'string',
'description' => 'Indicate whether the user has dismissed the coming soon notice or not.',
'single' => true,
'show_in_rest' => true,
)
);
}
/**
* Register user meta fields for Launch Your Store.
*
* @param array $user_data_fields user data fields.
* @return array
*/
public function add_user_data_fields( $user_data_fields ) {
return array_merge(
$user_data_fields,
array(
'launch_your_store_tour_hidden',
self::BANNER_DISMISS_USER_META_KEY,
)
);
}
/**
* Reset 'woocommerce_coming_soon_banner_dismissed' user meta to 'no'.
*
* Runs when a user logs-in successfully.
*
* @param string $user_login user login.
* @param object $user user object.
*/
public function reset_woocommerce_coming_soon_banner_dismissed( $user_login, $user ) {
$existing_meta = WCAdminUser::get_user_data_field( $user->ID, self::BANNER_DISMISS_USER_META_KEY );
if ( 'yes' === $existing_meta ) {
WCAdminUser::update_user_data_field( $user->ID, self::BANNER_DISMISS_USER_META_KEY, 'no' );
}
}
}
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