You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
6.3 KiB
276 lines
6.3 KiB
<?php |
|
/** |
|
* YoastSEO_AMP_Glue plugin file. |
|
* |
|
* @package YoastSEO_AMP_Glue\Options |
|
* @author Jip Moors |
|
* @copyright 2016 Yoast BV |
|
* @license GPL-2.0+ |
|
*/ |
|
|
|
if ( ! class_exists( 'YoastSEO_AMP_Options' ) ) { |
|
/** |
|
* Class to manage the YoastSEO_AMP option. |
|
*/ |
|
class YoastSEO_AMP_Options { |
|
|
|
/** |
|
* Name of the option in the database. |
|
* |
|
* @var string |
|
*/ |
|
private $option_name = 'wpseo_amp'; |
|
|
|
/** |
|
* Current options. |
|
* |
|
* @var array |
|
*/ |
|
private $options; |
|
|
|
/** |
|
* Option defaults. |
|
* |
|
* @var array |
|
*/ |
|
private $defaults = array( |
|
'version' => 1, |
|
'amp_site_icon' => '', |
|
'default_image' => '', |
|
'header-color' => '', |
|
'headings-color' => '', |
|
'text-color' => '', |
|
'meta-color' => '', |
|
'link-color' => '', |
|
'link-color-hover' => '', |
|
'underline' => 'underline', |
|
'blockquote-text-color' => '', |
|
'blockquote-bg-color' => '', |
|
'blockquote-border-color' => '', |
|
'extra-css' => '', |
|
'extra-head' => '', |
|
'analytics-extra' => '', |
|
); |
|
|
|
/** |
|
* Class instance. |
|
* |
|
* @var self |
|
*/ |
|
private static $instance; |
|
|
|
/** |
|
* Constructor. |
|
*/ |
|
private function __construct() { |
|
// Register settings. |
|
add_action( 'admin_init', array( $this, 'register_settings' ) ); |
|
} |
|
|
|
/** |
|
* Register the premium settings. |
|
*/ |
|
public function register_settings() { |
|
register_setting( 'wpseo_amp_settings', $this->option_name, array( $this, 'sanitize_options' ) ); |
|
} |
|
|
|
/** |
|
* Sanitize options. |
|
* |
|
* @param array $options Options as received in $_POST. |
|
* |
|
* @return mixed |
|
*/ |
|
public function sanitize_options( $options ) { |
|
$options['version'] = 1; |
|
|
|
// Sanitize extra CSS field. |
|
$extra_css = strip_tags( $options['extra-css'] ); |
|
$extra_css = wp_check_invalid_utf8( $extra_css ); |
|
$extra_css = _wp_specialchars( $extra_css, ENT_NOQUOTES ); |
|
$options['extra-css'] = $extra_css; |
|
|
|
// Only allow meta and link tags in head. |
|
$options['extra-head'] = strip_tags( $options['extra-head'], '<link><meta>' ); |
|
|
|
$colors = array( |
|
'header-color', |
|
'headings-color', |
|
'text-color', |
|
'meta-color', |
|
'link-color', |
|
'blockquote-text-color', |
|
'blockquote-bg-color', |
|
'blockquote-border-color', |
|
); |
|
|
|
foreach ( $colors as $color ) { |
|
$options[ $color ] = $this->sanitize_color( $options[ $color ], '' ); |
|
} |
|
|
|
// Only allow 'on' or 'off'. |
|
foreach ( $options as $key => $value ) { |
|
if ( 'post_types-' === substr( $key, 0, 11 ) ) { |
|
$options[ $key ] = ( $value === 'on' ) ? 'on' : 'off'; |
|
} |
|
} |
|
|
|
$options['analytics-extra'] = $this->sanitize_analytics_code( $options['analytics-extra'] ); |
|
|
|
return $options; |
|
} |
|
|
|
/** |
|
* Sanitize hexadecimal color. |
|
* |
|
* @param string $color String to test for valid color. |
|
* @param string $default Value the string will get when no color is found. |
|
* |
|
* @return string Color or $default. |
|
*/ |
|
private function sanitize_color( $color, $default ) { |
|
if ( preg_match( '~^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$~', $color, $matches ) ) { |
|
return $matches[0]; |
|
} |
|
|
|
return $default; |
|
} |
|
|
|
/** |
|
* Sanitize analytics code. |
|
* |
|
* @param string $source Raw input. |
|
* |
|
* @return string Sanitized code. |
|
*/ |
|
private function sanitize_analytics_code( $source ) { |
|
$source = trim( $source ); |
|
|
|
if ( empty( $source ) ) { |
|
return ''; |
|
} |
|
|
|
// If no <amp-analytics> occurs in the code, the code is invalid. |
|
if ( strpos( $source, '<amp-analytics ' ) === false ) { |
|
return ''; |
|
} |
|
|
|
if ( strpos( $source, '<script type="application/json">' ) === false ) { |
|
return strip_tags( $source, '<amp-analytics>' ); |
|
} |
|
|
|
return $this->sanitize_analytics_json( $source ); |
|
} |
|
|
|
/** |
|
* Get the options. |
|
* |
|
* @return array |
|
*/ |
|
public static function get() { |
|
|
|
$me = self::get_instance(); |
|
$me->fetch_options(); |
|
|
|
return $me->options; |
|
} |
|
|
|
/** |
|
* Get the singleton instance of this class. |
|
* |
|
* @return YoastSEO_AMP_Options |
|
*/ |
|
public static function get_instance() { |
|
if ( ! isset( self::$instance ) ) { |
|
self::$instance = new self(); |
|
} |
|
|
|
return self::$instance; |
|
} |
|
|
|
/** |
|
* Collect options. |
|
* |
|
* @SuppressWarnings("PMD.UnusedPrivateMethod") |
|
*/ |
|
private function fetch_options() { |
|
$saved_options = $this->options; |
|
if ( ! is_array( $this->options ) ) { |
|
$saved_options = get_option( 'wpseo_amp' ); |
|
|
|
// Apply defaults. |
|
$this->options = wp_parse_args( $saved_options, $this->defaults ); |
|
} |
|
|
|
// Make sure all post types are present. |
|
$this->update_post_type_settings(); |
|
|
|
// Save changes to database. |
|
if ( $this->options !== $saved_options ) { |
|
update_option( $this->option_name, $this->options ); |
|
} |
|
} |
|
|
|
/** |
|
* Get post types. |
|
*/ |
|
private function update_post_type_settings() { |
|
$post_type_names = array(); |
|
|
|
$post_types = get_post_types( array( 'public' => true ), 'objects' ); |
|
|
|
if ( is_array( $post_types ) && $post_types !== array() ) { |
|
foreach ( $post_types as $post_type ) { |
|
if ( ! isset( $this->options[ 'post_types-' . $post_type->name . '-amp' ] ) ) { |
|
$this->options[ 'post_types-' . $post_type->name . '-amp' ] = 'off'; |
|
if ( 'post' === $post_type->name ) { |
|
$this->options[ 'post_types-' . $post_type->name . '-amp' ] = 'on'; |
|
} |
|
} |
|
|
|
$post_type_names[] = $post_type->name; |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Sanitizes an analytics string when it has JSON in it. |
|
* |
|
* @param string $code The code to sanitize. |
|
* |
|
* @return string Sanitized string. |
|
*/ |
|
private function sanitize_analytics_json( $code ) { |
|
// Strip all tags, to verify JSON input. |
|
$json = strip_tags( $code ); |
|
|
|
// Non-parsable JSON is always bad. |
|
if ( is_null( json_decode( $json, true ) ) ) { |
|
return ''; |
|
} |
|
|
|
$allowed_tags = strip_tags( $code, '<amp-analytics>' ); |
|
|
|
// Strip JSON content so we can apply verified script tag. |
|
$tag = str_replace( $json, '', $allowed_tags ); |
|
|
|
$parts = explode( '><', $tag ); |
|
$parts[0] .= '>'; |
|
$parts[1] = '<' . $parts[1]; |
|
|
|
// Rebuild with script tag and JSON content. |
|
array_splice( |
|
$parts, |
|
1, |
|
null, |
|
array( |
|
'<script type="application/json">', |
|
trim( $json ), |
|
'</script>', |
|
) |
|
); |
|
|
|
return implode( "\n", $parts ); |
|
} |
|
} |
|
}
|
|
|