PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

View File

@ -0,0 +1,183 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Article data.
*
* @since 10.2
*/
class WPSEO_Schema_Article implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determines whether or not a piece should be added to the graph.
*
* @return bool
*/
public function is_needed() {
/**
* Filter: 'wpseo_schema_article_post_types' - Allow changing for which post types we output Article schema.
*
* @api string[] $post_types The post types for which we output Article.
*/
$post_types = apply_filters( 'wpseo_schema_article_post_types', array( 'post' ) );
return is_singular( $post_types );
}
/**
* Returns Article data.
*
* @return array $data Article data.
*/
public function generate() {
$post = get_post( $this->context->id );
$comment_count = get_comment_count( $this->context->id );
$data = array(
'@type' => 'Article',
'@id' => $this->context->canonical . WPSEO_Schema_IDs::ARTICLE_HASH,
'isPartOf' => array( '@id' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH ),
'author' => array(
'@id' => $this->get_author_url( $post ),
'name' => get_the_author_meta( 'display_name', $post->post_author ),
),
'publisher' => array( '@id' => $this->get_publisher_url() ),
'headline' => get_the_title(),
'datePublished' => mysql2date( DATE_W3C, $post->post_date_gmt, false ),
'dateModified' => mysql2date( DATE_W3C, $post->post_modified_gmt, false ),
'commentCount' => $comment_count['approved'],
'mainEntityOfPage' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH,
);
$data = $this->add_image( $data );
$data = $this->add_keywords( $data );
$data = $this->add_sections( $data );
return $data;
}
/**
* Determine the proper author URL.
*
* @param \WP_Post $post Post object.
*
* @return string
*/
private function get_author_url( $post ) {
if ( $this->context->site_represents === 'person' && $this->context->site_user_id === (int) $post->post_author ) {
return $this->context->site_url . WPSEO_Schema_IDs::PERSON_HASH;
}
return get_author_posts_url( $post->post_author ) . WPSEO_Schema_IDs::AUTHOR_HASH;
}
/**
* Determine the proper publisher URL.
*
* @return string
*/
private function get_publisher_url() {
if ( $this->context->site_represents === 'person' ) {
return $this->context->site_url . WPSEO_Schema_IDs::PERSON_HASH;
}
return $this->context->site_url . WPSEO_Schema_IDs::ORGANIZATION_HASH;
}
/**
* Adds tags as keywords, if tags are assigned.
*
* @param array $data Article data.
*
* @return array $data Article data.
*/
private function add_keywords( $data ) {
/**
* Filter: 'wpseo_schema_article_keywords_taxonomy' - Allow changing the taxonomy used to assign keywords to a post type Article data.
*
* @api string $taxonomy The chosen taxonomy.
*/
$taxonomy = apply_filters( 'wpseo_schema_article_keywords_taxonomy', 'post_tag' );
return $this->add_terms( $data, 'keywords', $taxonomy );
}
/**
* Adds categories as sections, if categories are assigned.
*
* @param array $data Article data.
*
* @return array $data Article data.
*/
private function add_sections( $data ) {
/**
* Filter: 'wpseo_schema_article_sections_taxonomy' - Allow changing the taxonomy used to assign keywords to a post type Article data.
*
* @api string $taxonomy The chosen taxonomy.
*/
$taxonomy = apply_filters( 'wpseo_schema_article_sections_taxonomy', 'category' );
return $this->add_terms( $data, 'articleSection', $taxonomy );
}
/**
* Adds a term or multiple terms, comma separated, to a field.
*
* @param array $data Article data.
* @param string $key The key in data to save the terms in.
* @param string $taxonomy The taxonomy to retrieve the terms from.
*
* @return mixed array $data Article data.
*/
private function add_terms( $data, $key, $taxonomy ) {
$terms = get_the_terms( $this->context->id, $taxonomy );
if ( is_array( $terms ) ) {
$keywords = array();
foreach ( $terms as $term ) {
// We are checking against the WordPress internal translation.
// @codingStandardsIgnoreLine
if ( $term->name !== __( 'Uncategorized' ) ) {
$keywords[] = $term->name;
}
}
$data[ $key ] = implode( ',', $keywords );
}
return $data;
}
/**
* Adds an image node if the post has a featured image.
*
* @param array $data The Article data.
*
* @return array $data The Article data.
*/
private function add_image( $data ) {
if ( has_post_thumbnail( $this->context->id ) ) {
$data['image'] = array(
'@id' => $this->context->canonical . WPSEO_Schema_IDs::PRIMARY_IMAGE_HASH,
);
}
return $data;
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Person data.
*
* @since 10.2
*
* @property WPSEO_Schema_Context $context A value object with context variables.
*/
class WPSEO_Schema_Author extends WPSEO_Schema_Person implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
parent::__construct( $context );
$this->context = $context;
$this->logo_hash = WPSEO_Schema_IDs::AUTHOR_LOGO_HASH;
}
/**
* Determine whether we should return Person schema.
*
* @return bool
*/
public function is_needed() {
if ( is_author() ) {
return true;
}
if ( $this->is_post_author() ) {
$post = get_post( $this->context->id );
// If the author is the user the site represents, no need for an extra author block.
if ( (int) $post->post_author === $this->context->site_user_id ) {
return false;
}
return true;
}
return false;
}
/**
* Builds our array of Schema Person data for a given user ID.
*
* @param int $user_id The user ID to use.
*
* @return array An array of Schema Person data.
*/
protected function build_person_data( $user_id ) {
$data = parent::build_person_data( $user_id );
// If this is an author page, the Person object is the main object, so we set it as such here.
if ( is_author() ) {
$data['mainEntityOfPage'] = array(
'@id' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH,
);
}
return $data;
}
/**
* Determine whether the current URL is worthy of Article schema.
*
* @return bool
*/
protected function is_post_author() {
/**
* Filter: 'wpseo_schema_article_post_type' - Allow changing for which post types we output Article schema.
*
* @api array $post_types The post types for which we output Article.
*/
$post_types = apply_filters( 'wpseo_schema_article_post_type', array( 'post' ) );
if ( is_singular( $post_types ) ) {
return true;
}
return false;
}
/**
* Determines a User ID for the Person data.
*
* @return bool|int User ID or false upon return.
*/
protected function determine_user_id() {
switch ( true ) {
case is_author():
$user_id = get_queried_object_id();
break;
default:
$post = get_post( $this->context->id );
$user_id = (int) $post->post_author;
break;
}
/**
* Filter: 'wpseo_schema_person_user_id' - Allows filtering of user ID used for person output.
*
* @api int|bool $user_id The user ID currently determined.
*/
return apply_filters( 'wpseo_schema_person_user_id', $user_id );
}
/**
* Returns the string to use in Schema's `@id`.
*
* @param int $user_id The user ID if we're on a user page.
*
* @return string The `@id` string value.
*/
protected function determine_schema_id( $user_id ) {
return get_author_posts_url( $user_id ) . WPSEO_Schema_IDs::AUTHOR_HASH;
}
}

View File

@ -0,0 +1,148 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Breadcrumb data.
*
* @since 10.2
*/
class WPSEO_Schema_Breadcrumb implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* Current position in the List.
*
* @var int
*/
private $index;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determine if we should add a breadcrumb attribute.
*
* @return bool
*/
public function is_needed() {
if ( is_404() ) {
return false;
}
if ( is_front_page() ) {
return false;
}
if ( $this->context->breadcrumbs_enabled ) {
return true;
}
return false;
}
/**
* Returns Schema breadcrumb data to allow recognition of page's position in the site hierarchy.
*
* @link https://developers.google.com/search/docs/data-types/breadcrumb
*
* @return bool|array Array on success, false on failure.
*/
public function generate() {
$breadcrumbs_instance = WPSEO_Breadcrumbs::get_instance();
$breadcrumbs = $breadcrumbs_instance->get_links();
$broken = false;
$list_elements = array();
foreach ( $breadcrumbs as $index => $breadcrumb ) {
if ( ! empty( $breadcrumb['hide_in_schema'] ) ) {
continue;
}
if ( ! array_key_exists( 'url', $breadcrumb ) || ! array_key_exists( 'text', $breadcrumb ) ) {
$broken = true;
break;
}
$list_elements[] = $this->add_breadcrumb( $index, $breadcrumb );
$this->index = $index;
}
if ( is_paged() ) {
$list_elements[] = $this->add_paginated_state();
}
$data = array(
'@type' => 'BreadcrumbList',
'@id' => $this->context->canonical . WPSEO_Schema_IDs::BREADCRUMB_HASH,
'itemListElement' => $list_elements,
);
// Only output if JSON is correctly formatted.
if ( ! $broken ) {
return $data;
}
return false;
}
/**
* Returns a breadcrumb array.
*
* @param int $index The position in the list.
* @param array $breadcrumb The breadcrumb array.
*
* @return array A breadcrumb listItem.
*/
private function add_breadcrumb( $index, $breadcrumb ) {
if ( empty( $breadcrumb['url'] ) ) {
if ( is_paged() ) {
// Retrieve the un-paginated state of the current page.
$breadcrumb['url'] = WPSEO_Frontend::get_instance()->canonical( false, true );
}
else {
$breadcrumb['url'] = $this->context->canonical;
}
}
if ( empty( $breadcrumb['text'] ) ) {
$breadcrumb['url'] = $this->context->title;
}
return array(
'@type' => 'ListItem',
'position' => ( $index + 1 ),
'item' => array(
'@type' => 'WebPage',
'@id' => $breadcrumb['url'],
'url' => $breadcrumb['url'], // For future proofing, we're trying to change the standard for this.
'name' => $breadcrumb['text'],
),
);
}
/**
* Adds the paginated state to the breadcrumb array.
*
* @return array A breadcrumb listItem.
*/
private function add_paginated_state() {
$this->index++;
return $this->add_breadcrumb( $this->index, array(
'url' => $this->context->canonical,
'text' => $this->context->title,
) );
}
}

View File

@ -0,0 +1,189 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Context variables for Schema generation.
*
* @property string $canonical The current page's canonical.
* @property string $company_name Holds the company name, if the site represents a company.
* @property int $id The post ID, if there is one.
* @property string $site_name The site's name.
* @property string $site_represents Whether this site represents a `company` or a `person`.
* @property string $site_url The site's URL.
* @property int $site_user_id The site's User ID if a site represents a `person`.
* @property string $title Page title.
* @property string $description Page description.
* @property bool $breadcrumbs_enabled Whether or not this site has breadcrumbs enabled.
*
* @since 10.2
*/
class WPSEO_Schema_Context {
/**
* The current page's canonical.
*
* @var string
*/
public $canonical;
/**
* Holds the company name, if the site represents a company.
*
* @var string
*/
public $company_name;
/**
* The queried object ID, if there is one.
*
* @var int
*/
public $id;
/**
* Whether this site represents a `company` or a `person`.
*
* @var string
*/
public $site_represents;
/**
* The site's Name.
*
* @var string
*/
public $site_name;
/**
* The site's URL.
*
* @var string
*/
public $site_url;
/**
* Page title.
*
* @var string
*/
public $title;
/**
* User ID when the site represents a Person.
*
* @var int
*/
public $site_user_id;
/**
* Page description.
*
* @var string
*/
public $description;
/**
* Whether or not this site has breadcrumbs enabled.
*
* @var bool
*/
public $breadcrumbs_enabled;
/**
* Hash used for the Author `@id`.
*/
const AUTHOR_HASH = '#author';
/**
* Hash used for the Author Logo's `@id`.
*/
const AUTHOR_LOGO_HASH = '#authorlogo';
/**
* Hash used for the Breadcrumb's `@id`.
*/
const BREADCRUMB_HASH = '#breadcrumb';
/**
* Hash used for the Person `@id`.
*/
const PERSON_HASH = '#person';
/**
* Hash used for the Article `@id`.
*/
const ARTICLE_HASH = '#article';
/**
* Hash used for the Organization `@id`.
*/
const ORGANIZATION_HASH = '#organization';
/**
* Hash used for the Organization `@id`.
*/
const ORGANIZATION_LOGO_HASH = '#logo';
/**
* Hash used for the logo `@id`.
*/
const PERSON_LOGO_HASH = '#personlogo';
/**
* Hash used for an Article's primary image `@id`.
*/
const PRIMARY_IMAGE_HASH = '#primaryimage';
/**
* Hash used for the WebPage's `@id`.
*/
const WEBPAGE_HASH = '#webpage';
/**
* Hash used for the Website's `@id`.
*/
const WEBSITE_HASH = '#website';
/**
* WPSEO_Schema_Context constructor.
*/
public function __construct() {
$this->build_data();
}
/**
* Builds all the required data for the context object.
*/
private function build_data() {
$this->breadcrumbs_enabled = current_theme_supports( 'yoast-seo-breadcrumbs' );
if ( ! $this->breadcrumbs_enabled ) {
$this->breadcrumbs_enabled = WPSEO_Options::get( 'breadcrumbs-enable', false );
}
$front = WPSEO_Frontend::get_instance();
$this->canonical = $front->canonical( false );
$this->title = $front->title( '' );
$this->description = $front->metadesc( false );
$this->site_name = $this->set_site_name();
$this->site_represents = WPSEO_Options::get( 'company_or_person', '' );
$this->site_url = trailingslashit( WPSEO_Utils::home_url() );
if ( $this->site_represents === 'company' ) {
$this->company_name = WPSEO_Options::get( 'company_name' );
}
if ( $this->site_represents === 'person' ) {
$this->site_user_id = WPSEO_Options::get( 'company_or_person_user_id', false );
}
$this->id = get_queried_object_id();
}
/**
* Retrieves the site's name from settings.
*
* @return string
*/
private function set_site_name() {
if ( '' !== WPSEO_Options::get( 'website_name', '' ) ) {
return WPSEO_Options::get( 'website_name' );
}
return get_bloginfo( 'name' );
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Constants used for @id variables.
*
* @since 10.2
*/
class WPSEO_Schema_IDs {
/**
* Hash used for the Author `@id`.
*/
const AUTHOR_HASH = '#author';
/**
* Hash used for the Author Logo's `@id`.
*/
const AUTHOR_LOGO_HASH = '#authorlogo';
/**
* Hash used for the Breadcrumb's `@id`.
*/
const BREADCRUMB_HASH = '#breadcrumb';
/**
* Hash used for the Person `@id`.
*/
const PERSON_HASH = '#person';
/**
* Hash used for the Article `@id`.
*/
const ARTICLE_HASH = '#article';
/**
* Hash used for the Organization `@id`.
*/
const ORGANIZATION_HASH = '#organization';
/**
* Hash used for the Organization `@id`.
*/
const ORGANIZATION_LOGO_HASH = '#logo';
/**
* Hash used for the logo `@id`.
*/
const PERSON_LOGO_HASH = '#personlogo';
/**
* Hash used for an Article's primary image `@id`.
*/
const PRIMARY_IMAGE_HASH = '#primaryimage';
/**
* Hash used for the WebPage's `@id`.
*/
const WEBPAGE_HASH = '#webpage';
/**
* Hash used for the Website's `@id`.
*/
const WEBSITE_HASH = '#website';
}

View File

@ -0,0 +1,155 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema image data.
*
* @since 11.1
*
* @property string $schema_id The `@id` to use for the returned image.
* @property array $data The ImageObject Schema array.
* @property int $attachment_id The ID of the attachment used to generate the object.
*/
class WPSEO_Schema_Image {
/**
* The `@id` to use for the returned image.
*
* @var string
*/
private $schema_id;
/**
* The ImageObject Schema array.
*
* @var array
*/
private $data;
/**
* The ID of the attachment used to generate the object.
*
* @var int
*/
private $attachment_id;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param string $schema_id The string to use in an image's `@id`.
*/
public function __construct( $schema_id ) {
$this->schema_id = $schema_id;
$this->generate_object();
}
/**
* Find an image based on its URL and generate a Schema object for it.
*
* @param string $url The image URL to base our object on.
* @param string $caption An optional caption.
*
* @return array Schema ImageObject array.
*/
public function generate_from_url( $url, $caption = '' ) {
$attachment_id = WPSEO_Image_Utils::get_attachment_by_url( $url );
if ( $attachment_id > 0 ) {
return $this->generate_from_attachment_id( $attachment_id, $caption );
}
return $this->simple_image_object( $url, $caption );
}
/**
* Retrieve data about an image from the database and use it to generate a Schema object.
*
* @param int $attachment_id The attachment to retrieve data from.
* @param string $caption The caption string, if there is one.
*
* @return array Schema ImageObject array.
*/
public function generate_from_attachment_id( $attachment_id, $caption = '' ) {
$this->attachment_id = $attachment_id;
$this->data['url'] = wp_get_attachment_image_url( $this->attachment_id, 'full' );
$this->add_image_size();
$this->add_caption( $caption );
return $this->data;
}
/**
* If we can't find $url in our database, we output a simple ImageObject.
*
* @param string $url The image URL.
* @param string $caption A caption, if set.
*
* @return array $data Schema ImageObject array.
*/
public function simple_image_object( $url, $caption = '' ) {
$this->data['url'] = $url;
if ( ! empty( $caption ) ) {
$this->data['caption'] = $caption;
}
return $this->data;
}
/**
* Retrieves an image's caption if set, or uses the alt tag if that's set.
*
* @param string $caption The caption string, if there is one.
*
* @return void
*/
private function add_caption( $caption = '' ) {
if ( ! empty( $caption ) ) {
$this->data['caption'] = $caption;
return;
}
$caption = wp_get_attachment_caption();
if ( ! empty( $caption ) ) {
$this->data['caption'] = $caption;
return;
}
$caption = get_post_meta( $this->attachment_id, '_wp_attachment_image_alt', true );
if ( ! empty( $caption ) ) {
$this->data['caption'] = $caption;
}
return;
}
/**
* Generates our bare bone ImageObject.
*
* @return void
*/
private function generate_object() {
$this->data = array(
'@type' => 'ImageObject',
'@id' => $this->schema_id,
);
}
/**
* Adds image's width and height.
*
* @return void
*/
private function add_image_size() {
$image_meta = wp_get_attachment_metadata( $this->attachment_id );
if ( empty( $image_meta['width'] ) || empty( $image_meta['height'] ) ) {
return;
}
$this->data['width'] = $image_meta['width'];
$this->data['height'] = $image_meta['height'];
}
}

View File

@ -0,0 +1,109 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Organization data.
*
* @since 10.2
*/
class WPSEO_Schema_Organization implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determines whether an Organization graph piece should be added.
*
* @return bool
*/
public function is_needed() {
return ( $this->context->site_represents === 'company' );
}
/**
* Returns the Organization Schema data.
*
* @return array $data The Organization schema.
*/
public function generate() {
$data = array(
'@type' => 'Organization',
'@id' => $this->context->site_url . WPSEO_Schema_IDs::ORGANIZATION_HASH,
'name' => $this->context->company_name,
'url' => $this->context->site_url,
'sameAs' => $this->fetch_social_profiles(),
);
$data = $this->add_logo( $data );
return $data;
}
/**
* Adds a site's logo.
*
* @param array $data The Organization schema.
*
* @return array $data The Organization schema.
*/
private function add_logo( $data ) {
$logo = WPSEO_Options::get( 'company_logo', '' );
if ( empty( $logo ) ) {
return $data;
}
$id = $this->context->site_url . WPSEO_Schema_IDs::ORGANIZATION_LOGO_HASH;
$schema_image = new WPSEO_Schema_Image( $id );
$data['logo'] = $schema_image->generate_from_url( $logo, $this->context->company_name );
$data['image'] = array( '@id' => $id );
return $data;
}
/**
* Retrieve the social profiles to display in the organization schema.
*
* @since 1.8
*
* @link https://developers.google.com/webmasters/structured-data/customize/social-profiles
*
* @return array $profiles An array of social profiles.
*/
private function fetch_social_profiles() {
$profiles = array();
$social_profiles = array(
'facebook_site',
'instagram_url',
'linkedin_url',
'myspace_url',
'youtube_url',
'pinterest_url',
'wikipedia_url',
);
foreach ( $social_profiles as $profile ) {
if ( WPSEO_Options::get( $profile, '' ) !== '' ) {
$profiles[] = WPSEO_Options::get( $profile );
}
}
if ( WPSEO_Options::get( 'twitter_site', '' ) !== '' ) {
$profiles[] = 'https://twitter.com/' . WPSEO_Options::get( 'twitter_site' );
}
return $profiles;
}
}

View File

@ -0,0 +1,197 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Person data.
*
* @since 10.2
*/
class WPSEO_Schema_Person implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determine whether we should return Person schema.
*
* @return bool
*/
public function is_needed() {
if ( $this->context->site_represents === 'person' || is_author() ) {
return true;
}
return false;
}
/**
* Returns Person Schema data.
*
* @return bool|array Person data on success, false on failure.
*/
public function generate() {
$user_id = $this->determine_user_id();
if ( ! $user_id ) {
return false;
}
$data = $this->build_person_data( $user_id );
return $data;
}
/**
* Determines a User ID for the Person data.
*
* @return bool|int User ID or false upon return.
*/
protected function determine_user_id() {
$user_id = $this->context->site_user_id;
/**
* Filter: 'wpseo_schema_person_user_id' - Allows filtering of user ID used for person output.
*
* @api int|bool $user_id The user ID currently determined.
*/
return apply_filters( 'wpseo_schema_person_user_id', $user_id );
}
/**
* Retrieve a list of social profile URLs for Person.
*
* @param int $user_id User ID.
*
* @return array $output A list of social profiles.
*/
protected function get_social_profiles( $user_id ) {
$social_profiles = array(
'facebook',
'instagram',
'linkedin',
'pinterest',
'twitter',
'myspace',
'youtube',
'soundcloud',
'tumblr',
'wikipedia',
);
$output = array();
foreach ( $social_profiles as $profile ) {
$social_url = $this->url_social_site( $profile, $user_id );
if ( $social_url ) {
$output[] = $social_url;
}
}
return $output;
}
/**
* Builds our array of Schema Person data for a given user ID.
*
* @param int $user_id The user ID to use.
*
* @return array An array of Schema Person data.
*/
protected function build_person_data( $user_id ) {
$user_data = get_userdata( $user_id );
$data = array(
'@type' => 'Person',
'@id' => $this->determine_schema_id( $user_id ),
'name' => $user_data->display_name,
);
$data = $this->add_image( $data, $user_data );
if ( ! empty( $user_data->description ) ) {
$data['description'] = $user_data->description;
}
$social_profiles = $this->get_social_profiles( $user_id );
if ( is_array( $social_profiles ) ) {
$data['sameAs'] = $social_profiles;
}
return $data;
}
/**
* Returns an ImageObject for the persons avatar.
*
* @param array $data The Person schema.
* @param \WP_User $user_data User data.
*
* @return array $data The Person schema.
*/
protected function add_image( $data, $user_data ) {
$url = get_avatar_url( $user_data->user_email );
if ( empty( $url ) ) {
return $data;
}
$id = $this->context->site_url . WPSEO_Schema_IDs::PERSON_LOGO_HASH;
$schema_image = new WPSEO_Schema_Image( $id );
$data['image'] = $schema_image->simple_image_object( $url, $user_data->display_name );
return $data;
}
/**
* Returns the string to use in Schema's `@id`.
*
* @param int $user_id The user ID if we're on a user page.
*
* @return string The `@id` string value.
*/
protected function determine_schema_id( $user_id ) {
switch ( true ) {
case ( $this->context->site_represents === 'company' ):
$url = get_author_posts_url( $user_id );
break;
default:
$url = $this->context->site_url;
break;
}
return $url . WPSEO_Schema_IDs::PERSON_HASH;
}
/**
* Returns an author's social site URL.
*
* @param string $social_site The social site to retrieve the URL for.
* @param mixed $user_id The user ID to use function outside of the loop.
*
* @return string
*/
protected function url_social_site( $social_site, $user_id = false ) {
$url = get_the_author_meta( $social_site, $user_id );
if ( ! empty( $url ) ) {
switch ( $social_site ) {
case 'twitter':
$url = 'https://twitter.com/' . $url;
break;
}
}
return $url;
}
}

View File

@ -0,0 +1,158 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema WebPage data.
*
* @since 10.2
*/
class WPSEO_Schema_WebPage implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determines whether or not a piece should be added to the graph.
*
* @return bool
*/
public function is_needed() {
if ( is_404() ) {
return false;
}
return true;
}
/**
* Returns WebPage schema data.
*
* @return array WebPage schema data.
*/
public function generate() {
$data = array(
'@type' => $this->determine_page_type(),
'@id' => $this->context->canonical . WPSEO_Schema_IDs::WEBPAGE_HASH,
'url' => $this->context->canonical,
'inLanguage' => get_bloginfo( 'language' ),
'name' => $this->context->title,
'isPartOf' => array(
'@id' => $this->context->site_url . WPSEO_Schema_IDs::WEBSITE_HASH,
),
);
if ( is_front_page() ) {
$about_id = WPSEO_Schema_IDs::ORGANIZATION_HASH;
if ( $this->context->site_represents === 'person' ) {
$about_id = WPSEO_Schema_IDs::PERSON_HASH;
}
$data['about'] = array(
'@id' => $this->context->site_url . $about_id,
);
}
if ( is_singular() ) {
$data = $this->add_featured_image( $data );
$post = get_post( $this->context->id );
$data['datePublished'] = mysql2date( DATE_W3C, $post->post_date_gmt, false );
$data['dateModified'] = mysql2date( DATE_W3C, $post->post_modified_gmt, false );
}
if ( ! empty( $this->context->description ) ) {
$data['description'] = $this->context->description;
}
if ( $this->add_breadcrumbs() ) {
$data['breadcrumb'] = array(
'@id' => $this->context->canonical . WPSEO_Schema_IDs::BREADCRUMB_HASH,
);
}
return $data;
}
/**
* Determine if we should add a breadcrumb attribute.
*
* @return bool
*/
private function add_breadcrumbs() {
if ( is_front_page() ) {
return false;
}
if ( $this->context->breadcrumbs_enabled ) {
return true;
}
return false;
}
/**
* Determine the page type for the current page.
*
* @return string
*/
private function determine_page_type() {
switch ( true ) {
case is_search():
$type = 'SearchResultsPage';
break;
case is_author():
$type = 'ProfilePage';
break;
case is_archive():
$type = 'CollectionPage';
break;
default:
$type = 'WebPage';
}
/**
* Filter: 'wpseo_schema_webpage_type' - Allow changing the WebPage type.
*
* @api string $type The WebPage type.
*/
return apply_filters( 'wpseo_schema_webpage_type', $type );
}
/**
* Adds a featured image to the schema if there is one.
*
* @param array $data WebPage Schema.
*
* @return array $data WebPage Schema.
*/
private function add_featured_image( $data ) {
if ( ! has_post_thumbnail( $this->context->id ) ) {
return $data;
}
$id = $this->context->canonical . WPSEO_Schema_IDs::PRIMARY_IMAGE_HASH;
$schema_image = new WPSEO_Schema_Image( $id );
$data['image'] = $schema_image->generate_from_attachment_id( get_post_thumbnail_id() );
$data['primaryImageOfPage'] = array(
'@id' => $id,
);
return $data;
}
}

View File

@ -0,0 +1,125 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Returns schema Website data.
*
* @since 10.2
*/
class WPSEO_Schema_Website implements WPSEO_Graph_Piece {
/**
* A value object with context variables.
*
* @var WPSEO_Schema_Context
*/
private $context;
/**
* WPSEO_Schema_Breadcrumb constructor.
*
* @param WPSEO_Schema_Context $context A value object with context variables.
*/
public function __construct( WPSEO_Schema_Context $context ) {
$this->context = $context;
}
/**
* Determines whether or not a piece should be added to the graph.
*
* @return bool
*/
public function is_needed() {
return true;
}
/**
* Outputs code to allow recognition of the internal search engine.
*
* @since 1.5.7
*
* @link https://developers.google.com/structured-data/site-name
*
* @return array Website data blob.
*/
public function generate() {
$data = array(
'@type' => 'WebSite',
'@id' => $this->context->site_url . WPSEO_Schema_IDs::WEBSITE_HASH,
'url' => $this->context->site_url,
'name' => $this->context->site_name,
'publisher' => array(
'@id' => $this->get_publisher(),
),
);
$data = $this->add_alternate_name( $data );
$data = $this->internal_search_section( $data );
return $data;
}
/**
* Determine the ID based on Company Or Person settings.
*
* @return string
*/
private function get_publisher() {
if ( $this->context->site_represents === 'person' ) {
return $this->context->site_url . WPSEO_Schema_IDs::PERSON_HASH;
}
return $this->context->site_url . WPSEO_Schema_IDs::ORGANIZATION_HASH;
}
/**
* Returns an alternate name if one was specified in the Yoast SEO settings.
*
* @param array $data The website data array.
*
* @return array $data
*/
private function add_alternate_name( $data ) {
if ( '' !== WPSEO_Options::get( 'alternate_website_name', '' ) ) {
$data['alternateName'] = WPSEO_Options::get( 'alternate_website_name' );
}
return $data;
}
/**
* Adds the internal search JSON LD code to the homepage if it's not disabled.
*
* @link https://developers.google.com/structured-data/slsb-overview
*
* @param array $data The website data array.
*
* @return array $data
*/
private function internal_search_section( $data ) {
/**
* Filter: 'disable_wpseo_json_ld_search' - Allow disabling of the json+ld output.
*
* @api bool $display_search Whether or not to display json+ld search on the frontend.
*/
if ( ! apply_filters( 'disable_wpseo_json_ld_search', false ) ) {
/**
* Filter: 'wpseo_json_ld_search_url' - Allows filtering of the search URL for Yoast SEO.
*
* @api string $search_url The search URL for this site with a `{search_term_string}` variable.
*/
$search_url = apply_filters( 'wpseo_json_ld_search_url', $this->context->site_url . '?s={search_term_string}' );
$data['potentialAction'] = array(
'@type' => 'SearchAction',
'target' => $search_url,
'query-input' => 'required name=search_term_string',
);
}
return $data;
}
}

View File

@ -0,0 +1,106 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
/**
* Class WPSEO_Schema
*
* Outputs schema code specific for Google's JSON LD stuff.
*
* @since 1.8
*/
class WPSEO_Schema implements WPSEO_WordPress_Integration {
/**
* Registers the hooks.
*/
public function register_hooks() {
add_action( 'wpseo_head', array( $this, 'json_ld' ), 91 );
add_action( 'wpseo_json_ld', array( $this, 'generate' ), 1 );
}
/**
* JSON LD output function that the functions for specific code can hook into.
*
* @since 1.8
*/
public function json_ld() {
$deprecated_data = array(
'_deprecated' => 'Please use the "wpseo_schema_*" filters to extend the Yoast SEO schema data - see the WPSEO_Schema class.',
);
/**
* Filter: 'wpseo_json_ld_output' - Allows disabling Yoast's schema output entirely.
*
* @api mixed If false or an empty array is returned, disable our output.
*/
$return = apply_filters( 'wpseo_json_ld_output', $deprecated_data, '' );
if ( $return === array() || $return === false ) {
return;
}
do_action( 'wpseo_json_ld' );
}
/**
* Outputs the JSON LD code in a valid JSON+LD wrapper.
*
* @since 10.2
*
* @return void
*/
public function generate() {
$graph = array();
foreach ( $this->get_graph_pieces() as $piece ) {
if ( ! $piece->is_needed() ) {
continue;
}
$graph_piece = $piece->generate();
/**
* Filter: 'wpseo_schema_<class name>' - Allows changing graph piece output.
*
* @api array $graph_piece The graph piece to filter.
*/
$class = str_replace( 'wpseo_schema_', '', strtolower( get_class( $piece ) ) );
$graph_piece = apply_filters( 'wpseo_schema_' . $class, $graph_piece );
if ( is_array( $graph_piece ) ) {
$graph[] = $graph_piece;
}
}
WPSEO_Utils::schema_output( $graph, 'yoast-schema-graph yoast-schema-graph--main' );
}
/**
* Gets all the graph pieces we need.
*
* @return array A filtered array of graph pieces.
*/
private function get_graph_pieces() {
$context = new WPSEO_Schema_Context();
$pieces = array(
new WPSEO_Schema_Organization( $context ),
new WPSEO_Schema_Person( $context ),
new WPSEO_Schema_Website( $context ),
new WPSEO_Schema_WebPage( $context ),
new WPSEO_Schema_Breadcrumb( $context ),
new WPSEO_Schema_Article( $context ),
new WPSEO_Schema_Author( $context ),
);
/**
* Filter: 'wpseo_schema_graph_pieces' - Allows adding pieces to the graph.
*
* @param WPSEO_Schema_Context $context An object with context variables.
*
* @api array $pieces The schema pieces.
*/
return apply_filters( 'wpseo_schema_graph_pieces', $pieces, $context );
}
}

View File

@ -0,0 +1,29 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Frontend\Schema
*/
if ( ! interface_exists( 'WPSEO_Graph_Piece' ) ) {
/**
* An interface for registering Schema Graph Pieces.
*
* @since 10.2
*/
interface WPSEO_Graph_Piece {
/**
* Add your piece of the graph.
*
* @return array|bool $graph A graph piece on success, false on failure.
*/
public function generate();
/**
* Determines whether or not a piece should be added to the graph.
*
* @return bool
*/
public function is_needed();
}
}