PDF rausgenommen

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

View File

@ -0,0 +1,8 @@
.yst_colorpicker {
clear: right;
}
label.checkbox {
display: block;
margin-bottom: 0.4em;
}

View File

@ -0,0 +1,3 @@
jQuery(document).ready(function($){
$('.yst_colorpicker').wpColorPicker();
});

View File

@ -0,0 +1,36 @@
/* global wpseoMediaL10n */
/* global ajaxurl */
/* global wp */
/* jshint -W097 */
/* jshint -W003 */
/* jshint unused:false */
// Taken and adapted from http://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/
jQuery(document).ready(
function($) {
'use strict';
if( typeof wp.media === 'undefined' ) {
return;
}
$('.wpseo_image_upload_button').each(function(index, element) {
var wpseo_target_id = $(element).attr('id').replace(/_button$/, '');
var wpseo_custom_uploader = wp.media.frames.file_frame = wp.media({
title: wpseoMediaL10n.choose_image,
button: { text: wpseoMediaL10n.choose_image },
multiple: false
});
wpseo_custom_uploader.on( 'select', function() {
var attachment = wpseo_custom_uploader.state().get( 'selection' ).first().toJSON();
$( '#' + wpseo_target_id ).val( attachment.url );
}
);
$(element).click( function( e ) {
e.preventDefault();
wpseo_custom_uploader.open();
} );
} );
}
);

View File

@ -0,0 +1,140 @@
<?php
/**
* @package YoastSEO_AMP_Glue\Admin
* @author Joost de Valk
* @copyright 2016 Yoast BV
* @license GPL-2.0+
*/
if ( ! class_exists( 'YoastSEO_AMP_Backend', false ) ) {
/**
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
*/
class YoastSEO_AMP_Backend {
/**
* @var array
*/
public $options;
/**
* YoastSEO_AMP_Backend constructor.
*/
public function __construct() {
$this->options = YoastSEO_AMP_Options::get();
// Add subitem to menu
add_filter( 'wpseo_submenu_pages', array( $this, 'add_submenu_page' ) );
// Register AMP admin page as a Yoast SEO admin page
add_filter( 'wpseo_admin_pages', array( $this, 'add_admin_pages' ) );
add_filter( 'wpseo_amp_supported_post_types', array( $this, 'remove_page_post_type' ) );
}
/**
* Filters out page post-type if not enabled in the AMP plugin.
*
* @param array $post_types Post types enabled for AMP support.
*
* @return array
*/
public function remove_page_post_type( $post_types ) {
if ( ! post_type_supports( 'page', AMP_QUERY_VAR ) ) {
unset( $post_types[ 'page' ] );
}
return $post_types;
}
/**
* Add submenu item
*
* @param array $sub_menu_pages
*
* @return array
*/
public function add_submenu_page( $sub_menu_pages ) {
$sub_menu_pages[] = array(
'wpseo_dashboard',
__( 'AMP', 'wordpress-seo' ),
__( 'AMP', 'wordpress-seo' ),
'manage_options',
'wpseo_amp',
array( $this, 'display' ),
array( array( $this, 'enqueue_admin_page' ) ),
);
return $sub_menu_pages;
}
/**
* Displays the admin page
*/
public function display() {
require 'views/admin-page.php';
}
/**
* Enqueue admin page JS
*/
public function enqueue_admin_page() {
wp_enqueue_style( 'yoast_amp_css', plugin_dir_url( __FILE__ ) . 'assets/amp-admin-page.css', array( 'wp-color-picker' ), false );
wp_enqueue_media(); // enqueue files needed for upload functionality
wp_enqueue_script( 'wpseo-admin-media', plugin_dir_url( __FILE__ ) . 'assets/wp-seo-admin-media.js', array(
'jquery',
'jquery-ui-core',
), false, true );
wp_localize_script( 'wpseo-admin-media', 'wpseoMediaL10n', $this->localize_media_script() );
wp_enqueue_script( 'yoast_amp_js', plugin_dir_url( __FILE__ ) . 'assets/amp-admin-page.js', array(
'jquery',
'wp-color-picker'
), false, true );
}
/**
* Pass some variables to js for upload module.
*
* @return array
*/
public function localize_media_script() {
return array(
'choose_image' => __( 'Use Logo', 'wordpress-seo' ),
);
}
/**
* Add admin page to admin_pages so the correct assets are loaded by WPSEO
*
* @param $admin_pages
*
* @return array
*/
public function add_admin_pages( $admin_pages ) {
$admin_pages[] = 'wpseo_amp';
return $admin_pages;
}
/**
* Render a color picker
*
* @param string $var
* @param string $label
*
* @SuppressWarnings("PMD.UnusedPrivateMethod") // As this is used in a view
*/
private function color_picker( $var, $label ) {
echo '<label class="checkbox" for="', esc_attr( $var ), '">', esc_html( $label ), '</label>';
echo '<input type="text" name="wpseo_amp[', esc_attr( $var ), ']"';
if ( isset( $this->options[ $var ] ) ) {
echo ' value="' . esc_attr( $this->options[ $var ] ) . '"';
}
echo ' class="yst_colorpicker" id="', esc_attr( $var ), '"/>';
echo '<br/>';
}
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* @package YoastSEO_AMP_Glue\CSS_Builder
* @author Jip Moors
* @copyright 2016 Yoast BV
* @license GPL-2.0+
*/
if ( ! class_exists( 'YoastSEO_AMP_CSS_Builder', false ) ) {
class YoastSEO_AMP_CSS_Builder {
/** @var array Option to CSS lookup map */
private $items = array();
/**
* Add option to CSS map
*
* @param string $option_key Option key.
* @param string $selector CSS Selector.
* @param string $property CSS Property that will hold the value of the option.
*/
public function add_option( $option_key, $selector, $property ) {
$this->items[ $option_key ] = array( 'selector' => $selector, 'property' => $property );
}
/**
* @return string Output CSS
*/
public function build() {
$options = YoastSEO_AMP_Options::get();
$output = "\n";
$css = array();
$options = array_filter( $options );
$apply = array_intersect_key( $this->items, $options );
if ( is_array( $apply ) ) {
foreach ( $apply as $key => $placement ) {
if ( ! isset( $css[ $placement['selector'] ] ) ) {
$css[ $placement['selector'] ] = array();
}
$css[ $placement['selector'] ][ $placement['property'] ] = $options[ $key ];
}
}
if ( ! empty( $css ) ) {
foreach ( $css as $selector => $properties ) {
$inner = '';
foreach ( $properties as $property => $value ) {
$inner .= sprintf( "%s: %s;\n", $property, $value );
}
$output .= sprintf( "%s {\n%s}\n", $selector, $inner );
}
}
return $output;
}
}
}

View File

@ -0,0 +1,396 @@
<?php
/**
* @package YoastSEO_AMP_Glue\Frontend
* @author Joost de Valk
* @copyright 2016 Yoast BV
* @license GPL-2.0+
*/
if ( ! class_exists( 'YoastSEO_AMP_Frontend' ) ) {
/**
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
*/
class YoastSEO_AMP_Frontend {
/**
* @var WPSEO_Frontend
*/
private $front;
/**
* @var array
*/
private $options;
/**
* @var array
*/
private $wpseo_options;
/**
* YoastSEO_AMP_Frontend constructor.
*/
public function __construct() {
$this->set_options();
add_action( 'amp_init', array( $this, 'post_types' ) );
add_action( 'amp_post_template_css', array( $this, 'additional_css' ) );
add_action( 'amp_post_template_head', array( $this, 'extra_head' ) );
add_action( 'amp_post_template_footer', array( $this, 'extra_footer' ) );
add_filter( 'amp_post_template_data', array( $this, 'fix_amp_post_data' ) );
add_filter( 'amp_post_template_metadata', array( $this, 'fix_amp_post_metadata' ), 10, 2 );
add_filter( 'amp_post_template_analytics', array( $this, 'analytics' ) );
add_filter( 'amp_content_sanitizers', array( $this, 'add_sanitizer' ) );
}
private function set_options() {
$this->wpseo_options = WPSEO_Options::get_all();
$this->options = YoastSEO_AMP_Options::get();
}
/**
* Add our own sanitizer to the array of sanitizers
*
* @param array $sanitizers
*
* @return array
*/
public function add_sanitizer( $sanitizers ) {
require_once 'class-sanitizer.php';
$sanitizers['Yoast_AMP_Blacklist_Sanitizer'] = array();
return $sanitizers;
}
/**
* If analytics tracking has been set, output it now.
*
* @param array $analytics
*
* @return array
*/
public function analytics( $analytics ) {
// If Monster Insights is outputting analytics, don't do anything.
if ( ! empty( $analytics['monsterinsights-googleanalytics'] ) ) {
// Clear analytics-extra options because Monster Insights is taking care of everything.
$this->options['analytics-extra'] = '';
return $analytics;
}
if ( ! empty( $this->options['analytics-extra'] ) ) {
return $analytics;
}
if ( ! class_exists( 'Yoast_GA_Options' ) || Yoast_GA_Options::instance()->get_tracking_code() === null ) {
return $analytics;
}
$UA = Yoast_GA_Options::instance()->get_tracking_code();
$analytics['yst-googleanalytics'] = array(
'type' => 'googleanalytics',
'attributes' => array(),
'config_data' => array(
'vars' => array(
'account' => $UA
),
'triggers' => array(
'trackPageview' => array(
'on' => 'visible',
'request' => 'pageview',
),
),
),
);
return $analytics;
}
/**
* Make AMP work for all the post types we want it for
*/
public function post_types() {
$post_types = get_post_types( array( 'public' => true ), 'objects' );
if ( is_array( $post_types ) && $post_types !== array() ) {
foreach ( $post_types as $post_type ) {
$post_type_name = $post_type->name;
if ( ! isset( $this->options[ 'post_types-' . $post_type_name . '-amp' ] ) ) {
continue;
}
// If AMP page support is not present, don't allow enabling it here.
if ( 'page' === $post_type_name && ! post_type_supports( 'page', AMP_QUERY_VAR ) ) {
continue;
}
if ( $this->options[ 'post_types-' . $post_type_name . '-amp' ] === 'on' ) {
add_post_type_support( $post_type_name, AMP_QUERY_VAR );
continue;
}
if ( 'post' === $post_type_name ) {
add_action( 'wp', array( $this, 'disable_amp_for_posts' ) );
continue;
}
remove_post_type_support( $post_type_name, AMP_QUERY_VAR );
}
}
}
/**
* Disables AMP for posts specifically, run later because of AMP plugin internals
*/
public function disable_amp_for_posts() {
remove_post_type_support( 'post', AMP_QUERY_VAR );
}
/**
* Fix the basic AMP post data
*
* @param array $data
*
* @return array
*/
public function fix_amp_post_data( $data ) {
if ( ! $this->front ) {
$this->front = WPSEO_Frontend::get_instance();
}
$data['canonical_url'] = $this->front->canonical( false );
if ( ! empty( $this->options['amp_site_icon'] ) ) {
$data['site_icon_url'] = $this->options['amp_site_icon'];
}
// If we are loading extra analytics, we need to load the module too.
if ( ! empty( $this->options['analytics-extra'] ) ) {
$data['amp_component_scripts']['amp-analytics'] = 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js';
}
return $data;
}
/**
* Fix the AMP metadata for a post
*
* @param array $metadata
* @param WP_Post $post
*
* @return array
*/
public function fix_amp_post_metadata( $metadata, $post ) {
if ( ! $this->front ) {
$this->front = WPSEO_Frontend::get_instance();
}
$this->build_organization_object( $metadata );
$desc = $this->front->metadesc( false );
if ( $desc ) {
$metadata['description'] = $desc;
}
$image = isset( $metadata['image'] ) ? $metadata['image'] : null;
$metadata['image'] = $this->get_image( $post, $image );
$metadata['@type'] = $this->get_post_schema_type( $post );
return $metadata;
}
/**
* Add additional CSS to the AMP output
*/
public function additional_css() {
require 'views/additional-css.php';
$selectors = $this->get_class_selectors();
$css_builder = new YoastSEO_AMP_CSS_Builder();
$css_builder->add_option( 'header-color', $selectors[ 'header-color' ], 'background' );
$css_builder->add_option( 'headings-color', $selectors[ 'headings-color' ], 'color' );
$css_builder->add_option( 'text-color', $selectors[ 'text-color' ], 'color' );
$css_builder->add_option( 'blockquote-bg-color', $selectors[ 'blockquote-bg-color' ], 'background-color' );
$css_builder->add_option( 'blockquote-border-color', $selectors[ 'blockquote-border-color' ], 'border-color' );
$css_builder->add_option( 'blockquote-text-color', $selectors[ 'blockquote-text-color' ], 'color' );
$css_builder->add_option( 'link-color', $selectors[ 'link-color' ], 'color' );
$css_builder->add_option( 'link-color-hover', $selectors[ 'link-color-hover' ], 'color' );
$css_builder->add_option( 'meta-color', $selectors[ 'meta-color' ], 'color' );
echo $css_builder->build();
if ( ! empty( $this->options['extra-css'] ) ) {
$safe_text = strip_tags( $this->options['extra-css'] );
$safe_text = wp_check_invalid_utf8( $safe_text );
$safe_text = _wp_specialchars( $safe_text, ENT_NOQUOTES );
echo $safe_text;
}
}
/**
* Outputs extra code in the head, if set
*/
public function extra_head() {
$options = WPSEO_Options::get_option( 'wpseo_social' );
if ( $options['twitter'] === true ) {
WPSEO_Twitter::get_instance();
}
if ( $options['opengraph'] === true ) {
$GLOBALS['wpseo_og'] = new WPSEO_OpenGraph;
}
do_action( 'wpseo_opengraph' );
echo strip_tags( $this->options['extra-head'], '<link><meta>' );
}
/**
* Outputs analytics code in the footer, if set
*/
public function extra_footer() {
echo $this->options['analytics-extra'];
}
/**
* Builds the organization object if needed.
*
* @param array $metadata
*/
private function build_organization_object( &$metadata ) {
// While it's using the blog name, it's actually outputting the company name.
if ( ! empty( $this->wpseo_options['company_name'] ) ) {
$metadata['publisher']['name'] = $this->wpseo_options['company_name'];
}
// The logo needs to be 600px wide max, 60px high max.
$logo = $this->get_image_object( $this->wpseo_options['company_logo'], array( 600, 60 ) );
if ( is_array( $logo ) ) {
$metadata['publisher']['logo'] = $logo;
}
}
/**
* Builds an image object array from an image URL
*
* @param string $image_url Image URL to build URL for.
* @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width
* and height values in pixels (in that order). Default 'full'.
*
* @return array|false
*/
private function get_image_object( $image_url, $size = 'full' ) {
if ( empty( $image_url ) ) {
return false;
}
$image_id = attachment_url_to_postid( $image_url );
$image_src = wp_get_attachment_image_src( $image_id, $size );
if ( is_array( $image_src ) ) {
return array(
'@type' => 'ImageObject',
'url' => $image_src[0],
'width' => $image_src[1],
'height' => $image_src[2]
);
}
return false;
}
/**
* Retrieve the Schema.org image for the post
*
* @param WP_Post $post Post to retrieve the data for.
* @param array|null $image The currently set post image.
*
* @return array
*/
private function get_image( $post, $image ) {
$og_image = $this->get_image_object( WPSEO_Meta::get_value( 'opengraph-image', $post->ID ) );
if ( is_array( $og_image ) ) {
return $og_image;
}
// Posts without an image fail validation in Google, leading to Search Console errors
if ( ! is_array( $image ) && isset( $this->options['default_image'] ) ) {
return $this->get_image_object( $this->options['default_image'] );
}
return $image;
}
/**
* Gets the Schema.org type for the post, based on the post type.
*
* @param WP_Post $post
*
* @return string
*/
private function get_post_schema_type( $post ) {
$type = 'WebPage';
if ( 'post' === $post->post_type ) {
$type = 'Article';
}
/**
* Filter: 'yoastseo_amp_schema_type' - Allow changing the Schema.org type for the post
*
* @api string $type The Schema.org type for the $post
*
* @param WP_Post $post
*/
$type = apply_filters( 'yoastseo_amp_schema_type', $type, $post );
return $type;
}
/**
* Gets version dependent class names
*
* @return array
*/
private function get_class_selectors() {
$selectors = array(
'header-color' => 'nav.amp-wp-title-bar',
'headings-color' => '.amp-wp-title, h2, h3, h4',
'text-color' => '.amp-wp-content',
'blockquote-bg-color' => '.amp-wp-content blockquote',
'blockquote-border-color' => '.amp-wp-content blockquote',
'blockquote-text-color' => '.amp-wp-content blockquote',
'link-color' => 'a, a:active, a:visited',
'link-color-hover' => 'a:hover, a:focus',
'meta-color' => '.amp-wp-meta li, .amp-wp-meta li a',
);
// CSS classnames have been changed in version 0.4.0.
if ( version_compare( AMP__VERSION, '0.4.0', '>=' ) ) {
$selectors_v4 = array(
'header-color' => 'header.amp-wp-header, html',
'text-color' => 'div.amp-wp-article',
'blockquote-bg-color' => '.amp-wp-article-content blockquote',
'blockquote-border-color' => '.amp-wp-article-content blockquote',
'blockquote-text-color' => '.amp-wp-article-content blockquote',
'meta-color' => '.amp-wp-meta, .amp-wp-meta a',
);
$selectors = array_merge( $selectors, $selectors_v4 );
}
return $selectors;
}
}
}

View File

@ -0,0 +1,233 @@
<?php
/**
* @package YoastSEO_AMP_Glue\Options
* @author Jip Moors
* @copyright 2016 Yoast BV
* @license GPL-2.0+
*/
if ( ! class_exists( 'YoastSEO_AMP_Options' ) ) {
class YoastSEO_AMP_Options {
/** @var string Name of the option in the database */
private $option_name = 'wpseo_amp';
/** @var array Current options */
private $options;
/** @var array Option defaults */
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' => '',
);
/** @var self Class instance */
private static $instance;
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 $options
*
* @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;
}
/**
* @param string $source Raw input.
*
* @return string Sanitized code.
*/
private function sanitize_analytics_code( $source ) {
$source = trim( $source );
if ( empty( $source ) ) {
return $source;
}
$code = $source;
// Strip all tags, to verify JSON input.
$json = strip_tags( $code );
$parsed_json = json_decode( $json, true );
// Non-parsable JSON is always bad.
if ( is_null( $parsed_json ) ) {
return '';
}
$allowed_tags = strip_tags( $code, '<amp-analytics>' );
// Strip JSON content so we can apply verified script tag.
$tag = str_replace( $json, '', $allowed_tags );
// If the tag doesn't occur in the code, the code is invalid.
if ( false === strpos( $allowed_tags, '<amp-analytics' ) ) {
return '';
}
$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 );
}
/**
* Get the options
*
* @return array
*/
public static function get() {
$me = self::get_instance();
$me->fetch_options();
return $me->options;
}
/**
* @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;
}
}
}
}
}

View File

@ -0,0 +1,149 @@
<?php
if ( ! defined( 'AMP__DIR__' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-base-sanitizer.php' );
/**
* Strips blacklisted tags and attributes from content, on top of the ones the AMP plugin already removes.
*
* See following for blacklist:
* https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#html-tags
*/
class Yoast_AMP_Blacklist_Sanitizer extends AMP_Base_Sanitizer {
/**
* The actual sanitization function
*/
public function sanitize() {
$body = $this->get_body_node();
$this->strip_attributes_recursive( $body );
}
/**
* Passes through the DOM and removes stuff that shouldn't be there.
*
* @param DOMNode $node
*/
private function strip_attributes_recursive( $node ) {
if ( $node->nodeType !== XML_ELEMENT_NODE ) {
return;
}
if ( $node->hasAttributes() ) {
$node_name = $node->nodeName;
$length = $node->attributes->length;
for ( $i = $length - 1; $i >= 0; $i -- ) {
$attribute = $node->attributes->item( $i );
switch ( $node_name ) {
case 'a':
$this->sanitize_a_attribute( $node, $attribute );
break;
case 'pre':
$this->sanitize_pre_attribute( $node, $attribute );
break;
case 'table':
$this->sanitize_table_attribute( $node, $attribute );
break;
case 'td':
case 'th':
$this->sanitize_cell_attribute( $node, $attribute );
break;
}
}
}
foreach ( $node->childNodes as $child_node ) {
$this->strip_attributes_recursive( $child_node );
}
}
/**
* Passes through the DOM and strips forbidden tags
*
* @param DOMNode $node
* @param array $tag_names
*/
private function strip_tags( $node, $tag_names ) {
foreach ( $tag_names as $tag_name ) {
$elements = $node->getElementsByTagName( $tag_name );
$length = $elements->length;
if ( 0 === $length ) {
continue;
}
for ( $i = $length - 1; $i >= 0; $i -- ) {
$element = $elements->item( $i );
$parent_node = $element->parentNode;
$parent_node->removeChild( $element );
if ( 'body' !== $parent_node->nodeName && AMP_DOM_Utils::is_node_empty( $parent_node ) ) {
$parent_node->parentNode->removeChild( $parent_node );
}
}
}
}
/**
* Sanitizes anchor attributes
*
* @param DOMNode $node
* @param object $attribute
*/
private function sanitize_a_attribute( $node, $attribute ) {
$attribute_name = strtolower( $attribute->name );
if ( 'rel' === $attribute_name && 'nofollow' !== $attribute->value ) {
$node->removeAttribute( $attribute_name );
}
}
/**
* Sanitizes pre tag attributes
*
* @param DOMNode $node
* @param object $attribute
*/
private function sanitize_pre_attribute( $node, $attribute ) {
$attribute_name = strtolower( $attribute->name );
if ( 'line' === $attribute_name ) {
$node->removeAttribute( $attribute_name );
}
}
/**
* Sanitizes td / th tag attributes
*
* @param DOMNode $node
* @param object $attribute
*/
private function sanitize_cell_attribute( $node, $attribute ) {
$attribute_name = strtolower( $attribute->name );
if ( in_array( $attribute_name, array( 'width', 'height' ) ) ) {
$node->removeAttribute( $attribute_name );
}
}
/**
* Sanitize table tag
* attributes
*
* @param DOMNode $node
* @param object $attribute
*/
private function sanitize_table_attribute( $node, $attribute ) {
$attribute_name = strtolower( $attribute->name );
if ( in_array( $attribute_name, array( 'border', 'cellspacing', 'cellpadding', 'summary' ) ) ) {
$node->removeAttribute( $attribute_name );
}
}
}

View File

@ -0,0 +1,7 @@
td, th {
text-align: left;
}
a, a:active, a:visited {
text-decoration: <?php echo ( ( 'underline' === $this->options['underline'] ) ? 'underline' : 'none' ); ?>;
}

View File

@ -0,0 +1,152 @@
<?php
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
$yform = Yoast_Form::get_instance();
$yform->admin_header( true, 'wpseo_amp', false, 'wpseo_amp_settings' );
?>
<h2 class="nav-tab-wrapper" id="wpseo-tabs">
<a class="nav-tab" id="posttypes-tab" href="#top#posttypes"><?php echo esc_html( __( 'Post types', 'wordpress-seo' ) ); ?></a>
<a class="nav-tab" id="design-tab" href="#top#design"><?php echo esc_html( __( 'Design', 'wordpress-seo' ) ); ?></a>
<a class="nav-tab" id="analytics-tab" href="#top#analytics"><?php echo esc_html( __( 'Analytics', 'wordpress-seo' ) ); ?></a>
</h2>
<div class="tabwrapper">
<div id="posttypes" class="wpseotab">
<h2><?php echo esc_html( __( 'Post types that have AMP support', 'wordpress-seo' ) ); ?></h2>
<p><?php echo esc_html( __( 'Generally you\'d want this to be your news post types.', 'wordpress-seo' ) ); ?><br/>
<?php echo esc_html( __( 'Post is enabled by default, feel free to enable any of them.', 'wordpress-seo' ) ); ?></p>
<?php
$post_types = apply_filters( 'wpseo_sitemaps_supported_post_types', get_post_types( array( 'public' => true ), 'objects' ) );
// Allow specific AMP post type overrides, especially needed for Page support.
$post_types = apply_filters( 'wpseo_amp_supported_post_types', $post_types );
if ( is_array( $post_types ) && $post_types !== array() ) {
foreach ( $post_types as $pt ) {
$yform->toggle_switch(
'post_types-' . $pt->name . '-amp',
array(
'on' => __( 'Enabled', 'wordpress-seo' ),
'off' => __( 'Disabled', 'wordpress-seo' )
),
$pt->labels->name . ' (<code>' . $pt->name . '</code>)'
);
}
}
if ( ! post_type_supports( 'page', AMP_QUERY_VAR ) ):
?>
<br>
<strong><?php echo esc_html( __( 'Please note:', 'wordpress-seo' ) ); ?></strong>
<?php echo esc_html( __( 'Currently pages are not supported by the AMP plugin.', 'wordpress-seo' ) ); ?>
<?php
endif;
?>
</p>
</div>
<div id="design" class="wpseotab">
<h3><?php echo esc_html( __( 'Images', 'wordpress-seo' ) ); ?></h3>
<?php
$yform->media_input( 'amp_site_icon', __( 'AMP icon', 'wordpress-seo' ) ); ?>
<p class="desc"><?php echo esc_html( __( 'Must be at least 32px &times; 32px', 'wordpress-seo' ) ); ?></p>
<br/>
<?php
$yform->media_input( 'default_image', __( 'Default image', 'wordpress-seo' ) ); ?>
<p class="desc"><?php echo esc_html( __( 'Used when a post doesn\'t have an image associated with it.', 'wordpress-seo' ) ); ?>
<br><?php echo esc_html( __( 'The image must be at least 696px wide.', 'wordpress-seo' ) ) ?></p>
<br/>
<h3><?php echo esc_html( __( 'Content colors', 'wordpress-seo' ) ); ?></h3>
<?php
$this->color_picker( 'header-color', __( 'AMP Header color', 'wordpress-seo' ) );
$this->color_picker( 'headings-color', __( 'Title color', 'wordpress-seo' ) );
$this->color_picker( 'text-color', __( 'Text color', 'wordpress-seo' ) );
$this->color_picker( 'meta-color', __( 'Post meta info color', 'wordpress-seo' ) );
?>
<br/>
<h3><?php echo esc_html( __( 'Links', 'wordpress-seo' ) ); ?></h3>
<?php
$this->color_picker( 'link-color', __( 'Text color', 'wordpress-seo' ) );
$this->color_picker( 'link-color-hover', __( 'Hover color', 'wordpress-seo' ) );
?>
<?php $yform->light_switch( 'underline', __( 'Underline', 'wordpress-seo' ), array(
__( 'Underline', 'wordpress-seo' ),
__( 'No underline', 'wordpress-seo' )
) ); ?>
<br/>
<h3><?php echo esc_html( __( 'Blockquotes', 'wordpress-seo' ) ); ?></h3>
<?php
$this->color_picker( 'blockquote-text-color', __( 'Text color', 'wordpress-seo' ) );
$this->color_picker( 'blockquote-bg-color', __( 'Background color', 'wordpress-seo' ) );
$this->color_picker( 'blockquote-border-color', __( 'Border color', 'wordpress-seo' ) );
?>
<br/>
<h3><?php echo esc_html( __( 'Extra CSS', 'wordpress-seo' ) ); ?></h3>
<?php $yform->textarea( 'extra-css', __( 'Extra CSS', 'wordpress-seo' ), array(
'rows' => 5,
'cols' => 100
) ); ?>
<br/>
<h3><?php printf( esc_html( __( 'Extra code in %s', 'wordpress-seo' ) ), '<code>&lt;head&gt;</code>' ); ?></h3>
<p><?php echo sprintf( esc_html( __( 'Only %s and %s tags are allowed, other tags will be removed automatically.', 'wordpress-seo' ) ), '<code>meta</code>', '<code>link</code>' ) ?></p>
<?php $yform->textarea( 'extra-head', __( 'Extra code', 'wordpress-seo' ), array(
'rows' => 5,
'cols' => 100
) ); ?>
</div>
<div id="analytics" class="wpseotab">
<h2><?php echo esc_html( __( 'AMP Analytics', 'wordpress-seo' ) ); ?></h2>
<?php
if ( class_exists( 'Yoast_GA_Options' ) ) {
echo '<p>', esc_html( __( 'Because your Google Analytics plugin by Yoast is active, your AMP pages will also be tracked.', 'wordpress-seo' ) ), '<br>';
$UA = Yoast_GA_Options::instance()->get_tracking_code();
if ( $UA === null ) {
echo esc_html( __( 'Make sure to connect your Google Analytics plugin properly.', 'wordpress-seo' ) );
} else {
echo sprintf( esc_html( __( 'Pageviews will be tracked using the following account: %s.', 'wordpress-seo' ) ), '<code>' . $UA . '</code>' );
}
echo '</p>';
echo '<p>', esc_html( __( 'Optionally you can override the default AMP tracking code with your own by putting it below:', 'wordpress-seo' ) ), '</p>';
$yform->textarea( 'analytics-extra', __( 'Analytics code', 'wordpress-seo' ), array(
'rows' => 5,
'cols' => 100
) );
} else {
echo '<p>', esc_html( __( 'Optionally add a valid google analytics tracking code.', 'wordpress-seo' ) ), '</p>';
$yform->textarea( 'analytics-extra', __( 'Analytics code', 'wordpress-seo' ), array(
'rows' => 5,
'cols' => 100
) );
}
?>
</div>
</div>
<?php
$yform->admin_footer();