File "schema.php"

Full Path: /home/mahaadedsdfdfhfg/public_html/wp-content/plugins/yoast-test-helper/src/schema.php
File size: 7.02 KB
MIME-type: text/x-php
Charset: utf-8

<?php

namespace Yoast\WP\Test_Helper;

use WPSEO_Utils;

/**
 * Class to influence the Schema functionality of Yoast SEO (Premium).
 */
class Schema implements Integration {

	/**
	 * Holds our option instance.
	 *
	 * @var Option
	 */
	private $option;

	/**
	 * Class constructor.
	 *
	 * @param Option $option Our option array.
	 */
	public function __construct( Option $option ) {
		$this->option = $option;
	}

	/**
	 * Adds the required hooks for this class.
	 */
	public function add_hooks() {
		if ( $this->option->get( 'replace_schema_domain' ) === true ) {
			\add_filter( 'wpseo_debug_json_data', [ $this, 'replace_domain' ] );
		}

		if ( $this->option->get( 'enable_schema_endpoint' ) === true ) {
			\add_action( 'template_redirect', [ $this, 'send_json_ld' ] );
			\add_action( 'init', [ $this, 'init_rewrite' ] );
		}

		switch ( $this->option->get( 'is_needed_breadcrumb' ) ) {
			case 'show':
			case 'hide':
				\add_filter( 'wpseo_schema_needs_breadcrumb', [ $this, 'filter_is_needed_breadcrumb' ] );
				break;
			default:
				\remove_filter( 'wpseo_schema_needs_breadcrumb', [ $this, 'filter_is_needed_breadcrumb' ] );
				break;
		}

		switch ( $this->option->get( 'is_needed_webpage' ) ) {
			case 'show':
			case 'hide':
				\add_filter( 'wpseo_schema_needs_webpage', [ $this, 'filter_is_needed_webpage' ] );
				break;
			default:
				\remove_filter( 'wpseo_schema_needs_webpage', [ $this, 'filter_is_needed_webpage' ] );
				break;
		}

		\add_action( 'admin_post_yoast_seo_test_schema', [ $this, 'handle_submit' ] );
	}

	/**
	 * Registers the schema endpoint if needed.
	 */
	public function init_rewrite() {
		\add_rewrite_endpoint( 'schema', \EP_ALL );
	}

	/**
	 * Send the Yoast SEO Schema.
	 */
	public function send_json_ld() {
		global $wp_query;

		if ( ! isset( $wp_query->query_vars['schema'] ) ) {
			return;
		}

		\header( 'Content-Type: application/ld+json' );
		$url = \YoastSEO()->meta->for_current_page()->canonical;
		if ( ! empty( $url ) ) {
			\header( 'Link: <' . $url . '>; rel="canonical"' );
		}

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is our self generated Schema, no need for escaping.
		echo WPSEO_Utils::format_json_encode( \YoastSEO()->meta->for_current_page()->schema );
		exit;
	}

	/**
	 * Retrieves the controls.
	 *
	 * @return string The HTML to use to render the controls.
	 */
	public function get_controls() {
		$select_options = [
			'none' => \esc_html__( 'Don\'t influence', 'yoast-test-helper' ),
			'show' => \esc_html__( 'Always include', 'yoast-test-helper' ),
			'hide' => \esc_html__( 'Never include', 'yoast-test-helper' ),
		];

		$output = Form_Presenter::create_select(
			'is_needed_breadcrumb',
			\esc_html__( 'Influence the Breadcrumb Graph piece: ', 'yoast-test-helper' ),
			$select_options,
			$this->option->get( 'is_needed_breadcrumb' )
		);

		$output .= Form_Presenter::create_select(
			'is_needed_webpage',
			\esc_html__( 'Influence the WebPage Graph piece: ', 'yoast-test-helper' ),
			$select_options,
			$this->option->get( 'is_needed_webpage' )
		);

		$output .= Form_Presenter::create_checkbox(
			'replace_schema_domain',
			\esc_html__( 'Replace .test domain name with example.com in Schema output.', 'yoast-test-helper' ),
			$this->option->get( 'replace_schema_domain' )
		);

		$output .= Form_Presenter::create_checkbox(
			'enable_schema_endpoint',
			\sprintf(
				/* translators: %1$ss is replaced by `<code>/schema/</code>`, %2$s is replaced by `<code>?schema</code>`. */
				\esc_html__( 'Enable the Schema endpoint for every URL: suffix the URL with %1$s or %2$s to get the Schema for that URL, pretty printed.', 'yoast-test-helper' ),
				'<code>/schema/</code>',
				'<code>?schema</code>'
			),
			$this->option->get( 'enable_schema_endpoint' )
		);

		return Form_Presenter::get_html( \__( 'Schema', 'yoast-test-helper' ), 'yoast_seo_test_schema', $output );
	}

	/**
	 * Handles the form submit.
	 *
	 * @return void
	 */
	public function handle_submit() {
		if ( \check_admin_referer( 'yoast_seo_test_schema' ) !== false ) {
			$this->option->set( 'replace_schema_domain', isset( $_POST['replace_schema_domain'] ) );
			$this->option->set( 'enable_schema_endpoint', isset( $_POST['enable_schema_endpoint'] ) );
		}

		if ( isset( $_POST['is_needed_breadcrumb'] ) ) {
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- validation is done in validate_submit.
			$validated_is_needed_breadcrumb = $this->validate_submit( $_POST['is_needed_breadcrumb'] );
			$this->option->set( 'is_needed_breadcrumb', $validated_is_needed_breadcrumb );
		}

		if ( isset( $_POST['is_needed_webpage'] ) ) {
			// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- validation is done in validate_submit.
			$validated_is_needed_webpage = $this->validate_submit( $_POST['is_needed_webpage'] );
			$this->option->set( 'is_needed_webpage', $validated_is_needed_webpage );
		}

		\wp_safe_redirect( \self_admin_url( 'tools.php?page=' . \apply_filters( 'Yoast\WP\Test_Helper\admin_page', '' ) ) );
	}

	/**
	 * Makes sure we only store data we know how to deal with.
	 *
	 * @param string $value The submitted value.
	 *
	 * @return string The validated submit value.
	 */
	private function validate_submit( $value ) {
		$value = (string) $value;
		if ( \in_array( $value, [ 'none', 'show', 'hide' ], true ) ) {
			return $value;
		}
		return 'none';
	}

	/**
	 * Replaces your .test domain name with example.com in JSON output.
	 *
	 * @param array $data Data to replace the domain in.
	 *
	 * @return array Data to replace the domain in.
	 */
	public function replace_domain( $data ) {
		$source = WPSEO_Utils::get_home_url();
		$target = 'https://example.com';

		if ( $source[ ( \strlen( $source ) - 1 ) ] === '/' ) {
			$source = \substr( $source, 0, -1 );
		}

		return $this->array_value_str_replace( $source, $target, $data );
	}

	/**
	 * Returns the current breadcrumb option as boolean.
	 *
	 * @return bool
	 */
	public function filter_is_needed_breadcrumb() {
		return $this->option->get( 'is_needed_breadcrumb' ) === 'show';
	}

	/**
	 * Returns the current webpage option as boolean.
	 *
	 * @return bool
	 */
	public function filter_is_needed_webpage() {
		return $this->option->get( 'is_needed_webpage' ) === 'show';
	}

	/**
	 * Deep replaces strings in an array.
	 *
	 * @param string $needle      The needle to replace.
	 * @param string $replacement The replacement.
	 * @param array  $subject     The array to replace in.
	 *
	 * @return array The array with needle replaced by replacement in strings.
	 */
	private function array_value_str_replace( $needle, $replacement, $subject ) {
		if ( \is_array( $subject ) ) {
			foreach ( $subject as $key => $value ) {
				if ( \is_array( $value ) ) {
					$subject[ $key ] = $this->array_value_str_replace( $needle, $replacement, $subject[ $key ] );
				}
				elseif ( \strpos( $value, $needle ) !== false ) {
					$subject[ $key ] = \str_replace( $needle, $replacement, $value );
				}
			}
		}

		return $subject;
	}
}