first
This commit is contained in:
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class Classes_Surface.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*/
|
||||
class Classes_Surface {
|
||||
|
||||
/**
|
||||
* The dependency injection container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
public $container;
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The dependency injection container.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instance of a class. Handy for unhooking things.
|
||||
*
|
||||
* @param string $class_name The class to get the instance of.
|
||||
*
|
||||
* @return mixed The instance of the class.
|
||||
*/
|
||||
public function get( $class_name ) {
|
||||
return $this->container->get( $class_name );
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception;
|
||||
use Yoast\WP\SEO\Helpers;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class Helpers_Surface.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*
|
||||
* @property Helpers\Asset_Helper $asset
|
||||
* @property Helpers\Author_Archive_Helper $author_archive
|
||||
* @property Helpers\Blocks_Helper $blocks
|
||||
* @property Helpers\Capability_Helper $capability
|
||||
* @property Helpers\Current_Page_Helper $current_page
|
||||
* @property Helpers\Date_Helper $date
|
||||
* @property Helpers\Environment_Helper $environment
|
||||
* @property Helpers\First_Time_Configuration_Notice_Helper $first_time_configuration_notice
|
||||
* @property Helpers\Home_Url_Helper $home_url
|
||||
* @property Helpers\Image_Helper $image
|
||||
* @property Helpers\Indexable_Helper $indexable
|
||||
* @property Helpers\Indexing_Helper $indexing
|
||||
* @property Helpers\Input_Helper $input
|
||||
* @property Helpers\Language_Helper $language
|
||||
* @property Helpers\Meta_Helper $meta
|
||||
* @property Helpers\Notification_Helper $notification
|
||||
* @property Helpers\Options_Helper $options
|
||||
* @property Helpers\Pagination_Helper $pagination
|
||||
* @property Helpers\Permalink_Helper $permalink
|
||||
* @property Helpers\Post_Helper $post
|
||||
* @property Helpers\Post_Type_Helper $post_type
|
||||
* @property Helpers\Primary_Term_Helper $primary_term
|
||||
* @property Helpers\Product_Helper $product
|
||||
* @property Helpers\Redirect_Helper $redirect
|
||||
* @property Helpers\Request_Helper $request
|
||||
* @property Helpers\Require_File_Helper $require_file
|
||||
* @property Helpers\Robots_Helper $robots
|
||||
* @property Helpers\Short_Link_Helper $short_link
|
||||
* @property Helpers\Site_Helper $site
|
||||
* @property Helpers\String_Helper $string
|
||||
* @property Helpers\Social_Profiles_Helper $social_profiles
|
||||
* @property Helpers\Taxonomy_Helper $taxonomy
|
||||
* @property Helpers\Url_Helper $url
|
||||
* @property Helpers\User_Helper $user
|
||||
* @property Helpers\Woocommerce_Helper $woocommerce
|
||||
* @property Helpers\Wordpress_Helper $wordpress
|
||||
*/
|
||||
class Helpers_Surface {
|
||||
|
||||
/**
|
||||
* The DI container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* The open_graph helper namespace
|
||||
*
|
||||
* @var Open_Graph_Helpers_Surface
|
||||
*/
|
||||
public $open_graph;
|
||||
|
||||
/**
|
||||
* The schema helper namespace
|
||||
*
|
||||
* @var Schema_Helpers_Surface
|
||||
*/
|
||||
public $schema;
|
||||
|
||||
/**
|
||||
* The twitter helper namespace
|
||||
*
|
||||
* @var Twitter_Helpers_Surface
|
||||
*/
|
||||
public $twitter;
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The dependency injection container.
|
||||
* @param Open_Graph_Helpers_Surface $open_graph The OpenGraph helpers surface.
|
||||
* @param Schema_Helpers_Surface $schema The Schema helpers surface.
|
||||
* @param Twitter_Helpers_Surface $twitter The Twitter helpers surface.
|
||||
*/
|
||||
public function __construct(
|
||||
ContainerInterface $container,
|
||||
Open_Graph_Helpers_Surface $open_graph,
|
||||
Schema_Helpers_Surface $schema,
|
||||
Twitter_Helpers_Surface $twitter
|
||||
) {
|
||||
$this->container = $container;
|
||||
$this->open_graph = $open_graph;
|
||||
$this->schema = $schema;
|
||||
$this->twitter = $twitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for getting helper classes.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return mixed The helper class.
|
||||
*/
|
||||
public function __get( $helper ) {
|
||||
return $this->container->get( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset for ensuring helper exists.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return bool Whether the helper exists.
|
||||
*/
|
||||
public function __isset( $helper ) {
|
||||
return $this->container->has( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents setting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
* @param mixed $value The property value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Set is never meant to be called.
|
||||
*/
|
||||
public function __set( $name, $value ) { // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- __set must have a name and value - PHPCS #3715.
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_set_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents unsetting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Unset is never meant to be called.
|
||||
*/
|
||||
public function __unset( $name ) {
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_unset_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name from a helper slug
|
||||
*
|
||||
* @param string $helper The name of the helper.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_helper_class( $helper ) {
|
||||
$helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) );
|
||||
|
||||
return "Yoast\WP\SEO\Helpers\\{$helper}_Helper";
|
||||
}
|
||||
}
|
388
wp-content/plugins/wordpress-seo/src/surfaces/meta-surface.php
Normal file
388
wp-content/plugins/wordpress-seo/src/surfaces/meta-surface.php
Normal file
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use Yoast\WP\SEO\Context\Meta_Tags_Context;
|
||||
use Yoast\WP\SEO\Helpers\Indexable_Helper;
|
||||
use Yoast\WP\SEO\Memoizers\Meta_Tags_Context_Memoizer;
|
||||
use Yoast\WP\SEO\Models\Indexable;
|
||||
use Yoast\WP\SEO\Repositories\Indexable_Repository;
|
||||
use Yoast\WP\SEO\Surfaces\Values\Meta;
|
||||
use Yoast\WP\SEO\Wrappers\WP_Rewrite_Wrapper;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Meta_Surface class.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*/
|
||||
class Meta_Surface {
|
||||
|
||||
/**
|
||||
* The container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* The memoizer for the meta tags context.
|
||||
*
|
||||
* @var Meta_Tags_Context_Memoizer
|
||||
*/
|
||||
private $context_memoizer;
|
||||
|
||||
/**
|
||||
* The indexable repository.
|
||||
*
|
||||
* @var Indexable_Repository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* Holds the WP rewrite wrapper instance.
|
||||
*
|
||||
* @var WP_Rewrite_Wrapper
|
||||
*/
|
||||
private $wp_rewrite_wrapper;
|
||||
|
||||
/**
|
||||
* The indexable helper.
|
||||
*
|
||||
* @var Indexable_Helper
|
||||
*/
|
||||
private $indexable_helper;
|
||||
|
||||
/**
|
||||
* Meta_Surface constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The DI container.
|
||||
* @param Meta_Tags_Context_Memoizer $context_memoizer The meta tags context memoizer.
|
||||
* @param Indexable_Repository $indexable_repository The indexable repository.
|
||||
* @param WP_Rewrite_Wrapper $wp_rewrite_wrapper The WP rewrite wrapper.
|
||||
* @param Indexable_Helper $indexable_helper The indexable helper.
|
||||
*/
|
||||
public function __construct(
|
||||
ContainerInterface $container,
|
||||
Meta_Tags_Context_Memoizer $context_memoizer,
|
||||
Indexable_Repository $indexable_repository,
|
||||
WP_Rewrite_Wrapper $wp_rewrite_wrapper,
|
||||
Indexable_Helper $indexable_helper
|
||||
) {
|
||||
$this->container = $container;
|
||||
$this->context_memoizer = $context_memoizer;
|
||||
$this->repository = $indexable_repository;
|
||||
$this->wp_rewrite_wrapper = $wp_rewrite_wrapper;
|
||||
$this->indexable_helper = $indexable_helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for the current page.
|
||||
*
|
||||
* @return Meta The meta values.
|
||||
*/
|
||||
public function for_current_page() {
|
||||
return $this->build_meta( $this->context_memoizer->for_current_page() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for the home page.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_home_page() {
|
||||
$front_page_id = (int) \get_option( 'page_on_front' );
|
||||
if ( \get_option( 'show_on_front' ) === 'page' && $front_page_id !== 0 ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $front_page_id, 'post' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Home_Page' ) );
|
||||
}
|
||||
|
||||
$indexable = $this->repository->find_for_home_page();
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for the posts page.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_posts_page() {
|
||||
$posts_page_id = (int) \get_option( 'page_for_posts' );
|
||||
if ( $posts_page_id !== 0 ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $posts_page_id, 'post' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Posts_Page' ) );
|
||||
}
|
||||
|
||||
$indexable = $this->repository->find_for_home_page();
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for a post type archive.
|
||||
*
|
||||
* @param string|null $post_type Optional. The post type to get the archive meta for. Defaults to the current post type.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_post_type_archive( $post_type = null ) {
|
||||
if ( $post_type === null ) {
|
||||
$post_type = \get_post_type();
|
||||
}
|
||||
|
||||
$indexable = $this->repository->find_for_post_type_archive( $post_type );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type_Archive' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for the search result page.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_search_result() {
|
||||
$indexable = $this->repository->find_for_system_page( 'search-result' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Search_Result_Page' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for the search result page.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_404() {
|
||||
$indexable = $this->repository->find_for_system_page( '404' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Error_Page' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for a post.
|
||||
*
|
||||
* @param int $id The ID of the post.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_post( $id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $id, 'post' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for a number of posts.
|
||||
*
|
||||
* @param int[] $ids The IDs of the posts.
|
||||
*
|
||||
* @return Meta[]|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_posts( $ids ) {
|
||||
$indexables = $this->repository->find_by_multiple_ids_and_type( $ids, 'post' );
|
||||
|
||||
if ( empty( $indexables ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove all false values.
|
||||
$indexables = \array_filter( $indexables );
|
||||
|
||||
return \array_map(
|
||||
function( $indexable ) {
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) );
|
||||
},
|
||||
$indexables
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for a term.
|
||||
*
|
||||
* @param int $id The ID of the term.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_term( $id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $id, 'term' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Term_Archive' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for an author.
|
||||
*
|
||||
* @param int $id The ID of the author.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_author( $id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $id, 'user' );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, 'Author_Archive' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta for an indexable.
|
||||
*
|
||||
* @param Indexable $indexable The indexable.
|
||||
* @param string|null $page_type Optional. The page type if already known.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_indexable( $indexable, $page_type = null ) {
|
||||
|
||||
if ( ! \is_a( $indexable, Indexable::class ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( \is_null( $page_type ) ) {
|
||||
$page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta for an indexable.
|
||||
*
|
||||
* @param Indexable[] $indexables The indexables.
|
||||
* @param string|null $page_type Optional. The page type if already known.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_indexables( $indexables, $page_type = null ) {
|
||||
$closure = function( $indexable ) use ( $page_type ) {
|
||||
$this_page_type = $page_type;
|
||||
if ( \is_null( $this_page_type ) ) {
|
||||
$this_page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, $this_page_type ) );
|
||||
};
|
||||
|
||||
return \array_map( $closure, $indexables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta tags context for a url.
|
||||
*
|
||||
* @param string $url The url of the page. Required to be relative to the site url.
|
||||
*
|
||||
* @return Meta|false The meta values. False if none could be found.
|
||||
*/
|
||||
public function for_url( $url ) {
|
||||
$url_parts = \wp_parse_url( $url );
|
||||
$site_parts = \wp_parse_url( \site_url() );
|
||||
|
||||
if ( ( ! \is_array( $url_parts ) || ! \is_array( $site_parts ) )
|
||||
|| ! isset( $url_parts['host'], $url_parts['path'], $site_parts['host'], $site_parts['scheme'] )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $url_parts['host'] !== $site_parts['host'] ) {
|
||||
return false;
|
||||
}
|
||||
// Ensure the scheme is consistent with values in the DB.
|
||||
$url = $site_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
|
||||
|
||||
if ( $this->is_date_archive_url( $url ) ) {
|
||||
$indexable = $this->repository->find_for_date_archive();
|
||||
}
|
||||
else {
|
||||
$indexable = $this->repository->find_by_permalink( $url );
|
||||
}
|
||||
|
||||
// If we still don't have an indexable abort, the WP globals could be anything so we can't use the unknown indexable.
|
||||
if ( ! $indexable ) {
|
||||
return false;
|
||||
}
|
||||
$page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable );
|
||||
|
||||
if ( $page_type === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given URL is a date archive URL.
|
||||
*
|
||||
* @param string $url The url.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_date_archive_url( $url ) {
|
||||
$path = \wp_parse_url( $url, \PHP_URL_PATH );
|
||||
if ( $path === null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = \ltrim( $path, '/' );
|
||||
$wp_rewrite = $this->wp_rewrite_wrapper->get();
|
||||
$date_rewrite = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), \EP_DATE );
|
||||
$date_rewrite = \apply_filters( 'date_rewrite_rules', $date_rewrite );
|
||||
|
||||
foreach ( (array) $date_rewrite as $match => $query ) {
|
||||
if ( \preg_match( "#^$match#", $path ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new meta value object
|
||||
*
|
||||
* @param Meta_Tags_Context $context The meta tags context.
|
||||
*
|
||||
* @return Meta The meta value
|
||||
*/
|
||||
protected function build_meta( Meta_Tags_Context $context ) {
|
||||
return new Meta( $context, $this->container );
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception;
|
||||
use Yoast\WP\SEO\Helpers\Open_Graph;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class Open_Graph_Helpers_Surface.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*
|
||||
* @property Open_Graph\Image_Helper $image
|
||||
*/
|
||||
class Open_Graph_Helpers_Surface {
|
||||
|
||||
/**
|
||||
* The DI container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The dependency injection container.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for getting helper classes.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return mixed The helper class.
|
||||
*/
|
||||
public function __get( $helper ) {
|
||||
return $this->container->get( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset for ensuring helper exists.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return bool Whether the helper exists.
|
||||
*/
|
||||
public function __isset( $helper ) {
|
||||
return $this->container->has( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents setting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
* @param mixed $value The property value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Set is never meant to be called.
|
||||
*/
|
||||
public function __set( $name, $value ) { // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- __set must have a name and value - PHPCS #3715.
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_set_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents unsetting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Unset is never meant to be called.
|
||||
*/
|
||||
public function __unset( $name ) {
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_unset_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name from a helper slug
|
||||
*
|
||||
* @param string $helper The name of the helper.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_helper_class( $helper ) {
|
||||
$helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) );
|
||||
return "Yoast\WP\SEO\Helpers\Open_Graph\\{$helper}_Helper";
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception;
|
||||
use Yoast\WP\SEO\Helpers\Schema;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class Schema_Helpers_Surface.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*
|
||||
* @property Schema\Article_Helper $article
|
||||
* @property Schema\HTML_Helper $html
|
||||
* @property Schema\ID_Helper $id
|
||||
* @property Schema\Image_Helper $image
|
||||
* @property Schema\Language_Helper $language
|
||||
*/
|
||||
class Schema_Helpers_Surface {
|
||||
|
||||
/**
|
||||
* The DI container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* Helpers that should be fully capitalized.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $capitalized_helpers = [ 'html', 'id' ];
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The dependency injection container.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for getting helper classes.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return mixed The helper class.
|
||||
*/
|
||||
public function __get( $helper ) {
|
||||
return $this->container->get( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset for ensuring helper exists.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return bool Whether the helper exists.
|
||||
*/
|
||||
public function __isset( $helper ) {
|
||||
return $this->container->has( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents setting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
* @param mixed $value The property value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Set is never meant to be called.
|
||||
*/
|
||||
public function __set( $name, $value ) { // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- __set must have a name and value - PHPCS #3715.
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_set_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents unsetting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Unset is never meant to be called.
|
||||
*/
|
||||
public function __unset( $name ) {
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_unset_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name from a helper slug
|
||||
*
|
||||
* @param string $helper The name of the helper.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_helper_class( $helper ) {
|
||||
if ( \in_array( $helper, $this->capitalized_helpers, true ) ) {
|
||||
$helper = \strtoupper( $helper );
|
||||
}
|
||||
$helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) );
|
||||
return "Yoast\WP\SEO\Helpers\Schema\\{$helper}_Helper";
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces;
|
||||
|
||||
use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception;
|
||||
use Yoast\WP\SEO\Helpers\Twitter;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class Twitter_Helpers_Surface.
|
||||
*
|
||||
* Surface for the indexables.
|
||||
*
|
||||
* @property Twitter\Image_Helper $image
|
||||
*/
|
||||
class Twitter_Helpers_Surface {
|
||||
|
||||
/**
|
||||
* The DI container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param ContainerInterface $container The dependency injection container.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for getting helper classes.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return mixed The helper class.
|
||||
*/
|
||||
public function __get( $helper ) {
|
||||
return $this->container->get( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset for ensuring helper exists.
|
||||
*
|
||||
* @param string $helper The helper to get.
|
||||
*
|
||||
* @return bool Whether the helper exists.
|
||||
*/
|
||||
public function __isset( $helper ) {
|
||||
return $this->container->has( $this->get_helper_class( $helper ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents setting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
* @param mixed $value The property value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Set is never meant to be called.
|
||||
*/
|
||||
public function __set( $name, $value ) { // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- __set must have a name and value - PHPCS #3715.
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_set_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents unsetting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Unset is never meant to be called.
|
||||
*/
|
||||
public function __unset( $name ) {
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_unset_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name from a helper slug
|
||||
*
|
||||
* @param string $helper The name of the helper.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_helper_class( $helper ) {
|
||||
$helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) );
|
||||
return "Yoast\WP\SEO\Helpers\Twitter\\{$helper}_Helper";
|
||||
}
|
||||
}
|
331
wp-content/plugins/wordpress-seo/src/surfaces/values/meta.php
Normal file
331
wp-content/plugins/wordpress-seo/src/surfaces/values/meta.php
Normal file
@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Surfaces\Values;
|
||||
|
||||
use WPSEO_Replace_Vars;
|
||||
use Yoast\WP\SEO\Context\Meta_Tags_Context;
|
||||
use Yoast\WP\SEO\Exceptions\Forbidden_Property_Mutation_Exception;
|
||||
use Yoast\WP\SEO\Integrations\Front_End_Integration;
|
||||
use Yoast\WP\SEO\Models\Indexable;
|
||||
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;
|
||||
use Yoast\WP\SEO\Presenters\Rel_Next_Presenter;
|
||||
use Yoast\WP\SEO\Presenters\Rel_Prev_Presenter;
|
||||
use Yoast\WP\SEO\Surfaces\Helpers_Surface;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Meta value object.
|
||||
*
|
||||
* @property array $breadcrumbs The breadcrumbs array for the current page.
|
||||
* @property string $canonical The canonical URL for the current page.
|
||||
* @property string $company_name The company name from the Knowledge graph settings.
|
||||
* @property int $company_logo_id The attachment ID for the company logo.
|
||||
* @property string $description The meta description for the current page, if set.
|
||||
* @property int $estimated_reading_time_minutes The estimated reading time in minutes for posts.
|
||||
* @property Indexable $indexable The indexable object.
|
||||
* @property string $main_schema_id Schema ID that points to the main Schema thing on the page, usually the webpage or article Schema piece.
|
||||
* @property string $meta_description The meta description for the current page, if set.
|
||||
* @property string $open_graph_article_author The article:author value.
|
||||
* @property string $open_graph_article_modified_time The article:modified_time value.
|
||||
* @property string $open_graph_article_published_time The article:published_time value.
|
||||
* @property string $open_graph_article_publisher The article:publisher value.
|
||||
* @property string $open_graph_description The og:description.
|
||||
* @property bool $open_graph_enabled Whether OpenGraph is enabled on this site.
|
||||
* @property string $open_graph_fb_app_id The Facebook App ID.
|
||||
* @property array $open_graph_images The array of images we have for this page.
|
||||
* @property string $open_graph_locale The og:locale for the current page.
|
||||
* @property string $open_graph_publisher The OpenGraph publisher reference.
|
||||
* @property string $open_graph_site_name The og:site_name.
|
||||
* @property string $open_graph_title The og:title.
|
||||
* @property string $open_graph_type The og:type.
|
||||
* @property string $open_graph_url The og:url.
|
||||
* @property string $page_type The Schema page type.
|
||||
* @property array $robots An array of the robots values set for the current page.
|
||||
* @property string $rel_next The next page in the series, if any.
|
||||
* @property string $rel_prev The previous page in the series, if any.
|
||||
* @property array $schema The entire Schema array for the current page.
|
||||
* @property string $schema_page_type The Schema page type.
|
||||
* @property string $site_name The site name from the Yoast SEO settings.
|
||||
* @property string $site_represents Whether the site represents a 'person' or a 'company'.
|
||||
* @property array|false $site_represents_reference The schema reference ID for what this site represents.
|
||||
* @property string $site_url The site's main URL.
|
||||
* @property int $site_user_id If the site represents a 'person', this is the ID of the accompanying user profile.
|
||||
* @property string $title The SEO title for the current page.
|
||||
* @property string $twitter_card The Twitter card type for the current page.
|
||||
* @property string $twitter_creator The Twitter card author for the current page.
|
||||
* @property string $twitter_description The Twitter card description for the current page.
|
||||
* @property string $twitter_image The Twitter card image for the current page.
|
||||
* @property string $twitter_site The Twitter card site reference for the current page.
|
||||
* @property string $twitter_title The Twitter card title for the current page.
|
||||
* @property string $wordpress_site_name The site name from the WordPress settings.
|
||||
*/
|
||||
class Meta {
|
||||
|
||||
/**
|
||||
* The container.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The meta tags context.
|
||||
*
|
||||
* @var Meta_Tags_Context
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The front end integration.
|
||||
*
|
||||
* @var Front_End_Integration
|
||||
*/
|
||||
protected $front_end;
|
||||
|
||||
/**
|
||||
* The helpers surface.
|
||||
*
|
||||
* @var Helpers_Surface
|
||||
*/
|
||||
protected $helpers;
|
||||
|
||||
/**
|
||||
* The replace vars helper
|
||||
*
|
||||
* @var WPSEO_Replace_Vars
|
||||
*/
|
||||
protected $replace_vars;
|
||||
|
||||
/**
|
||||
* Collection of properties dynamically set via the magic __get() method.
|
||||
*
|
||||
* @var array<string, mixed> Key is the property name.
|
||||
*/
|
||||
private $properties_bin = [];
|
||||
|
||||
/**
|
||||
* Create a meta value object.
|
||||
*
|
||||
* @param Meta_Tags_Context $context The indexable presentation.
|
||||
* @param ContainerInterface $container The DI container.
|
||||
*/
|
||||
public function __construct(
|
||||
Meta_Tags_Context $context,
|
||||
ContainerInterface $container
|
||||
) {
|
||||
$this->container = $container;
|
||||
$this->context = $context;
|
||||
|
||||
$this->helpers = $this->container->get( Helpers_Surface::class );
|
||||
$this->replace_vars = $this->container->get( WPSEO_Replace_Vars::class );
|
||||
$this->front_end = $this->container->get( Front_End_Integration::class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output as would be presented in the head.
|
||||
*
|
||||
* @return object The HTML and JSON presentation of the head metadata.
|
||||
*/
|
||||
public function get_head() {
|
||||
$presenters = $this->get_presenters();
|
||||
|
||||
/** This filter is documented in src/integrations/front-end-integration.php */
|
||||
$presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context );
|
||||
|
||||
$html_output = '';
|
||||
$json_head_fields = [];
|
||||
|
||||
foreach ( $presenters as $presenter ) {
|
||||
$presenter->presentation = $presentation;
|
||||
$presenter->replace_vars = $this->replace_vars;
|
||||
$presenter->helpers = $this->helpers;
|
||||
|
||||
$html_output .= $this->create_html_presentation( $presenter );
|
||||
$json_field = $this->create_json_field( $presenter );
|
||||
|
||||
// Only use the output of presenters that could successfully present their data.
|
||||
if ( $json_field !== null && ! empty( $json_field->key ) ) {
|
||||
$json_head_fields[ $json_field->key ] = $json_field->value;
|
||||
}
|
||||
}
|
||||
$html_output = \trim( $html_output );
|
||||
|
||||
return (object) [
|
||||
'html' => $html_output,
|
||||
'json' => $json_head_fields,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for presenting values through the appropriate presenter, if it exists.
|
||||
*
|
||||
* @param string $name The property to get.
|
||||
*
|
||||
* @return mixed The value, as presented by the appropriate presenter.
|
||||
*/
|
||||
public function __get( $name ) {
|
||||
if ( \array_key_exists( $name, $this->properties_bin ) ) {
|
||||
return $this->properties_bin[ $name ];
|
||||
}
|
||||
|
||||
/** This filter is documented in src/integrations/front-end-integration.php */
|
||||
$presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context );
|
||||
|
||||
if ( ! isset( $presentation->{$name} ) ) {
|
||||
if ( isset( $this->context->{$name} ) ) {
|
||||
$this->properties_bin[ $name ] = $this->context->{$name};
|
||||
return $this->properties_bin[ $name ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
$presenter_namespace = 'Yoast\WP\SEO\Presenters\\';
|
||||
$parts = \explode( '_', $name );
|
||||
if ( $parts[0] === 'twitter' ) {
|
||||
$presenter_namespace .= 'Twitter\\';
|
||||
$parts = \array_slice( $parts, 1 );
|
||||
}
|
||||
elseif ( $parts[0] === 'open' && $parts[1] === 'graph' ) {
|
||||
$presenter_namespace .= 'Open_Graph\\';
|
||||
$parts = \array_slice( $parts, 2 );
|
||||
}
|
||||
|
||||
$presenter_class = $presenter_namespace . \implode( '_', \array_map( 'ucfirst', $parts ) ) . '_Presenter';
|
||||
|
||||
if ( \class_exists( $presenter_class ) ) {
|
||||
/**
|
||||
* The indexable presenter.
|
||||
*
|
||||
* @var Abstract_Indexable_Presenter
|
||||
*/
|
||||
$presenter = new $presenter_class();
|
||||
$presenter->presentation = $presentation;
|
||||
$presenter->helpers = $this->helpers;
|
||||
$presenter->replace_vars = $this->replace_vars;
|
||||
$value = $presenter->get();
|
||||
}
|
||||
else {
|
||||
$value = $presentation->{$name};
|
||||
}
|
||||
|
||||
$this->properties_bin[ $name ] = $value;
|
||||
return $this->properties_bin[ $name ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset for ensuring properties on the presentation are recognised.
|
||||
*
|
||||
* @param string $name The property to get.
|
||||
*
|
||||
* @return bool Whether or not the requested property exists.
|
||||
*/
|
||||
public function __isset( $name ) {
|
||||
if ( \array_key_exists( $name, $this->properties_bin ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isset( $this->context->presentation->{$name} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents setting dynamic properties and overwriting the value of declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
* @param mixed $value The property value.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Set is never meant to be called.
|
||||
*/
|
||||
public function __set( $name, $value ) { // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed -- __set must have a name and value - PHPCS #3715.
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_set_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents unsetting dynamic properties and unsetting declared properties
|
||||
* from an inaccessible context.
|
||||
*
|
||||
* @param string $name The property name.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Forbidden_Property_Mutation_Exception Unset is never meant to be called.
|
||||
*/
|
||||
public function __unset( $name ) {
|
||||
throw Forbidden_Property_Mutation_Exception::cannot_unset_because_property_is_immutable( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips all nested dependencies from the debug info.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __debugInfo() {
|
||||
return [ 'context' => $this->context ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all presenters.
|
||||
*
|
||||
* @return Abstract_Indexable_Presenter[]
|
||||
*/
|
||||
protected function get_presenters() {
|
||||
$presenters = $this->front_end->get_presenters( $this->context->page_type, $this->context );
|
||||
|
||||
if ( $this->context->page_type === 'Date_Archive' ) {
|
||||
/**
|
||||
* Define a filter that removes objects of type Rel_Next_Presenter or Rel_Prev_Presenter from a list.
|
||||
*
|
||||
* @param object $presenter The presenter to verify.
|
||||
*
|
||||
* @return bool True if the presenter is not a Rel_Next or Rel_Prev presenter.
|
||||
*/
|
||||
$callback = static function ( $presenter ) {
|
||||
return ! \is_a( $presenter, Rel_Next_Presenter::class )
|
||||
&& ! \is_a( $presenter, Rel_Prev_Presenter::class );
|
||||
};
|
||||
$presenters = \array_filter( $presenters, $callback );
|
||||
}
|
||||
|
||||
return $presenters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the presenter to create a line of HTML.
|
||||
*
|
||||
* @param Abstract_Indexable_Presenter $presenter The presenter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function create_html_presentation( $presenter ) {
|
||||
$presenter_output = $presenter->present();
|
||||
if ( ! empty( $presenter_output ) ) {
|
||||
return $presenter_output . \PHP_EOL;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a presenter's key and value to JSON.
|
||||
*
|
||||
* @param Abstract_Indexable_Presenter $presenter The presenter whose key and value are to be converted to JSON.
|
||||
*
|
||||
* @return object|null
|
||||
*/
|
||||
protected function create_json_field( $presenter ) {
|
||||
if ( $presenter->get_key() === 'NO KEY PROVIDED' ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = $presenter->get();
|
||||
if ( empty( $value ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (object) [
|
||||
'key' => $presenter->escape_key(),
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user