Σ(゚Д゚;≡;゚д゚)Σ(゚Д゚;≡;゚д゚)Σ(゚Д゚;≡;゚д゚)始,故人唐宰相鲁公,🆚开府南服,余以布衣从戎。明年,别公漳水湄。后明年,公以事过张睢阳庙及颜杲卿所尝往来处,悲歌慷慨,卒不负其言而从之游。今其诗具在,可考也。😭 HEX
HEX
Server: Apache
System: Linux webm006.cluster120.gra.hosting.ovh.net 6.18.39-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Tue Jul 21 12:03:15 CEST 2026 x86_64
User: studionolh (122383)
PHP: 7.3.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/s/t/u/studionolh/www/wp-includes/Requests/Cookie/reusable-blocks/presenters.tar
url-list-presenter.php000064400000001727152335320000011035 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

/**
 * Presenter class for the URL list.
 */
class Url_List_Presenter extends Abstract_Presenter {

	/**
	 * A list of arrays containing titles and URLs.
	 *
	 * @var array
	 */
	private $links;

	/**
	 * Classname for the URL list.
	 *
	 * @var string
	 */
	private $class_name;

	/**
	 * Url_List_Presenter constructor.
	 *
	 * @param array  $links      A list of arrays containing titles and urls.
	 * @param string $class_name Classname for the url list.
	 */
	public function __construct( $links, $class_name = 'yoast-url-list' ) {
		$this->links      = $links;
		$this->class_name = $class_name;
	}

	/**
	 * Presents the URL list.
	 *
	 * @return string The URL list.
	 */
	public function present() {
		$output = '<ul class="' . $this->class_name . '">';
		foreach ( $this->links as $link ) {
			$output .= '<li><a href="' . $link['permalink'] . '">' . $link['title'] . '</a></li>';
		}
		$output .= '</ul>';
		return $output;
	}
}
googlebot-presenter.php000064400000003272152335320000011240 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

\_deprecated_file( \basename( __FILE__ ), 'WPSEO 14.9' );

/**
 * Presenter class for the googlebot output.
 */
class Googlebot_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * Returns the googlebot output.
	 *
	 * @deprecated 14.9 Values merged into the robots meta tag.
	 * @codeCoverageIgnore
	 *
	 * @return string The googlebot output tag.
	 */
	public function present() {
		\_deprecated_function( __METHOD__, 'WPSEO 14.9' );

		$googlebot = \implode( ', ', $this->get() );
		$googlebot = $this->filter( $googlebot );

		if ( \is_string( $googlebot ) && $googlebot !== '' ) {
			return \sprintf( '<meta name="googlebot" content="%s" />', \esc_attr( $googlebot ) );
		}

		return '';
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @deprecated 14.9 Values merged into the robots meta tag.
	 * @codeCoverageIgnore
	 *
	 * @return array The raw value.
	 */
	public function get() {
		\_deprecated_function( __METHOD__, 'WPSEO 14.9' );

		return $this->presentation->googlebot;
	}

	/**
	 * Run the googlebot output content through the `wpseo_googlebot` filter.
	 *
	 * @param string $googlebot The meta googlebot output to filter.
	 *
	 * @return string The filtered meta googlebot output.
	 */
	private function filter( $googlebot ) {
		/**
		 * Filter: 'wpseo_googlebot' - Allows filtering of the meta googlebot output of Yoast SEO.
		 *
		 * @api string $googlebot The meta googlebot directives to be echoed.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \apply_filters( 'wpseo_googlebot', $googlebot, $this->presentation );
	}
}
webmaster/bing-presenter.php000064400000001105152335320000012160 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Webmaster;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Bing Webmaster verification setting.
 */
class Bing_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'msvalidate.01';

	/**
	 * Retrieves the webmaster tool site verification value from the settings.
	 *
	 * @return string The webmaster tool site verification value.
	 */
	public function get() {
		return $this->helpers->options->get( 'msverify', '' );
	}
}
webmaster/yandex-presenter.php000064400000001123152335320000012531 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Webmaster;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Yandex Webmaster verification setting.
 */
class Yandex_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'yandex-verification';

	/**
	 * Retrieves the webmaster tool site verification value from the settings.
	 *
	 * @return string The webmaster tool site verification value.
	 */
	public function get() {
		return $this->helpers->options->get( 'yandexverify', '' );
	}
}
webmaster/google-presenter.php000064400000001135152335320000012520 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Webmaster;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Google Search Console verification setting.
 */
class Google_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'google-site-verification';

	/**
	 * Retrieves the webmaster tool site verification value from the settings.
	 *
	 * @return string The webmaster tool site verification value.
	 */
	public function get() {
		return $this->helpers->options->get( 'googleverify', '' );
	}
}
webmaster/baidu-presenter.php000064400000001132152335320000012325 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Webmaster;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Baidu Webmaster Tools verification setting.
 */
class Baidu_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'baidu-site-verification';

	/**
	 * Retrieves the webmaster tool site verification value from the settings.
	 *
	 * @return string The webmaster tool site verification value.
	 */
	public function get() {
		return $this->helpers->options->get( 'baiduverify', '' );
	}
}
webmaster/pinterest-presenter.php000064400000001130152335320000013254 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Webmaster;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Pinterest Webmaster verification setting.
 */
class Pinterest_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'p:domain_verify';

	/**
	 * Retrieves the webmaster tool site verification value from the settings.
	 *
	 * @return string The webmaster tool site verification value.
	 */
	public function get() {
		return $this->helpers->options->get( 'pinterestverify', '' );
	}
}
twitter/site-presenter.php000064400000003206152335320000011722 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter site tag.
 */
class Site_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:site';

	/**
	 * Run the Twitter site through the `wpseo_twitter_site` filter.
	 *
	 * @return string The filtered Twitter site.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_twitter_site' - Allow changing the Twitter site account as output in the Twitter card by Yoast SEO.
		 *
		 * @api string $twitter_site Twitter site account string.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		$twitter_site = \apply_filters( 'wpseo_twitter_site', $this->presentation->twitter_site, $this->presentation );
		$twitter_site = $this->get_twitter_id( $twitter_site );

		if ( ! \is_string( $twitter_site ) || $twitter_site === '' ) {
			return '';
		}

		return '@' . $twitter_site;
	}

	/**
	 * Checks if the given id is actually an id or a url and if url, distills the id from it.
	 *
	 * Solves issues with filters returning urls and theme's/other plugins also adding a user meta
	 * twitter field which expects url rather than an id (which is what we expect).
	 *
	 * @param string $id Twitter ID or url.
	 *
	 * @return string|bool Twitter ID or false if it failed to get a valid Twitter ID.
	 */
	private function get_twitter_id( $id ) {
		if ( \preg_match( '`([A-Za-z0-9_]{1,25})$`', $id, $match ) ) {
			return $match[1];
		}

		return false;
	}
}
twitter/image-presenter.php000064400000001725152335320000012044 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter image.
 */
class Image_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:image';

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'url';

	/**
	 * Run the Twitter image value through the `wpseo_twitter_image` filter.
	 *
	 * @return string The filtered Twitter image.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_twitter_image' - Allow changing the Twitter Card image.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 *
		 * @api string $twitter_image Image URL string.
		 */
		return (string) \apply_filters( 'wpseo_twitter_image', $this->presentation->twitter_image, $this->presentation );
	}
}
twitter/card-presenter.php000064400000001554152335320000011673 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter Card tag.
 */
class Card_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:card';

	/**
	 * Runs the card type through the `wpseo_twitter_card_type` filter.
	 *
	 * @return string The filtered card type.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_twitter_card_type' - Allow changing the Twitter card type.
		 *
		 * @api string $card_type The card type.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \trim( \apply_filters( 'wpseo_twitter_card_type', $this->presentation->twitter_card, $this->presentation ) );
	}
}
twitter/creator-presenter.php000064400000000753152335320000012421 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter creator.
 */
class Creator_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:creator';

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		return $this->presentation->twitter_creator;
	}
}
twitter/title-presenter.php000064400000001623152335320000012100 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter title.
 */
class Title_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:title';

	/**
	 * Run the Twitter title through replace vars and the `wpseo_twitter_title` filter.
	 *
	 * @return string The filtered Twitter title.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_twitter_title' - Allow changing the Twitter title.
		 *
		 * @api string $twitter_title The Twitter title.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \trim( \apply_filters( 'wpseo_twitter_title', $this->replace_vars( $this->presentation->twitter_title ), $this->presentation ) );
	}
}
twitter/description-presenter.php000064400000001774152335320000013311 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Twitter;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Twitter description.
 */
class Description_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:description';

	/**
	 * Run the Twitter description through replace vars and the `wpseo_twitter_description` filter.
	 *
	 * @return string The filtered Twitter description.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_twitter_description' - Allow changing the Twitter description as output in the Twitter card by Yoast SEO.
		 *
		 * @api string $twitter_description The description string.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \apply_filters( 'wpseo_twitter_description', $this->replace_vars( $this->presentation->twitter_description ), $this->presentation );
	}
}
abstract-indexable-tag-presenter.php000064400000003222152335320000013557 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

/**
 * Abstract presenter class for indexable tag presentations.
 *
 * @phpcs:disable Yoast.Files.FileName.InvalidClassFileName
 */
abstract class Abstract_Indexable_Tag_Presenter extends Abstract_Indexable_Presenter {

	const META_PROPERTY_CONTENT = '<meta property="%2$s" content="%1$s" />';
	const META_NAME_CONTENT     = '<meta name="%2$s" content="%1$s" />';
	const LINK_REL_HREF         = '<link rel="%2$s" href="%1$s" />';
	const DEFAULT_TAG_FORMAT    = self::META_NAME_CONTENT;

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::DEFAULT_TAG_FORMAT;

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'attribute';

	/**
	 * Returns a tag in the head.
	 *
	 * @return string The tag.
	 */
	public function present() {
		$value = $this->get();

		if ( ! \is_string( $value ) || $value === '' ) {
			return '';
		}

		/**
		 * There may be some classes that are derived from this class that do not use the $key property
		 * in their $tag_format string. In that case the key property will simply not be used.
		 */
		return \sprintf(
			$this->tag_format,
			$this->escape_value( $value ),
			$this->key
		);
	}

	/**
	 * Escaped the output.
	 *
	 * @param string $value The desired method of escaping; 'html', 'url' or 'attribute'.
	 *
	 * @return string The escaped value.
	 */
	protected function escape_value( $value ) {
		switch ( $this->escaping ) {
			case 'html':
				return \esc_html( $value );
			case 'url':
				return \esc_url( $value, null, 'attribute' );
			case 'attribute':
			default:
				return \esc_attr( $value );
		}
	}
}
bingbot-presenter.php000064400000003212152335320000010675 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

\_deprecated_file( \basename( __FILE__ ), 'WPSEO 14.9' );

/**
 * Presenter class for the bingbot output.
 */
class Bingbot_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * Returns the bingbot output.
	 *
	 * @deprecated 14.9 Values merged into the robots meta tag.
	 * @codeCoverageIgnore
	 *
	 * @return string The bingbot output tag.
	 */
	public function present() {
		\_deprecated_function( __METHOD__, 'WPSEO 14.9' );

		$bingbot = \implode( ', ', $this->get() );
		$bingbot = $this->filter( $bingbot );

		if ( \is_string( $bingbot ) && $bingbot !== '' ) {
			return \sprintf( '<meta name="bingbot" content="%s" />', \esc_attr( $bingbot ) );
		}

		return '';
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @deprecated 14.9 Values merged into the robots meta tag.
	 * @codeCoverageIgnore
	 *
	 * @return array The raw value.
	 */
	public function get() {
		\_deprecated_function( __METHOD__, 'WPSEO 14.9' );

		return $this->presentation->bingbot;
	}

	/**
	 * Run the bingbot output content through the `wpseo_bingbot` filter.
	 *
	 * @param string $bingbot The meta bingbot output to filter.
	 *
	 * @return string The filtered meta bingbot output.
	 */
	private function filter( $bingbot ) {
		/**
		 * Filter: 'wpseo_bingbot' - Allows filtering of the meta bingbot output of Yoast SEO.
		 *
		 * @api string $bingbot The meta bingbot directives to be echoed.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \apply_filters( 'wpseo_bingbot', $bingbot, $this->presentation );
	}
}
debug/marker-open-presenter.php000064400000003110152335320000012554 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Debug;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;

/**
 * Presenter class for the debug open marker.
 */
final class Marker_Open_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * Returns the debug close marker.
	 *
	 * @return string The debug close marker.
	 */
	public function present() {
		/**
		 * Filter: 'wpseo_debug_markers' - Allow disabling the debug markers.
		 *
		 * @api bool $show_markers True when the debug markers should be shown.
		 */
		if ( ! \apply_filters( 'wpseo_debug_markers', true ) ) {
			return '';
		}
		$version_info = 'v' . \WPSEO_VERSION;

		if ( $this->helpers->product->is_premium() ) {
			$version_info = $this->construct_version_info();
		}

		return \sprintf(
			'<!-- This site is optimized with the %1$s %2$s - https://yoast.com/wordpress/plugins/seo/ -->',
			\esc_html( $this->helpers->product->get_name() ),
			$version_info
		);
	}

	/**
	 * Gets the plugin version information, including the free version if Premium is used.
	 *
	 * @return string The constructed version information.
	 */
	private function construct_version_info() {
		/**
		 * Filter: 'wpseo_hide_version' - can be used to hide the Yoast SEO version in the debug marker (only available in Yoast SEO Premium).
		 *
		 * @api bool
		 */
		if ( \apply_filters( 'wpseo_hide_version', false ) ) {
			return '';
		}

		return 'v' . \WPSEO_PREMIUM_VERSION . ' (Yoast SEO v' . \WPSEO_VERSION . ')';
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		return '';
	}
}
debug/marker-close-presenter.php000064400000001503152335320000012724 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Debug;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;

/**
 * Presenter class for the debug close marker.
 */
final class Marker_Close_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * Returns the debug close marker.
	 *
	 * @return string The debug close marker.
	 */
	public function present() {
		/**
		 * Filter: 'wpseo_debug_markers' - Allow disabling the debug markers.
		 *
		 * @api bool $show_markers True when the debug markers should be shown.
		 */
		if ( ! \apply_filters( 'wpseo_debug_markers', true ) ) {
			return '';
		}

		return \sprintf(
			'<!-- / %s. -->',
			\esc_html( $this->helpers->product->get_name() )
		);
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		return '';
	}
}
open-graph/url-presenter.php000064400000002133152335320000012114 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph URL.
 */
class Url_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:url';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'attribute';

	/**
	 * Run the url content through the `wpseo_opengraph_url` filter.
	 *
	 * @return string The filtered url.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_opengraph_url' - Allow changing the Yoast SEO generated open graph URL.
		 *
		 * @api string $url The open graph URL.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \urldecode( (string) \apply_filters( 'wpseo_opengraph_url', $this->presentation->open_graph_url, $this->presentation ) );
	}
}
open-graph/title-presenter.php000064400000002170152335320000012434 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph title.
 */
class Title_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:title';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the title content through replace vars, the `wpseo_opengraph_title` filter and sanitization.
	 *
	 * @return string The filtered title.
	 */
	public function get() {
		$title = $this->replace_vars( $this->presentation->open_graph_title );
		/**
		 * Filter: 'wpseo_opengraph_title' - Allow changing the Yoast SEO generated title.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 *
		 * @api string $title The title.
		 */
		$title = (string) \trim( \apply_filters( 'wpseo_opengraph_title', $title, $this->presentation ) );
		return $this->helpers->string->strip_all_tags( $title );
	}
}
open-graph/article-published-time-presenter.php000064400000001250152335320000015645 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph article published time.
 */
class Article_Published_Time_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'article:published_time';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		return $this->presentation->open_graph_article_published_time;
	}
}
open-graph/type-presenter.php000064400000001735152335320000012302 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph type.
 */
class Type_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:type';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the opengraph type content through the `wpseo_opengraph_type` filter.
	 *
	 * @return string The filtered type.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_opengraph_type' - Allow changing the opengraph type.
		 *
		 * @api string $type The type.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \apply_filters( 'wpseo_opengraph_type', $this->presentation->open_graph_type, $this->presentation );
	}
}
open-graph/article-author-presenter.php000064400000002237152335320000014242 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph article author.
 */
class Article_Author_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'article:author';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the article author's Facebook URL through the `wpseo_opengraph_author_facebook` filter.
	 *
	 * @return string The filtered article author's Facebook URL.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_opengraph_author_facebook' - Allow developers to filter the article author's Facebook URL.
		 *
		 * @api bool|string $article_author The article author's Facebook URL, return false to disable.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \trim( \apply_filters( 'wpseo_opengraph_author_facebook', $this->presentation->open_graph_article_author, $this->presentation ) );
	}
}
open-graph/site-name-presenter.php000064400000002046152335320000013177 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph site name.
 */
class Site_Name_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:site_name';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Runs the site name through the `wpseo_opengraph_site_name` filter.
	 *
	 * @return string The filtered site_name.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_opengraph_site_name' - Allow changing the Yoast SEO generated Open Graph site name.
		 *
		 * @api string $site_name The site_name.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \trim( \apply_filters( 'wpseo_opengraph_site_name', $this->presentation->open_graph_site_name, $this->presentation ) );
	}
}
open-graph/article-publisher-presenter.php000064400000002253152335320000014733 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph article publisher.
 */
class Article_Publisher_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'article:publisher';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the article publisher's Facebook URL through the `wpseo_og_article_publisher` filter.
	 *
	 * @return string The filtered article publisher's Facebook URL.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_og_article_publisher' - Allow developers to filter the article publisher's Facebook URL.
		 *
		 * @api bool|string $article_publisher The article publisher's Facebook URL, return false to disable.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \trim( \apply_filters( 'wpseo_og_article_publisher', $this->presentation->open_graph_article_publisher, $this->presentation ) );
	}
}
open-graph/description-presenter.php000064400000002437152335320000013644 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph description.
 */
class Description_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:description';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the Open Graph description through replace vars and the `wpseo_opengraph_desc` filter and sanitization.
	 *
	 * @return string The filtered description.
	 */
	public function get() {
		$meta_og_description = $this->replace_vars( $this->presentation->open_graph_description );

		/**
		 * Filter: 'wpseo_opengraph_desc' - Allow changing the Yoast SEO generated Open Graph description.
		 *
		 * @api string The description.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		$meta_og_description = \apply_filters( 'wpseo_opengraph_desc', $meta_og_description, $this->presentation );
		$meta_og_description = $this->helpers->string->strip_all_tags( \stripslashes( $meta_og_description ) );
		return \trim( $meta_og_description );
	}
}
open-graph/image-presenter.php000064400000004547152335320000012407 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;

/**
 * Presenter class for the Open Graph image.
 */
class Image_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:image';

	/**
	 * Image tags that we output for each image.
	 *
	 * @var array
	 */
	protected static $image_tags = [
		'width'     => 'width',
		'height'    => 'height',
		'type'      => 'type',
	];

	/**
	 * Returns the image for a post.
	 *
	 * @return string The image tag.
	 */
	public function present() {
		$images = $this->get();

		if ( empty( $images ) ) {
			return '';
		}

		$return = '';
		foreach ( $images as $image_index => $image_meta ) {
			$image_url = $image_meta['url'];

			$return .= '<meta property="og:image" content="' . \esc_url( $image_url, null, 'attribute' ) . '" />';

			foreach ( static::$image_tags as $key => $value ) {
				if ( empty( $image_meta[ $key ] ) ) {
					continue;
				}

				$return .= \PHP_EOL . "\t" . '<meta property="og:image:' . \esc_attr( $key ) . '" content="' . \esc_attr( $image_meta[ $key ] ) . '" />';
			}
		}

		return $return;
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return array The raw value.
	 */
	public function get() {
		$images = [];

		foreach ( $this->presentation->open_graph_images as $open_graph_image ) {
			$images[] = \array_intersect_key(
				// First filter the object.
				$this->filter( $open_graph_image ),
				// Then strip all keys that aren't in the image tags or the url.
				\array_flip( \array_merge( static::$image_tags, [ 'url' ] ) )
			);
		}

		return \array_filter( $images );
	}

	/**
	 * Run the image content through the `wpseo_opengraph_image` filter.
	 *
	 * @param array $image The image.
	 *
	 * @return array The filtered image.
	 */
	protected function filter( $image ) {
		/**
		 * Filter: 'wpseo_opengraph_image' - Allow changing the Open Graph image.
		 *
		 * @api string - The URL of the Open Graph image.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		$image_url = \trim( \apply_filters( 'wpseo_opengraph_image', $image['url'], $this->presentation ) );
		if ( ! empty( $image_url ) && \is_string( $image_url ) ) {
			$image['url'] = $image_url;
		}

		return $image;
	}
}
open-graph/article-modified-time-presenter.php000064400000001244152335320000015451 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Presenter class for the Open Graph article modified time.
 */
class Article_Modified_Time_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'article:modified_time';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		return $this->presentation->open_graph_article_modified_time;
	}
}
open-graph/locale-presenter.php000064400000001754152335320000012561 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Open_Graph;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter;

/**
 * Final presenter class for the Open Graph locale.
 */
final class Locale_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'og:locale';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::META_PROPERTY_CONTENT;

	/**
	 * Run the locale through the `wpseo_og_locale` filter.
	 *
	 * @return string The filtered locale.
	 */
	public function get() {
		/**
		 * Filter: 'wpseo_og_locale' - Allow changing the Yoast SEO Open Graph locale.
		 *
		 * @api string The locale string
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \trim( \apply_filters( 'wpseo_og_locale', $this->presentation->open_graph_locale, $this->presentation ) );
	}
}
meta-description-presenter.php000064400000003534152335320000012527 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the meta description.
 */
class Meta_Description_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'description';

	/**
	 * Returns the meta description for a post.
	 *
	 * @return string The meta description tag.
	 */
	public function present() {
		$output = parent::present();

		if ( ! empty( $output ) ) {
			return $output;
		}

		if ( \current_user_can( 'wpseo_manage_options' ) ) {
			return '<!-- ' .
				\sprintf(
					/* Translators: %1$s resolves to the SEO menu item, %2$s resolves to the Search Appearance submenu item. */
					\esc_html__( 'Admin only notice: this page does not show a meta description because it does not have one, either write it for this page specifically or go into the [%1$s - %2$s] menu and set up a template.', 'wordpress-seo' ),
					\esc_html__( 'SEO', 'wordpress-seo' ),
					\esc_html__( 'Search Appearance', 'wordpress-seo' )
				) .
				' -->';
		}

		return '';
	}

	/**
	 * Run the meta description content through replace vars, the `wpseo_metadesc` filter and sanitization.
	 *
	 * @return string The filtered meta description.
	 */
	public function get() {
		$meta_description = $this->replace_vars( $this->presentation->meta_description );

		/**
		 * Filter: 'wpseo_metadesc' - Allow changing the Yoast SEO meta description sentence.
		 *
		 * @api string $meta_description The description sentence.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		$meta_description = \apply_filters( 'wpseo_metadesc', $meta_description, $this->presentation );
		$meta_description = $this->helpers->string->strip_all_tags( \stripslashes( $meta_description ) );
		return \trim( $meta_description );
	}
}
abstract-presenter.php000064400000000571152335320000011061 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

/**
 * Abstract_Presenter class.
 */
abstract class Abstract_Presenter {

	/**
	 * Returns the output as string.
	 *
	 * @return string The output.
	 */
	abstract public function present();

	/**
	 * Returns the output as string.
	 *
	 * @return string The output.
	 */
	public function __toString() {
		return $this->present();
	}
}
rel-next-presenter.php000064400000003160152335320000011011 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the rel next meta tag.
 */
class Rel_Next_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'next';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::LINK_REL_HREF;

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'url';

	/**
	 * Returns the rel next meta tag.
	 *
	 * @return string The rel next tag.
	 */
	public function present() {
		$output = parent::present();

		if ( ! empty( $output ) ) {
			/**
			 * Filter: 'wpseo_next_rel_link' - Allow changing link rel output by Yoast SEO.
			 *
			 * @api string $unsigned The full `<link` element.
			 */
			return \apply_filters( 'wpseo_next_rel_link', $output );
		}

		return '';
	}

	/**
	 * Run the canonical content through the `wpseo_adjacent_rel_url` filter.
	 *
	 * @return string The filtered adjacent link.
	 */
	public function get() {
		if ( \in_array( 'noindex', $this->presentation->robots, true ) ) {
			return '';
		}

		/**
		 * Filter: 'wpseo_adjacent_rel_url' - Allow filtering of the rel next URL put out by Yoast SEO.
		 *
		 * @api string $rel_next The rel next URL.
		 *
		 * @param string                 $rel          Link relationship, prev or next.
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return (string) \trim( \apply_filters( 'wpseo_adjacent_rel_url', $this->presentation->rel_next, 'next', $this->presentation ) );
	}
}
slack/enhanced-data-presenter.php000064400000003761152335320000013033 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Slack;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;

/**
 * Presenter class for the Slack enhanced data.
 */
class Enhanced_Data_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'twitter:misc';

	/**
	 * Presents the enhanced data for Slack
	 *
	 * @return string The Twitter tags for Slack.
	 */
	public function present() {
		$enhanced_data = $this->get();
		$twitter_tags  = '';
		$i             = 1;
		foreach ( $enhanced_data as $label => $value ) {
			$twitter_tags .= \sprintf( "\t" . '<meta name="twitter:label%1$d" content="%2$s" />' . "\n", $i, $label );
			$twitter_tags .= \sprintf( "\t" . '<meta name="twitter:data%1$d" content="%2$s" />' . "\n", $i, $value );
			++$i;
		}

		return \trim( $twitter_tags );
	}

	/**
	 * Gets the enhanced data array.
	 *
	 * @return array The enhanced data array
	 */
	public function get() {
		$data                   = [];
		$author_id              = $this->presentation->source->post_author;
		$estimated_reading_time = $this->presentation->estimated_reading_time_minutes;

		if ( $this->presentation->model->object_sub_type === 'post' && $author_id ) {
			$data[ \__( 'Written by', 'wordpress-seo' ) ] = \get_the_author_meta( 'display_name', $author_id );
		}

		if ( ! empty( $estimated_reading_time ) ) {
			/* translators: %s expands to the reading time number, in minutes */
			$data[ \__( 'Est. reading time', 'wordpress-seo' ) ] = \sprintf( \_n( '%s minute', '%s minutes', $estimated_reading_time, 'default' ), $estimated_reading_time );
		}

		/**
		 * Filter: 'wpseo_enhanced_slack_data' - Allows filtering of the enhanced data for sharing on Slack.
		 *
		 * @api array $data The enhanced Slack sharing data.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \apply_filters( 'wpseo_enhanced_slack_data', $data, $this->presentation );
	}
}
admin/indexing-notification-presenter.php000064400000011513152335320000014635 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Config\Indexing_Reasons;
use Yoast\WP\SEO\Helpers\Short_Link_Helper;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Class Indexing_Notification_Presenter.
 *
 * @package Yoast\WP\SEO\Presenters\Admin
 */
class Indexing_Notification_Presenter extends Abstract_Presenter {

	/**
	 * The total number of unindexed objects.
	 *
	 * @var int
	 */
	protected $total_unindexed;

	/**
	 * The message to show in the notification.
	 *
	 * @var string
	 */
	protected $reason;

	/**
	 * The short link helper.
	 *
	 * @var Short_Link_Helper
	 */
	protected $short_link_helper;

	/**
	 * Indexing_Notification_Presenter constructor.
	 *
	 * @param Short_Link_Helper $short_link_helper The short link helper.
	 * @param int               $total_unindexed   Total number of unindexed objects.
	 * @param string            $reason            The reason to show in the notification.
	 */
	public function __construct( $short_link_helper, $total_unindexed, $reason ) {
		$this->short_link_helper = $short_link_helper;
		$this->total_unindexed   = $total_unindexed;
		$this->reason            = $reason;
	}

	/**
	 * Returns the notification as an HTML string.
	 *
	 * @return string The HTML string representation of the notification.
	 */
	public function present() {
		$notification_text  = '<p>' . $this->get_message( $this->reason ) . '</p>';
		$notification_text .= '<p>' . $this->get_time_estimate( $this->total_unindexed ) . '</p>';
		$notification_text .= '<a class="button" href="' . \get_admin_url( null, 'admin.php?page=wpseo_tools&start-indexation=true' ) . '">';
		$notification_text .= \esc_html__( 'Start SEO data optimization', 'wordpress-seo' );
		$notification_text .= '</a>';

		return $notification_text;
	}

	/**
	 * Determines the message to show in the indexing notification.
	 *
	 * @param string $reason The reason identifier.
	 *
	 * @return string The message to show in the notification.
	 */
	protected function get_message( $reason ) {
		switch ( $reason ) {
			case Indexing_Reasons::REASON_PERMALINK_SETTINGS:
				$text = \esc_html__( 'Because of a change in your permalink structure, some of your SEO data needs to be reprocessed.', 'wordpress-seo' );
				break;
			case Indexing_Reasons::REASON_HOME_URL_OPTION:
				$text = \esc_html__( 'Because of a change in your home URL setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' );
				break;
			case Indexing_Reasons::REASON_CATEGORY_BASE_PREFIX:
				$text = \esc_html__( 'Because of a change in your category base setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' );
				break;
			case Indexing_Reasons::REASON_TAG_BASE_PREFIX:
				$text = \esc_html__( 'Because of a change in your tag base setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' );
				break;
			default:
				$text = \esc_html__( 'You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. ', 'wordpress-seo' );
		}

		/**
		 * Filter: 'wpseo_indexables_indexation_alert' - Allow developers to filter the reason of the indexation
		 *
		 * @param string $text   The text to show as reason.
		 * @param string $reason The reason value.
		 */
		return (string) \apply_filters( 'wpseo_indexables_indexation_alert', $text, $reason );
	}

	/**
	 * Creates a time estimate based on the total number on unindexed objects.
	 *
	 * @param int $total_unindexed The total number of unindexed objects.
	 *
	 * @return string The time estimate as a HTML string.
	 */
	protected function get_time_estimate( $total_unindexed ) {
		if ( $total_unindexed < 400 ) {
			return \esc_html__( 'We estimate this will take less than a minute.', 'wordpress-seo' );
		}

		if ( $total_unindexed < 2500 ) {
			return \esc_html__( 'We estimate this will take a couple of minutes.', 'wordpress-seo' );
		}

		$estimate  = \esc_html__( 'We estimate this could take a long time, due to the size of your site. As an alternative to waiting, you could:', 'wordpress-seo' );
		$estimate .= '<ul class="ul-disc">';
		$estimate .= '<li>';
		$estimate .= \sprintf(
			/* translators: 1: Expands to Yoast SEO */
			\esc_html__( 'Wait for a week or so, until %1$s automatically processes most of your content in the background.', 'wordpress-seo' ),
			'Yoast SEO'
		);
		$estimate .= '</li>';
		$estimate .= '<li>';
		$estimate .= \sprintf(
			/* translators: 1: Link to article about indexation command, 2: Anchor closing tag, 3: Link to WP CLI. */
			\esc_html__( '%1$sRun the indexation process on your server%2$s using %3$sWP CLI%2$s.', 'wordpress-seo' ),
			'<a href="' . \esc_url( $this->short_link_helper->get( 'https://yoa.st/3-w' ) ) . '" target="_blank">',
			'</a>',
			'<a href="https://wp-cli.org/" target="_blank">'
		);

		$estimate .= '</li>';
		$estimate .= '</ul>';

		return $estimate;
	}
}
admin/migration-error-presenter.php000064400000003634152335320000013471 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Shortlinker;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Presenter class for the migration error.
 */
class Migration_Error_Presenter extends Abstract_Presenter {

	/**
	 * Holds the migration error.
	 *
	 * The array holds the following values if filled:
	 * - int|false $time    The timestamp.
	 * - string    $version The Yoast SEO version.
	 * - string    $message The error message.
	 *
	 * @var array
	 */
	protected $migration_error;

	/**
	 * Migration_Error_Presenter constructor.
	 *
	 * @param array $migration_error The migration error.
	 */
	public function __construct( $migration_error ) {
		$this->migration_error = $migration_error;
	}

	/**
	 * Presents the migration error that occurred.
	 *
	 * @return string The error HTML.
	 */
	public function present() {
		$message = \sprintf(
			/* translators: %s: Yoast SEO. */
			\esc_html__( '%s had problems creating the database tables needed to speed up your site.', 'wordpress-seo' ),
			'Yoast SEO'
		);
		$support = \sprintf(
			/* translators: %1$s: link to help article about solving table issue. %2$s: is anchor closing. */
			\esc_html__( 'Please read %1$sthis help article%2$s to find out how to resolve this problem.', 'wordpress-seo' ),
			'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/3-6' ) . '">',
			'</a>'
		);
		$reassurance = \sprintf(
			/* translators: %s: Yoast SEO. */
			\esc_html__( 'Your site will continue to work normally, but won\'t take full advantage of %s.', 'wordpress-seo' ),
			'Yoast SEO'
		);

		$debug_info = \sprintf(
			'<details><summary>%1$s</summary><p>%2$s</p></details>',
			\esc_html__( 'Show debug information', 'wordpress-seo' ),
			\esc_html( $this->migration_error['message'] )
		);

		return \sprintf(
			'<div class="notice notice-error"><p>%1$s</p><p>%2$s</p><p>%3$s</p>%4$s</div>',
			$message,
			$support,
			$reassurance,
			$debug_info
		);
	}
}
admin/indexing-error-presenter.php000064400000010463152335320000013303 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Addon_Manager;
use Yoast\WP\SEO\Helpers\Product_Helper;
use Yoast\WP\SEO\Helpers\Short_Link_Helper;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * An error that should be shown when indexation has failed.
 */
class Indexing_Error_Presenter extends Abstract_Presenter {

	/**
	 * The short link helper.
	 *
	 * @var Short_Link_Helper
	 */
	protected $short_link_helper;

	/**
	 * The product helper
	 *
	 * @var Product_Helper
	 */
	protected $product_helper;

	/**
	 * The addon manager.
	 *
	 * @var WPSEO_Addon_Manager
	 */
	protected $addon_manager;

	/**
	 * Indexing_Error_Presenter constructor.
	 *
	 * @param Short_Link_Helper   $short_link_helper Represents the short link helper.
	 * @param Product_Helper      $product_helper    The product helper.
	 * @param WPSEO_Addon_Manager $addon_manager     The addon manager.
	 */
	public function __construct(
		Short_Link_Helper $short_link_helper,
		Product_Helper $product_helper,
		WPSEO_Addon_Manager $addon_manager
	) {
		$this->short_link_helper = $short_link_helper;
		$this->product_helper    = $product_helper;
		$this->addon_manager     = $addon_manager;
	}

	/**
	 * Generates the first paragraph of the error message to show when indexing failed.
	 *
	 * The contents of the paragraph varies based on whether WordPress SEO Premium has a valid, activated subscription or not.
	 *
	 * @param bool $is_premium                     Whether WordPress SEO Premium is currently active.
	 * @param bool $has_valid_premium_subscription Whether WordPress SEO Premium currently has a valid subscription.
	 *
	 * @return string
	 */
	protected function generate_first_paragraph( $is_premium, $has_valid_premium_subscription ) {
		$message = \__(
			'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please click the button again to re-start the process. ',
			'wordpress-seo'
		);

		if ( $is_premium ) {
			if ( $has_valid_premium_subscription ) {
				$message .= \__( 'If the problem persists, please contact support.', 'wordpress-seo' );
			}
			else {
				$message = \sprintf(
					/* translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */
					\__(
						'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.',
						'wordpress-seo'
					),
					'<a href="' . \esc_url( $this->short_link_helper->get( 'https://yoa.st/3wv' ) ) . '">',
					'</a>'
				);
			}
		}

		return $message;
	}

	/**
	 * Generates the second paragraph of the error message to show when indexing failed.
	 *
	 * The error message varies based on whether WordPress SEO Premium has a valid, activated subscription or not.
	 *
	 * @param bool $is_premium                     Whether WordPress SEO Premium is currently active.
	 * @param bool $has_valid_premium_subscription Whether WordPress SEO Premium currently has a valid subscription.
	 *
	 * @return string The second paragraph of the error message.
	 */
	protected function generate_second_paragraph( $is_premium, $has_valid_premium_subscription ) {
		return \sprintf(
			/* translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */
			\__(
				'Below are the technical details for the error. See %1$sthis page%2$s for a more detailed explanation.',
				'wordpress-seo'
			),
			'<a href="' . \esc_url( $this->short_link_helper->get( 'https://yoa.st/4f3' ) ) . '">',
			'</a>'
		);
	}

	/**
	 * Presents the error message to show if SEO optimization failed.
	 *
	 * The error message varies based on whether WordPress SEO Premium has a valid, activated subscription or not.
	 *
	 * @return string The error message to show.
	 */
	public function present() {
		$is_premium                     = $this->product_helper->is_premium();
		$has_valid_premium_subscription = $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG );

		$output  = '<p>' . $this->generate_first_paragraph( $is_premium, $has_valid_premium_subscription ) . '</p>';
		$output .= '<p>' . $this->generate_second_paragraph( $is_premium, $has_valid_premium_subscription ) . '</p>';

		return $output;
	}
}
admin/light-switch-presenter.php000064400000010764152335320000012761 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Class Light_Switch_Presenter.
 *
 * @package Yoast\WP\SEO\Presenters\Admin
 */
class Light_Switch_Presenter extends Abstract_Presenter {

	/**
	 * The variable to create the checkbox for.
	 *
	 * @var string
	 */
	protected $var;

	/**
	 * The visual label text for the toggle.
	 *
	 * @var string
	 */
	protected $label;

	/**
	 * Array of two visual labels for the buttons.
	 *
	 * @var array
	 */
	protected $buttons;

	/**
	 * The name of the underlying checkbox.
	 *
	 * @var string
	 */
	protected $name;

	/**
	 * The variable current value.
	 *
	 * @var string|bool
	 */
	protected $value;

	/**
	 * Reverse order of buttons.
	 *
	 * @var bool
	 */
	protected $reverse;

	/**
	 * The inline Help HTML.
	 *
	 * @var string
	 */
	protected $help;

	/**
	 * Whether the visual label is displayed in strong text.
	 *
	 * @var bool
	 */
	protected $strong;

	/**
	 * The disabled attribute HTML.
	 *
	 * @var string
	 */
	protected $disabled_attribute;

	/**
	 * Light_Switch_Presenter constructor.
	 *
	 * @param string      $variable           The variable to create the checkbox for.
	 * @param string      $label              The visual label text for the toggle.
	 * @param array       $buttons            Array of two visual labels for the buttons (defaults Disabled/Enabled).
	 * @param string      $name               The name of the underlying checkbox.
	 * @param string|bool $value              The variable current value, to determine the checked attribute.
	 * @param bool        $reverse            Optional. Reverse order of buttons (default true).
	 * @param string      $help               Optional. Inline Help HTML that will be printed out before the toggle. Default is empty.
	 * @param bool        $strong             Optional. Whether the visual label is displayed in strong text. Default is false.
	 *                                        Starting from Yoast SEO 16.5, the visual label is forced to bold via CSS.
	 * @param string      $disabled_attribute Optional. The disabled HTML attribute. Default is empty.
	 */
	public function __construct(
		$variable,
		$label,
		$buttons,
		$name,
		$value,
		$reverse = true,
		$help = '',
		$strong = false,
		$disabled_attribute = ''
	) {
		$this->var                = $variable;
		$this->label              = $label;
		$this->buttons            = $buttons;
		$this->name               = $name;
		$this->value              = $value;
		$this->reverse            = $reverse;
		$this->help               = $help;
		$this->strong             = $strong;
		$this->disabled_attribute = $disabled_attribute;
	}

	/**
	 * Presents the light switch toggle.
	 *
	 * @return string The light switch's HTML.
	 */
	public function present() {
		if ( empty( $this->buttons ) ) {
			$this->buttons = [ \__( 'Disabled', 'wordpress-seo' ), \__( 'Enabled', 'wordpress-seo' ) ];
		}

		list( $off_button, $on_button ) = $this->buttons;

		$class = 'switch-light switch-candy switch-yoast-seo';

		if ( $this->reverse ) {
			$class .= ' switch-yoast-seo-reverse';
		}

		$help_class   = ! empty( $this->help ) ? ' switch-container__has-help' : '';
		$strong_class = ( $this->strong ) ? ' switch-light-visual-label__strong' : '';

		$output  = '<div class="switch-container' . $help_class . '">';
		$output .= \sprintf(
			'<span class="switch-light-visual-label%1$s" id="%2$s">%3$s</span>%4$s',
			$strong_class, // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $strong_class output is hardcoded.
			\esc_attr( $this->var . '-label' ),
			\esc_html( $this->label ),
			$this->help // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML.
		);
		$output .= '<label class="' . $class . '"><b class="switch-yoast-seo-jaws-a11y">&nbsp;</b>';
		$output .= \sprintf(
			'<input type="checkbox" aria-labelledby="%1$s" id="%2$s" name="%3$s" value="on"%4$s%5$s/>',
			\esc_attr( $this->var . '-label' ),
			\esc_attr( $this->var ),
			\esc_attr( $this->name ),
			\checked( $this->value, 'on', false ), // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The output is hardcoded by WordPress.
			$this->disabled_attribute // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded.
		);
		$output .= '<span aria-hidden="true">';
		$output .= '<span>' . \esc_html( $off_button ) . '</span>';
		$output .= '<span>' . \esc_html( $on_button ) . '</span>';
		$output .= '<a></a>';
		$output .= '</span></label><div class="clear"></div></div>';

		return $output;
	}
}
admin/badge-presenter.php000064400000005221152335320000011405 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Config\Badge_Group_Names;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for "New" badges.
 */
class Badge_Presenter extends Abstract_Presenter {

	/**
	 * Identifier of the badge.
	 *
	 * @var string
	 */
	private $id;

	/**
	 * Optional link of the badge.
	 *
	 * @var string
	 */
	private $link;

	/**
	 * Optional group which the badge belongs to.
	 *
	 * Each group has a fixed period after which the group will no longer be considered new and the badges will disappear.
	 *
	 * @var string
	 */
	private $group;

	/**
	 * Optional object storing the group names and expiration versions.
	 *
	 * The group names set in Yoast SEO are used by default, but they can be overridden to use custom ones for an add-on.
	 *
	 * @var Badge_Group_Names
	 */
	private $badge_group_names;

	/**
	 * Badge_Presenter constructor.
	 *
	 * @param string                 $id                Id of the badge.
	 * @param string                 $link              Optional link of the badge.
	 * @param string                 $group             Optional group which the badge belongs to.
	 * @param Badge_Group_Names|null $badge_group_names Optional object storing the group names.
	 */
	public function __construct( $id, $link = '', $group = '', $badge_group_names = null ) {
		$this->id    = $id;
		$this->link  = $link;
		$this->group = $group;

		if ( ! $badge_group_names instanceof Badge_Group_Names ) {
			$badge_group_names = new Badge_Group_Names();
		}
		$this->badge_group_names = $badge_group_names;
	}

	/**
	 * Presents the New Badge. If a link has been passed, the badge is presented with the link.
	 * Otherwise a static badge is presented.
	 *
	 * @return string The styled New Badge.
	 */
	public function present() {
		if ( ! $this->is_group_still_new() ) {
			return '';
		}

		if ( $this->link !== '' ) {
			return \sprintf(
				'<a class="yoast-badge yoast-badge__is-link yoast-new-badge" id="%1$s-new-badge" href="%2$s">%3$s</a>',
				\esc_attr( $this->id ),
				\esc_url( $this->link ),
				\esc_html__( 'New', 'wordpress-seo' )
			);
		}

		return \sprintf(
			'<span class="yoast-badge yoast-new-badge" id="%1$s-new-badge">%2$s</span>',
			\esc_attr( $this->id ),
			\esc_html__( 'New', 'wordpress-seo' )
		);
	}

	/**
	 * Check whether the new badge should be shown according to the group it is in.
	 *
	 * @return bool True if still new.
	 */
	public function is_group_still_new() {
		// If there's no group configured, the new badge is always active.
		if ( ! $this->group ) {
			return true;
		}

		return $this->badge_group_names->is_still_eligible_for_new_badge( $this->group );
	}
}
admin/indexing-list-item-presenter.php000064400000003012152335320000014051 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Helpers\Short_Link_Helper;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Class Indexing_List_Item_Presenter.
 *
 * @package Yoast\WP\SEO\Presenters\Admin
 */
class Indexing_List_Item_Presenter extends Abstract_Presenter {

	/**
	 * The short link helper.
	 *
	 * @var Short_Link_Helper
	 */
	protected $short_link_helper;

	/**
	 * Indexing_List_Item_Presenter constructor.
	 *
	 * @param Short_Link_Helper $short_link_helper Represents the short link helper.
	 */
	public function __construct( Short_Link_Helper $short_link_helper ) {
		$this->short_link_helper = $short_link_helper;
	}

	/**
	 * Presents the list item for the tools menu.
	 *
	 * @return string The list item HTML.
	 */
	public function present() {
		$output  = \sprintf( '<li><strong>%s</strong><br/>', \esc_html__( 'Optimize SEO Data', 'wordpress-seo' ) );
		$output .= \sprintf(
			'%1$s <a href="%2$s" target="_blank">%3$s</a>',
			\esc_html__( 'You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. If you have a lot of content it might take a while, but trust us, it\'s worth it.', 'wordpress-seo' ),
			\esc_url( $this->short_link_helper->get( 'https://yoa.st/3-z' ) ),
			\esc_html__( 'Learn more about the benefits of optimized SEO data.', 'wordpress-seo' )
		);

		$output .= '<div id="yoast-seo-indexing-action" style="margin: 16px 0;"></div>';
		$output .= '</li>';

		return $output;
	}
}
admin/notice-presenter.php000064400000006321152335320000011626 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Admin_Asset_Manager;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for Yoast-styled WordPress admin notices.
 */
class Notice_Presenter extends Abstract_Presenter {

	/**
	 * The title of the admin notice.
	 *
	 * @var string
	 */
	private $title;

	/**
	 * The content of the admin notice.
	 *
	 * @var string
	 */
	private $content;

	/**
	 * The filename of the image for the notice. Should be a file in the 'images' folder.
	 *
	 * @var string
	 */
	private $image_filename;

	/**
	 * HTML string to be displayed after the main content, usually a button.
	 *
	 * @var string
	 */
	private $button;

	/**
	 * Whether the notice should be dismissible.
	 *
	 * @var bool
	 */
	private $is_dismissible;

	/**
	 * The id for the div of the notice.
	 *
	 * @var string
	 */
	private $id;

	/**
	 * An instance of the WPSEO_Admin_Asset_Manager class.
	 *
	 * @var WPSEO_Admin_Asset_Manager
	 */
	protected $asset_manager;

	/**
	 * Notice_Presenter constructor.
	 *
	 * @param string      $title          Title of the admin notice.
	 * @param string      $content        Content of the admin notice.
	 * @param string|null $image_filename Optional. The filename of the image of the admin notice,
	 *                                    should be inside the 'images' folder.
	 * @param string|null $button         Optional. An HTML string to be displayed after the main content,
	 *                                    usually a button.
	 * @param bool        $is_dismissible Optional. Whether the admin notice should be dismissible.
	 * @param string      $id             Optional. The id of the notice.
	 */
	public function __construct( $title, $content, $image_filename = null, $button = null, $is_dismissible = false, $id = '' ) {
		$this->title          = $title;
		$this->content        = $content;
		$this->image_filename = $image_filename;
		$this->button         = $button;
		$this->is_dismissible = $is_dismissible;
		$this->id             = $id;

		if ( ! $this->asset_manager ) {
			$this->asset_manager = new WPSEO_Admin_Asset_Manager();
		}

		$this->asset_manager->enqueue_style( 'notifications' );
	}

	/**
	 * Presents the Notice.
	 *
	 * @return string The styled Notice.
	 */
	public function present() {
		$dismissible = ( $this->is_dismissible ) ? ' is-dismissible' : '';
		$id          = ( $this->id ) ? ' id="' . $this->id . '"' : '';

		// WordPress admin notice.
		$out  = '<div' . $id . ' class="notice notice-yoast yoast' . $dismissible . '">';
		$out .= '<div class="notice-yoast__container">';

		// Header.
		$out .= '<div>';
		$out .= '<div class="notice-yoast__header">';
		$out .= '<span class="yoast-icon"></span>';
		$out .= \sprintf(
			'<h2 class="notice-yoast__header-heading">%s</h2>',
			\esc_html( $this->title )
		);
		$out .= '</div>';
		$out .= '<p>' . $this->content . '</p>';
		if ( ! \is_null( $this->button ) ) {
			$out .= '<p>' . $this->button . '</p>';
		}
		$out .= '</div>';

		if ( ! \is_null( $this->image_filename ) ) {
			$out .= '<img src="' . \esc_url( \plugin_dir_url( \WPSEO_FILE ) . 'images/' . $this->image_filename ) . '" alt="" height="60" width="75"/>';
		}

		$out .= '</div>';
		$out .= '</div>';

		return $out;
	}
}
admin/beta-badge-presenter.php000064400000002447152335320000012325 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for "Beta" badges.
 */
class Beta_Badge_Presenter extends Abstract_Presenter {

	/**
	 * Identifier of the badge.
	 *
	 * @var string
	 */
	private $id;

	/**
	 * Optional link of the badge.
	 *
	 * @var string
	 */
	private $link;

	/**
	 * Beta_Badge_Presenter constructor.
	 *
	 * @param string $id   Id of the badge.
	 * @param string $link Optional link of the badge.
	 */
	public function __construct( $id, $link = '' ) {
		$this->id   = $id;
		$this->link = $link;
	}

	/**
	 * Presents the Beta Badge. If a link has been passed, the badge is presented with the link.
	 * Otherwise a static badge is presented.
	 *
	 * @return string The styled Beta Badge.
	 */
	public function present() {
		if ( $this->link !== '' ) {
			return \sprintf(
				'<a class="yoast-badge yoast-badge__is-link yoast-beta-badge" id="%1$s-beta-badge" href="%2$s">%3$s</a>',
				\esc_attr( $this->id ),
				\esc_url( $this->link ),
				'Beta' // We don't want this string to be translatable.
			);
		}

		return \sprintf(
			'<span class="yoast-badge yoast-beta-badge" id="%1$s-beta-badge">%2$s</span>',
			\esc_attr( $this->id ),
			'Beta' // We don't want this string to be translatable.
		);
	}
}
admin/premium-badge-presenter.php000064400000002510152335320000013057 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for "Premium" badges.
 */
class Premium_Badge_Presenter extends Abstract_Presenter {

	/**
	 * Identifier of the badge.
	 *
	 * @var string
	 */
	private $id;

	/**
	 * Optional link of the badge.
	 *
	 * @var string
	 */
	private $link;

	/**
	 * Premium_Badge_Presenter constructor.
	 *
	 * @param string $id   Id of the badge.
	 * @param string $link Optional link of the badge.
	 */
	public function __construct( $id, $link = '' ) {
		$this->id   = $id;
		$this->link = $link;
	}

	/**
	 * Presents the Premium Badge. If a link has been passed, the badge is presented with the link.
	 * Otherwise a static badge is presented.
	 *
	 * @return string The styled Premium Badge.
	 */
	public function present() {
		if ( $this->link !== '' ) {
			return \sprintf(
				'<a class="yoast-badge yoast-badge__is-link yoast-premium-badge" id="%1$s-premium-badge" href="%2$s">%3$s</a>',
				\esc_attr( $this->id ),
				\esc_url( $this->link ),
				'Premium' // We don't want this string to be translatable.
			);
		}

		return \sprintf(
			'<span class="yoast-badge yoast-premium-badge" id="%1$s-premium-badge">%2$s</span>',
			\esc_attr( $this->id ),
			'Premium' // We don't want this string to be translatable.
		);
	}
}
admin/alert-presenter.php000064400000003063152335320000011454 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Admin_Asset_Manager;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for Alert boxes.
 */
class Alert_Presenter extends Abstract_Presenter {

	/**
	 * Content of the Alert.
	 *
	 * @var string
	 */
	private $content = '';

	/**
	 * The type of the Alert.
	 *
	 * Can be: "error", "info", "success" or "warning".
	 * Controls the colours and icon of the Alert.
	 *
	 * @var string
	 */
	private $type;

	/**
	 * An instance of the WPSEO_Admin_Asset_Manager class.
	 *
	 * @var WPSEO_Admin_Asset_Manager
	 */
	protected $asset_manager;

	/**
	 * Alert_Presenter constructor.
	 *
	 * @param string $content Content of the Alert.
	 * @param string $type    Type of the Alert (error/info/success/warning), default is warning.
	 */
	public function __construct( $content, $type = 'warning' ) {
		$this->content = $content;
		$this->type    = $type;

		if ( ! $this->asset_manager ) {
			$this->asset_manager = new WPSEO_Admin_Asset_Manager();
		}

		$this->asset_manager->enqueue_style( 'alert' );
	}

	/**
	 * Presents the Alert.
	 *
	 * @return string The styled Alert.
	 */
	public function present() {
		$icon_file = 'images/alert-' . $this->type . '-icon.svg';

		$out  = '<div class="yoast-alert yoast-alert--' . $this->type . '">';
		$out .= '<span>';
		$out .= '<img class="yoast-alert__icon" src="' . \esc_url( \plugin_dir_url( \WPSEO_FILE ) . $icon_file ) . '" alt="" />';
		$out .= '</span>';

		$out .= '<span>' . $this->content . '</span>';
		$out .= '</div>';

		return $out;
	}
}
admin/meta-fields-presenter.php000064400000003100152335320000012527 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WP_Post;
use WPSEO_Meta;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Presenter class for meta fields in the post editor.
 *
 * Outputs the hidden fields for a particular field group and post.
 */
class Meta_Fields_Presenter extends Abstract_Presenter {

	/**
	 * The meta fields for which we are going to output hidden input.
	 *
	 * @var array
	 */
	private $meta_fields;

	/**
	 * The metabox post.
	 *
	 * @var WP_Post The metabox post.
	 */
	private $post;

	/**
	 * Meta_Fields_Presenter constructor.
	 *
	 * @param WP_Post $post        The metabox post.
	 * @param string  $field_group The key under which a group of fields is grouped.
	 * @param string  $post_type   The post type.
	 */
	public function __construct( $post, $field_group, $post_type = 'post' ) {
		$this->post        = $post;
		$this->meta_fields = WPSEO_Meta::get_meta_field_defs( $field_group, $post_type );
	}

	/**
	 * Presents the Meta Fields.
	 *
	 * @return string The styled Alert.
	 */
	public function present() {
		$output = '';

		foreach ( $this->meta_fields as $key => $meta_field ) {
			$form_key   = \esc_attr( WPSEO_Meta::$form_prefix . $key );
			$meta_value = WPSEO_Meta::get_value( $key, $this->post->ID );

			$default = '';
			if ( isset( $meta_field['default'] ) ) {
				$default = \sprintf( ' data-default="%s"', \esc_attr( $meta_field['default'] ) );
			}

			$output .= '<input type="hidden" id="' . $form_key . '" name="' . $form_key . '" value="' . \esc_attr( $meta_value ) . '"' . $default . '/>' . "\n";
		}

		return $output;
	}
}
admin/help-link-presenter.php000064400000004047152335320000012233 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Admin_Asset_Manager;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Represents the presenter class for Help link.
 */
class Help_Link_Presenter extends Abstract_Presenter {

	/**
	 * Help link.
	 *
	 * @var string
	 */
	private $link;

	/**
	 * Help link visually hidden text.
	 *
	 * @var string
	 */
	private $link_text;

	/**
	 * Whether the Help link opens in a new browser tab.
	 *
	 * @var bool
	 */
	private $opens_in_new_browser_tab;

	/**
	 * An instance of the WPSEO_Admin_Asset_Manager class.
	 *
	 * @var WPSEO_Admin_Asset_Manager
	 */
	private $asset_manager;

	/**
	 * Help_Link_Presenter constructor.
	 *
	 * @param string $link                     Help link.
	 * @param string $link_text                Help link visually hidden text.
	 * @param bool   $opens_in_new_browser_tab Whether the link opens in a new browser tab. Default true.
	 */
	public function __construct( $link = '', $link_text = '', $opens_in_new_browser_tab = true ) {
		$this->link                     = $link;
		$this->link_text                = $link_text;
		$this->opens_in_new_browser_tab = $opens_in_new_browser_tab;

		if ( ! $this->asset_manager ) {
			$this->asset_manager = new WPSEO_Admin_Asset_Manager();
		}

		$this->asset_manager->enqueue_style( 'admin-global' );
	}

	/**
	 * Presents the Help link.
	 *
	 * @return string The styled Help link.
	 */
	public function present() {
		if ( $this->link === '' || $this->link_text === '' ) {
			return;
		}

		$target_blank_attribute = '';
		$new_tab_message        = '';

		if ( $this->opens_in_new_browser_tab ) {
			$target_blank_attribute = ' target="_blank"';
			$new_tab_message        = ' ' . \__( '(Opens in a new browser tab)', 'wordpress-seo' );
		}

		return \sprintf(
			'<a href="%1$s"%2$s class="yoast_help yoast-help-link dashicons"><span class="yoast-help-icon" aria-hidden="true"></span><span class="screen-reader-text">%3$s</span></a>',
			\esc_url( $this->link ),
			$target_blank_attribute,
			\esc_html( $this->link_text . $new_tab_message )
		);
	}
}
admin/auto-update-notification-presenter.php000064400000003370152335320000015262 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Class Auto_Update_Notification_Presenter.
 */
class Auto_Update_Notification_Presenter extends Abstract_Presenter {

	/**
	 * Returns the notification as an HTML string.
	 *
	 * @return string The notification in an HTML string representation.
	 */
	public function present() {
		$notification_text  = '<p>';
		$notification_text .= $this->get_message();
		$notification_text .= '</p>';

		return $notification_text;
	}

	/**
	 * Returns the message to show.
	 *
	 * @return string The message.
	 */
	protected function get_message() {
		if ( \is_multisite() ) {
			return \sprintf(
				/* Translators: %1$s expands to 'Yoast SEO', %2$s to an opening anchor tag for a link leading to the Plugins page, and %3$s to a closing anchor tag. */
				\esc_html__(
					'We see that you enabled automatic updates for WordPress. We recommend that you do this for %1$s as well. This way we can guarantee that WordPress and %1$s will continue to run smoothly together. Please contact your network admin to enable auto-updates for %1$s.',
					'wordpress-seo'
				),
				'Yoast SEO'
			);
		}

		return \sprintf(
			/* Translators: %1$s expands to 'Yoast SEO', %2$s to an opening anchor tag for a link leading to the Plugins page, and %3$s to a closing anchor tag. */
			\esc_html__(
				'We see that you enabled automatic updates for WordPress. We recommend that you do this for %1$s as well. This way we can guarantee that WordPress and %1$s will continue to run smoothly together. %2$sGo to your plugins overview to enable auto-updates for %1$s.%3$s',
				'wordpress-seo'
			),
			'Yoast SEO',
			'<a href="' . \esc_url( \get_admin_url( null, 'plugins.php' ) ) . '">',
			'</a>'
		);
	}
}
admin/indexing-failed-notification-presenter.php000064400000005764152335320000016072 0ustar00<?php

namespace Yoast\WP\SEO\Presenters\Admin;

use WPSEO_Addon_Manager;
use Yoast\WP\SEO\Helpers\Product_Helper;
use Yoast\WP\SEO\Helpers\Short_Link_Helper;
use Yoast\WP\SEO\Presenters\Abstract_Presenter;

/**
 * Class Indexing_Failed_Notification_Presenter.
 *
 * @package Yoast\WP\SEO\Presenters\Notifications
 */
class Indexing_Failed_Notification_Presenter extends Abstract_Presenter {

	/**
	 * The product helper.
	 *
	 * @var Product_Helper
	 */
	protected $product_helper;

	/**
	 * The addon manager.
	 *
	 * @var WPSEO_Addon_Manager
	 */
	protected $class_addon_manager;

	/**
	 * The short link helper.
	 *
	 * @var Short_Link_Helper
	 */
	protected $short_link_helper;

	/**
	 * Indexing_Failed_Notification_Presenter constructor.
	 *
	 * @param Product_Helper      $product_helper      The product helper.
	 * @param Short_Link_Helper   $short_link_helper   The addon manager.
	 * @param WPSEO_Addon_Manager $class_addon_manager The addon manager.
	 */
	public function __construct( $product_helper, $short_link_helper, $class_addon_manager ) {
		$this->class_addon_manager = $class_addon_manager;
		$this->short_link_helper   = $short_link_helper;
		$this->product_helper      = $product_helper;
	}

	/**
	 * Returns the notification as an HTML string.
	 *
	 * @return string The notification in an HTML string representation.
	 */
	public function present() {
		$notification_text = \sprintf(
			/* Translators: %1$s expands to an opening anchor tag for a link leading to the Yoast SEO tools page, %2$s expands to a closing anchor tag. */
			\esc_html__(
				'Something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please %1$sre-start the process%2$s.',
				'wordpress-seo'
			),
			'<a href="' . \get_admin_url( null, 'admin.php?page=wpseo_tools' ) . '">',
			'</a>'
		);

		if ( $this->product_helper->is_premium() ) {
			if ( $this->has_valid_premium_subscription() ) {
				// Add a support message for premium customers.
				$notification_text .= ' ';
				$notification_text .= \esc_html__( 'If the problem persists, please contact support.', 'wordpress-seo' );
			}
			else {
				// Premium plugin with inactive addon; overwrite the entire error message.
				$notification_text = \sprintf(
					/* Translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */
					\esc_html__(
						'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.',
						'wordpress-seo'
					),
					'<a href="' . \esc_url( $this->short_link_helper->get( 'https://yoa.st/3wv' ) ) . '">',
					'</a>'
				);
			}
		}

		return '<p>' . $notification_text . '</p>';
	}

	/**
	 * Determines if the site has a valid Premium subscription.
	 *
	 * @return bool
	 */
	protected function has_valid_premium_subscription() {
		return $this->class_addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG );
	}
}
title-presenter.php000064400000003320152335320000010372 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the document title.
 */
class Title_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'title';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = '<title>%s</title>';

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'html';

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string The raw value.
	 */
	public function get() {
		// This ensures backwards compatibility with other plugins using this filter as well.
		\add_filter( 'pre_get_document_title', [ $this, 'get_title' ], 15 );
		$title = \wp_get_document_title();
		\remove_filter( 'pre_get_document_title', [ $this, 'get_title' ], 15 );
		return $title;
	}

	/**
	 * Returns a tag in the head.
	 *
	 * @return string The tag.
	 */
	public function present() {
		$value = $this->get();

		if ( \is_string( $value ) && $value !== '' ) {
			return \sprintf( $this->tag_format, $this->escape_value( $value ) );
		}

		return '';
	}

	/**
	 * Returns the presentation title.
	 *
	 * @return string The title.
	 */
	public function get_title() {
		$title = $this->replace_vars( $this->presentation->title );

		/**
		 * Filter: 'wpseo_title' - Allow changing the Yoast SEO generated title.
		 *
		 * @api string $title The title.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		$title = \apply_filters( 'wpseo_title', $title, $this->presentation );
		$title = $this->helpers->string->strip_all_tags( $title );
		return \trim( $title );
	}
}
schema-presenter.php000064400000002637152335320000010523 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use WPSEO_Utils;

/**
 * Presenter class for the schema object.
 */
class Schema_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'schema';

	/**
	 * Returns the schema output.
	 *
	 * @return string The schema tag.
	 */
	public function present() {
		$deprecated_data = [
			'_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 === [] || $return === false ) {
			return '';
		}

		/**
		 * Action: 'wpseo_json_ld' - Output Schema before the main schema from Yoast SEO is output.
		 */
		\do_action( 'wpseo_json_ld' );

		$schema = $this->get();
		if ( \is_array( $schema ) ) {
			$output = WPSEO_Utils::format_json_encode( $schema );
			$output = \str_replace( "\n", \PHP_EOL . "\t", $output );
			return '<script type="application/ld+json" class="yoast-schema-graph">' . $output . '</script>';
		}

		return '';
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return array The raw value.
	 */
	public function get() {
		return $this->presentation->schema;
	}
}
abstract-indexable-presenter.php000064400000003063152335320000013011 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use WPSEO_Replace_Vars;
use Yoast\WP\SEO\Presentations\Indexable_Presentation;
use Yoast\WP\SEO\Surfaces\Helpers_Surface;

/**
 * Abstract presenter class for indexable presentations.
 */
abstract class Abstract_Indexable_Presenter extends Abstract_Presenter {

	/**
	 * The WPSEO Replace Vars object.
	 *
	 * @var WPSEO_Replace_Vars
	 */
	public $replace_vars;

	/**
	 * The indexable presentation.
	 *
	 * @var Indexable_Presentation
	 */
	public $presentation;

	/**
	 * The helpers surface
	 *
	 * @var Helpers_Surface
	 */
	public $helpers;

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'NO KEY PROVIDED';

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return string|array The raw value.
	 */
	abstract public function get();

	/**
	 * Transforms an indexable presenter's key to a json safe key string.
	 *
	 * @return string|null
	 */
	public function escape_key() {
		if ( $this->key === 'NO KEY PROVIDED' ) {
			return null;
		}
		return \str_replace( [ ':', ' ', '-' ], '_', $this->key );
	}

	/**
	 * Returns the metafield's property key.
	 *
	 * @return string The property key.
	 */
	public function get_key() {
		return $this->key;
	}

	/**
	 * Replace replacement variables in a string.
	 *
	 * @param string $replacevar_string The string with replacement variables.
	 *
	 * @return string The string with replacement variables replaced.
	 */
	protected function replace_vars( $replacevar_string ) {
		return $this->replace_vars->replace( $replacevar_string, $this->presentation->source );
	}
}
canonical-presenter.php000064400000002155152335320000011205 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the canonical.
 */
class Canonical_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'canonical';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::LINK_REL_HREF;

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'url';

	/**
	 * Run the canonical content through the `wpseo_canonical` filter.
	 *
	 * @return string The filtered canonical.
	 */
	public function get() {
		if ( \in_array( 'noindex', $this->presentation->robots, true ) ) {
			return '';
		}

		/**
		 * Filter: 'wpseo_canonical' - Allow filtering of the canonical URL put out by Yoast SEO.
		 *
		 * @api string $canonical The canonical URL.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \urldecode( (string) \trim( \apply_filters( 'wpseo_canonical', $this->presentation->canonical, $this->presentation ) ) );
	}
}
robots-presenter.php000064400000001307152335320000010564 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

/**
 * Presenter class for the robots output.
 */
class Robots_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'robots';

	/**
	 * Returns the robots output.
	 *
	 * @return string The robots output tag.
	 */
	public function present() {
		$robots = \implode( ', ', $this->get() );

		if ( \is_string( $robots ) && $robots !== '' ) {
			return \sprintf( '<meta name="robots" content="%s" />', \esc_attr( $robots ) );
		}

		return '';
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return array The raw value.
	 */
	public function get() {
		return $this->presentation->robots;
	}
}
rel-prev-presenter.php000064400000003134152335320000011010 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

/**
 * Presenter class for the rel prev meta tag.
 */
class Rel_Prev_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'prev';

	/**
	 * The tag format including placeholders.
	 *
	 * @var string
	 */
	protected $tag_format = self::LINK_REL_HREF;

	/**
	 * The method of escaping to use.
	 *
	 * @var string
	 */
	protected $escaping = 'url';

	/**
	 * Returns the rel prev meta tag.
	 *
	 * @param bool $output_tag Optional. Whether or not to output the HTML tag. Defaults to true.
	 *
	 * @return string The rel prev tag.
	 */
	public function present( $output_tag = true ) {
		$output = parent::present();

		if ( ! empty( $output ) ) {
			/**
			 * Filter: 'wpseo_prev_rel_link' - Allow changing link rel output by Yoast SEO.
			 *
			 * @api string $unsigned The full `<link` element.
			 */
			return \apply_filters( 'wpseo_prev_rel_link', $output );
		}

		return '';
	}

	/**
	 * Run the rel prev content through the `wpseo_adjacent_rel_url` filter.
	 *
	 * @return string The filtered adjacent link.
	 */
	public function get() {
		if ( \in_array( 'noindex', $this->presentation->robots, true ) ) {
			return '';
		}

		/**
		 * Filter: 'wpseo_adjacent_rel_url' - Allow filtering of the rel prev URL put out by Yoast SEO.
		 *
		 * @api string $canonical The rel prev URL.
		 *
		 * @param string                 $rel          Link relationship, prev or next.
		 */
		return (string) \trim( \apply_filters( 'wpseo_adjacent_rel_url', $this->presentation->rel_prev, 'prev', $this->presentation ) );
	}
}
breadcrumbs-presenter.php000064400000015021152335320000011543 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the breadcrumbs.
 */
class Breadcrumbs_Presenter extends Abstract_Indexable_Presenter {

	/**
	 * The id attribute.
	 *
	 * @var string
	 */
	private $id;

	/**
	 * The class name attribute.
	 *
	 * @var string
	 */
	private $class;

	/**
	 * The wrapper element name.
	 *
	 * @var string
	 */
	private $wrapper;

	/**
	 * Separator to use.
	 *
	 * @var string
	 */
	private $separator;

	/**
	 * The element.
	 *
	 * @var string
	 */
	private $element;

	/**
	 * Presents the breadcrumbs.
	 *
	 * @return string The breadcrumbs HTML.
	 */
	public function present() {
		$breadcrumbs = $this->get();
		if ( ! \is_array( $breadcrumbs ) || empty( $breadcrumbs ) ) {
			return '';
		}

		$links = [];
		$total = \count( $breadcrumbs );
		foreach ( $breadcrumbs as $index => $breadcrumb ) {
			$links[ $index ] = $this->crumb_to_link( $breadcrumb, $index, $total );
		}

		// Removes any effectively empty links.
		$links  = \array_map( 'trim', $links );
		$links  = \array_filter( $links );
		$output = \implode( $this->get_separator(), $links );

		if ( empty( $output ) ) {
			return '';
		}

		$output = '<' . $this->get_wrapper() . $this->get_id() . $this->get_class() . '>' . $output . '</' . $this->get_wrapper() . '>';
		$output = $this->filter( $output );

		$prefix = $this->helpers->options->get( 'breadcrumbs-prefix' );
		if ( $prefix !== '' ) {
			$output = "\t" . $prefix . "\n" . $output;
		}

		return $output;
	}

	/**
	 * Gets the raw value of a presentation.
	 *
	 * @return array The raw value.
	 */
	public function get() {
		return $this->presentation->breadcrumbs;
	}

	/**
	 * Filters the output.
	 *
	 * @param string $output The HTML output.
	 *
	 * @return string The filtered output.
	 */
	protected function filter( $output ) {
		/**
		 * Filter: 'wpseo_breadcrumb_output' - Allow changing the HTML output of the Yoast SEO breadcrumbs class.
		 *
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 *
		 * @api string $output The HTML output.
		 */
		return \apply_filters( 'wpseo_breadcrumb_output', $output, $this->presentation );
	}

	/**
	 * Create a breadcrumb element string.
	 *
	 * @param array $breadcrumb Link info array containing the keys:
	 *                          'text'                  => (string) link text.
	 *                          'url'                   => (string) link url.
	 *                          (optional) 'title'      => (string) link title attribute text.
	 * @param int   $index      Index for the current breadcrumb.
	 * @param int   $total      The total number of breadcrumbs.
	 *
	 * @return string The breadcrumb link.
	 */
	protected function crumb_to_link( $breadcrumb, $index, $total ) {
		$link = '';

		if ( ! isset( $breadcrumb['text'] ) || ! \is_string( $breadcrumb['text'] ) || empty( $breadcrumb['text'] ) ) {
			return $link;
		}

		$text = \trim( $breadcrumb['text'] );

		if (
			$index < ( $total - 1 )
			&& isset( $breadcrumb['url'] )
			&& \is_string( $breadcrumb['url'] )
			&& ! empty( $breadcrumb['url'] )
		) {
			// If it's not the last element and we have a url.
			$link      .= '<' . $this->get_element() . '>';
			$title_attr = isset( $breadcrumb['title'] ) ? ' title="' . \esc_attr( $breadcrumb['title'] ) . '"' : '';
			$link      .= '<a href="' . \esc_url( $breadcrumb['url'] ) . '"' . $title_attr . '>' . $text . '</a>';
		}
		elseif ( $index === ( $total - 1 ) ) {
			// If it's the last element.
			$inner_elm = 'span';
			if ( $this->helpers->options->get( 'breadcrumbs-boldlast' ) === true ) {
				$inner_elm = 'strong';
			}

			$link .= '<' . $inner_elm . ' class="breadcrumb_last" aria-current="page">' . $text . '</' . $inner_elm . '>';
			// This is the last element, now close all previous elements.
			while ( $index > 0 ) {
				$link .= '</' . $this->get_element() . '>';
				--$index;
			}
		}
		else {
			// It's not the last element and has no url.
			$link .= '<span>' . $text . '</span>';
		}

		/**
		 * Filter: 'wpseo_breadcrumb_single_link' - Allow changing of each link being put out by the Yoast SEO breadcrumbs class.
		 *
		 * @param array $link The link array.
		 *
		 * @api string $link_output The output string.
		 */
		return \apply_filters( 'wpseo_breadcrumb_single_link', $link, $breadcrumb );
	}

	/**
	 * Retrieves HTML ID attribute.
	 *
	 * @return string The id attribute.
	 */
	protected function get_id() {
		if ( ! $this->id ) {
			/**
			 * Filter: 'wpseo_breadcrumb_output_id' - Allow changing the HTML ID on the Yoast SEO breadcrumbs wrapper element.
			 *
			 * @api string $unsigned ID to add to the wrapper element.
			 */
			$this->id = \apply_filters( 'wpseo_breadcrumb_output_id', '' );
			if ( ! \is_string( $this->id ) ) {
				return '';
			}

			if ( $this->id !== '' ) {
				$this->id = ' id="' . \esc_attr( $this->id ) . '"';
			}
		}

		return $this->id;
	}

	/**
	 * Retrieves HTML Class attribute.
	 *
	 * @return string The class attribute.
	 */
	protected function get_class() {
		if ( ! $this->class ) {
			/**
			 * Filter: 'wpseo_breadcrumb_output_class' - Allow changing the HTML class on the Yoast SEO breadcrumbs wrapper element.
			 *
			 * @api string $unsigned Class to add to the wrapper element.
			 */
			$this->class = \apply_filters( 'wpseo_breadcrumb_output_class', '' );
			if ( ! \is_string( $this->class ) ) {
				return '';
			}

			if ( $this->class !== '' ) {
				$this->class = ' class="' . \esc_attr( $this->class ) . '"';
			}
		}

		return $this->class;
	}

	/**
	 * Retrieves the wrapper element name.
	 *
	 * @return string The wrapper element name.
	 */
	protected function get_wrapper() {
		if ( ! $this->wrapper ) {
			$this->wrapper = \apply_filters( 'wpseo_breadcrumb_output_wrapper', 'span' );
			$this->wrapper = \tag_escape( $this->wrapper );
			if ( ! \is_string( $this->wrapper ) || $this->wrapper === '' ) {
				$this->wrapper = 'span';
			}
		}

		return $this->wrapper;
	}

	/**
	 * Retrieves the separator.
	 *
	 * @return string The separator.
	 */
	protected function get_separator() {
		if ( ! $this->separator ) {
			$this->separator = \apply_filters( 'wpseo_breadcrumb_separator', $this->helpers->options->get( 'breadcrumbs-sep' ) );
			$this->separator = ' ' . $this->separator . ' ';
		}

		return $this->separator;
	}

	/**
	 * Retrieves the crumb element name.
	 *
	 * @return string The element to use.
	 */
	protected function get_element() {
		if ( ! $this->element ) {
			$this->element = \esc_attr( \apply_filters( 'wpseo_breadcrumb_single_link_wrapper', 'span' ) );
		}

		return $this->element;
	}
}
meta-author-presenter.php000064400000002525152335320000011505 0ustar00<?php

namespace Yoast\WP\SEO\Presenters;

use Yoast\WP\SEO\Presentations\Indexable_Presentation;

/**
 * Presenter class for the meta author tag.
 */
class Meta_Author_Presenter extends Abstract_Indexable_Tag_Presenter {

	/**
	 * The tag key name.
	 *
	 * @var string
	 */
	protected $key = 'author';

	/**
	 * Returns the author for a post in a meta author tag.
	 *
	 * @return string The meta author tag.
	 */
	public function present() {
		$output = parent::present();

		if ( ! empty( $output ) ) {
			return $output;
		}

		return '';
	}

	/**
	 * Get the author's display name.
	 *
	 * @return string The author's display name.
	 */
	public function get() {
		if ( $this->presentation->model->object_sub_type !== 'post' ) {
			return '';
		}

		$user_data = \get_userdata( $this->presentation->context->post->post_author );

		if ( ! $user_data instanceof \WP_User ) {
			return '';
		}

		/**
		 * Filter: 'wpseo_meta_author' - Allow developers to filter the article's author meta tag.
		 *
		 * @param string                 $author_name  The article author's display name. Return empty to disable the tag.
		 * @param Indexable_Presentation $presentation The presentation of an indexable.
		 */
		return \trim( $this->helpers->schema->html->smart_strip_tags( \apply_filters( 'wpseo_meta_author', $user_data->display_name, $this->presentation ) ) );
	}
}