Version Description
- Split the plugin into several classes.
- Added a settings page, found under SEO -> AMP
- This new settings page has:
- A post types settings tab;
- A design settings tab;
- An analytics integration tab.
- Added sanitization functions that further clean up AMP output to make sure more pages pass validation.
- Added a default image (settable on the design tab) to use when a post has no image. This because the image in the JSON+LD output is required by Google.
- The plugin now automatically enables AMP GA tracking when GA by Yoast is enabled, but also allows you to add custom tracking.
Download this release
Release Info
Developer | joostdevalk |
Plugin | Glue for Yoast SEO & AMP |
Version | 0.3 |
Comparing to | |
See all releases |
Code changes from version 0.2 to 0.3
- classes/assets/amp-admin-page.css +3 -0
- classes/assets/amp-admin-page.js +3 -0
- classes/assets/wp-seo-admin-media.js +36 -0
- classes/class-backend.php +119 -0
- classes/class-build-css.php +65 -0
- classes/class-frontend.php +311 -0
- classes/class-options.php +146 -0
- classes/class-sanitizer.php +179 -0
- classes/views/additional-css.php +7 -0
- classes/views/admin-page.php +141 -0
- readme.txt +13 -25
- yoastseo-amp.php +20 -114
classes/assets/amp-admin-page.css
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
.yst_colorpicker {
|
2 |
+
clear: right;
|
3 |
+
}
|
classes/assets/amp-admin-page.js
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($){
|
2 |
+
$('.yst_colorpicker').wpColorPicker();
|
3 |
+
});
|
classes/assets/wp-seo-admin-media.js
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* global wpseoMediaL10n */
|
2 |
+
/* global ajaxurl */
|
3 |
+
/* global wp */
|
4 |
+
/* jshint -W097 */
|
5 |
+
/* jshint -W003 */
|
6 |
+
/* jshint unused:false */
|
7 |
+
|
8 |
+
// Taken and adapted from http://www.webmaster-source.com/2013/02/06/using-the-wordpress-3-5-media-uploader-in-your-plugin-or-theme/
|
9 |
+
jQuery(document).ready(
|
10 |
+
function($) {
|
11 |
+
'use strict';
|
12 |
+
if( typeof wp.media === 'undefined' ) {
|
13 |
+
return;
|
14 |
+
}
|
15 |
+
|
16 |
+
$('.wpseo_image_upload_button').each(function(index, element) {
|
17 |
+
var wpseo_target_id = $(element).attr('id').replace(/_button$/, '');
|
18 |
+
var wpseo_custom_uploader = wp.media.frames.file_frame = wp.media({
|
19 |
+
title: wpseoMediaL10n.choose_image,
|
20 |
+
button: { text: wpseoMediaL10n.choose_image },
|
21 |
+
multiple: false
|
22 |
+
});
|
23 |
+
|
24 |
+
wpseo_custom_uploader.on( 'select', function() {
|
25 |
+
var attachment = wpseo_custom_uploader.state().get( 'selection' ).first().toJSON();
|
26 |
+
$( '#' + wpseo_target_id ).val( attachment.url );
|
27 |
+
}
|
28 |
+
);
|
29 |
+
|
30 |
+
$(element).click( function( e ) {
|
31 |
+
e.preventDefault();
|
32 |
+
wpseo_custom_uploader.open();
|
33 |
+
} );
|
34 |
+
} );
|
35 |
+
}
|
36 |
+
);
|
classes/class-backend.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package YoastSEO_AMP_Glue\Admin
|
4 |
+
* @author Joost de Valk
|
5 |
+
* @copyright 2016 Yoast BV
|
6 |
+
* @license GPL-2.0+
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'YoastSEO_AMP_Backend', false ) ) {
|
10 |
+
/**
|
11 |
+
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
|
12 |
+
*/
|
13 |
+
class YoastSEO_AMP_Backend {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var array
|
17 |
+
*/
|
18 |
+
public $options;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* YoastSEO_AMP_Backend constructor.
|
22 |
+
*/
|
23 |
+
public function __construct() {
|
24 |
+
$this->options = YoastSEO_AMP_Options::get();
|
25 |
+
|
26 |
+
// Add subitem to menu
|
27 |
+
add_filter( 'wpseo_submenu_pages', array( $this, 'add_submenu_page' ) );
|
28 |
+
|
29 |
+
// Register AMP admin page as a Yoast SEO admin page
|
30 |
+
add_filter( 'wpseo_admin_pages', array( $this, 'add_admin_pages' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Add submenu item
|
35 |
+
*
|
36 |
+
* @param array $sub_menu_pages
|
37 |
+
*
|
38 |
+
* @return array
|
39 |
+
*/
|
40 |
+
public function add_submenu_page( $sub_menu_pages ) {
|
41 |
+
|
42 |
+
$sub_menu_pages[] = array(
|
43 |
+
'wpseo_dashboard',
|
44 |
+
__( 'AMP', 'wordpress-seo' ),
|
45 |
+
__( 'AMP', 'wordpress-seo' ),
|
46 |
+
'manage_options',
|
47 |
+
'wpseo_amp',
|
48 |
+
array( $this, 'display' ),
|
49 |
+
array( array( $this, 'enqueue_admin_page' ) ),
|
50 |
+
);
|
51 |
+
|
52 |
+
return $sub_menu_pages;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Displays the admin page
|
57 |
+
*/
|
58 |
+
public function display() {
|
59 |
+
require 'views/admin-page.php';
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Enqueue admin page JS
|
64 |
+
*/
|
65 |
+
public function enqueue_admin_page() {
|
66 |
+
wp_enqueue_style( 'yoast_amp_css', plugin_dir_url( __FILE__ ) . 'assets/amp-admin-page.css', array( 'wp-color-picker' ), false );
|
67 |
+
|
68 |
+
wp_enqueue_media(); // enqueue files needed for upload functionality
|
69 |
+
wp_enqueue_script( 'wpseo-admin-media', plugin_dir_url( __FILE__ ) . 'assets/wp-seo-admin-media.js', array(
|
70 |
+
'jquery',
|
71 |
+
'jquery-ui-core',
|
72 |
+
), false, true );
|
73 |
+
wp_localize_script( 'wpseo-admin-media', 'wpseoMediaL10n', $this->localize_media_script() );
|
74 |
+
|
75 |
+
wp_enqueue_script( 'yoast_amp_js', plugin_dir_url( __FILE__ ) . 'assets/amp-admin-page.js', array(
|
76 |
+
'jquery',
|
77 |
+
'wp-color-picker'
|
78 |
+
), false, true );
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Pass some variables to js for upload module.
|
83 |
+
*
|
84 |
+
* @return array
|
85 |
+
*/
|
86 |
+
public function localize_media_script() {
|
87 |
+
return array(
|
88 |
+
'choose_image' => __( 'Use Logo', 'wordpress-seo' ),
|
89 |
+
);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Add admin page to admin_pages so the correct assets are loaded by WPSEO
|
94 |
+
*
|
95 |
+
* @param $admin_pages
|
96 |
+
*
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
public function add_admin_pages( $admin_pages ) {
|
100 |
+
$admin_pages[] = 'wpseo_amp';
|
101 |
+
|
102 |
+
return $admin_pages;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @param string $var
|
107 |
+
* @param string $label
|
108 |
+
*/
|
109 |
+
private function color_picker( $var, $label ) {
|
110 |
+
echo '<label class="checkbox" for="', $var, '">', $label, '</label>';
|
111 |
+
echo '<input type="text" name="wpseo_amp[', $var, ']"';
|
112 |
+
if ( isset( $this->options[ $var ] ) ) {
|
113 |
+
echo ' value="' . $this->options[ $var ] . '"';
|
114 |
+
}
|
115 |
+
echo ' class="yst_colorpicker" id="', $var, '"/>';
|
116 |
+
echo '<br/>';
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
classes/class-build-css.php
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package YoastSEO_AMP_Glue\CSS_Builder
|
4 |
+
* @author Jip Moors
|
5 |
+
* @copyright 2016 Yoast BV
|
6 |
+
* @license GPL-2.0+
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'YoastSEO_AMP_CSS_Builder', false ) ) {
|
10 |
+
|
11 |
+
class YoastSEO_AMP_CSS_Builder {
|
12 |
+
|
13 |
+
/** @var array Option to CSS lookup map */
|
14 |
+
private $items = array();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Add option to CSS map
|
18 |
+
*
|
19 |
+
* @param string $option_key Option key.
|
20 |
+
* @param string $selector CSS Selector.
|
21 |
+
* @param string $property CSS Property that will hold the value of the option.
|
22 |
+
*/
|
23 |
+
public function add_option( $option_key, $selector, $property ) {
|
24 |
+
$this->items[ $option_key ] = array( 'selector' => $selector, 'property' => $property );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @return string Output CSS
|
29 |
+
*/
|
30 |
+
public function build() {
|
31 |
+
$options = YoastSEO_AMP_Options::get();
|
32 |
+
|
33 |
+
$output = "\n";
|
34 |
+
$css = array();
|
35 |
+
|
36 |
+
$options = array_filter( $options );
|
37 |
+
$apply = array_intersect_key( $this->items, $options );
|
38 |
+
|
39 |
+
if ( is_array( $apply ) ) {
|
40 |
+
foreach ( $apply as $key => $placement ) {
|
41 |
+
|
42 |
+
if ( ! isset( $css[ $placement['selector'] ] ) ) {
|
43 |
+
$css[ $placement['selector'] ] = array();
|
44 |
+
}
|
45 |
+
|
46 |
+
$css[ $placement['selector'] ][ $placement['property'] ] = $options[ $key ];
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
if ( ! empty( $css ) ) {
|
51 |
+
foreach ( $css as $selector => $properties ) {
|
52 |
+
|
53 |
+
$inner = '';
|
54 |
+
foreach ( $properties as $property => $value ) {
|
55 |
+
$inner .= sprintf( "%s: %s;\n", $property, $value );
|
56 |
+
}
|
57 |
+
|
58 |
+
$output .= sprintf( "%s {\n%s}\n", $selector, $inner );
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
return $output;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
classes/class-frontend.php
ADDED
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package YoastSEO_AMP_Glue\Frontend
|
4 |
+
* @author Joost de Valk
|
5 |
+
* @copyright 2016 Yoast BV
|
6 |
+
* @license GPL-2.0+
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'YoastSEO_AMP_Frontend' ) ) {
|
10 |
+
/**
|
11 |
+
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
|
12 |
+
*/
|
13 |
+
class YoastSEO_AMP_Frontend {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var WPSEO_Frontend
|
17 |
+
*/
|
18 |
+
private $front;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var array
|
22 |
+
*/
|
23 |
+
private $options;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @var array
|
27 |
+
*/
|
28 |
+
private $wpseo_options;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* YoastSEO_AMP_Frontend constructor.
|
32 |
+
*/
|
33 |
+
public function __construct() {
|
34 |
+
$this->set_options();
|
35 |
+
|
36 |
+
add_action( 'wp', array( $this, 'post_types' ) );
|
37 |
+
|
38 |
+
add_action( 'amp_post_template_css', array( $this, 'additional_css' ) );
|
39 |
+
add_action( 'amp_post_template_head', array( $this, 'extra_head' ) );
|
40 |
+
add_action( 'amp_post_template_footer', array( $this, 'extra_footer' ) );
|
41 |
+
|
42 |
+
add_filter( 'amp_post_template_data', array( $this, 'fix_amp_post_data' ) );
|
43 |
+
add_filter( 'amp_post_template_metadata', array( $this, 'fix_amp_post_metadata' ), 10, 2 );
|
44 |
+
add_filter( 'amp_post_template_analytics', array( $this, 'analytics' ) );
|
45 |
+
|
46 |
+
add_filter( 'amp_content_sanitizers', array( $this, 'add_sanitizer' ) );
|
47 |
+
}
|
48 |
+
|
49 |
+
private function set_options() {
|
50 |
+
$this->wpseo_options = WPSEO_Options::get_all();
|
51 |
+
$this->options = YoastSEO_AMP_Options::get();
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Add our own sanitizer to the array of sanitizers
|
56 |
+
*
|
57 |
+
* @param array $sanitizers
|
58 |
+
*
|
59 |
+
* @return array
|
60 |
+
*/
|
61 |
+
public function add_sanitizer( $sanitizers ) {
|
62 |
+
require_once 'class-sanitizer.php';
|
63 |
+
|
64 |
+
$sanitizers['Yoast_AMP_Blacklist_Sanitizer'] = array();
|
65 |
+
|
66 |
+
return $sanitizers;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* If analytics tracking has been set, output it now.
|
71 |
+
*
|
72 |
+
* @param array $analytics
|
73 |
+
*
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
public function analytics( $analytics ) {
|
77 |
+
if ( isset( $this->options['analytics-extra'] ) && ! empty( $this->options['analytics-extra'] ) ) {
|
78 |
+
return $analytics;
|
79 |
+
}
|
80 |
+
|
81 |
+
if ( ! class_exists( 'Yoast_GA_Options' ) || Yoast_GA_Options::instance()->get_tracking_code() === null ) {
|
82 |
+
return $analytics;
|
83 |
+
}
|
84 |
+
$UA = Yoast_GA_Options::instance()->get_tracking_code();
|
85 |
+
|
86 |
+
$analytics['yst-googleanalytics'] = array(
|
87 |
+
'type' => 'googleanalytics',
|
88 |
+
'attributes' => array(
|
89 |
+
),
|
90 |
+
'config_data' => array(
|
91 |
+
'vars' => array(
|
92 |
+
'account' => $UA
|
93 |
+
),
|
94 |
+
'triggers' => array(
|
95 |
+
'trackPageview' => array(
|
96 |
+
'on' => 'visible',
|
97 |
+
'request' => 'pageview',
|
98 |
+
),
|
99 |
+
),
|
100 |
+
),
|
101 |
+
);
|
102 |
+
|
103 |
+
return $analytics;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Make AMP work for all the post types we want it for
|
108 |
+
*/
|
109 |
+
public function post_types() {
|
110 |
+
$post_types = get_post_types( array( 'public' => true ), 'objects' );
|
111 |
+
if ( is_array( $post_types ) && $post_types !== array() ) {
|
112 |
+
foreach ( $post_types as $pt ) {
|
113 |
+
if ( $this->options[ 'post_types-' . $pt->name . '-amp' ] === 'on' ) {
|
114 |
+
add_post_type_support( $pt->name, AMP_QUERY_VAR );
|
115 |
+
}
|
116 |
+
else {
|
117 |
+
remove_post_type_support( $pt->name, AMP_QUERY_VAR );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Fix the basic AMP post data
|
125 |
+
*
|
126 |
+
* @param array $data
|
127 |
+
*
|
128 |
+
* @return array
|
129 |
+
*/
|
130 |
+
public function fix_amp_post_data( $data ) {
|
131 |
+
$data['canonical_url'] = $this->front->canonical( false );
|
132 |
+
if ( ! empty( $this->options['amp_site_icon'] ) ) {
|
133 |
+
$data['site_icon_url'] = $this->options['amp_site_icon'];
|
134 |
+
}
|
135 |
+
|
136 |
+
// If we are loading extra analytics, we need to load the module too.
|
137 |
+
if ( ! empty( $this->options['analytics-extra'] ) ) {
|
138 |
+
$data['amp_component_scripts']['amp-analytics'] = 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js';
|
139 |
+
}
|
140 |
+
|
141 |
+
return $data;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Fix the AMP metadata for a post
|
146 |
+
*
|
147 |
+
* @param array $metadata
|
148 |
+
* @param WP_Post $post
|
149 |
+
*
|
150 |
+
* @return array
|
151 |
+
*/
|
152 |
+
public function fix_amp_post_metadata( $metadata, $post ) {
|
153 |
+
$this->front = WPSEO_Frontend::get_instance();
|
154 |
+
|
155 |
+
$this->build_organization_object( $metadata );
|
156 |
+
|
157 |
+
$desc = $this->front->metadesc( false );
|
158 |
+
if ( $desc ) {
|
159 |
+
$metadata['description'] = $desc;
|
160 |
+
}
|
161 |
+
|
162 |
+
$metadata['image'] = $this->get_image( $post );
|
163 |
+
$metadata['@type'] = $this->get_post_schema_type( $post );
|
164 |
+
|
165 |
+
return $metadata;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Add additional CSS to the AMP output
|
170 |
+
*/
|
171 |
+
public function additional_css() {
|
172 |
+
|
173 |
+
require 'views/additional-css.php';
|
174 |
+
|
175 |
+
$css_builder = new YoastSEO_AMP_CSS_Builder();
|
176 |
+
$css_builder->add_option( 'header-color', 'nav.amp-wp-title-bar', 'background' );
|
177 |
+
$css_builder->add_option( 'headings-color', '.amp-wp-title, h2, h3, h4', 'color' );
|
178 |
+
$css_builder->add_option( 'text-color', '.amp-wp-content', 'color' );
|
179 |
+
|
180 |
+
$css_builder->add_option( 'blockquote-bg-color', '.amp-wp-content blockquote', 'background-color' );
|
181 |
+
$css_builder->add_option( 'blockquote-border-color', '.amp-wp-content blockquote', 'border-color' );
|
182 |
+
$css_builder->add_option( 'blockquote-text-color', '.amp-wp-content blockquote', 'color' );
|
183 |
+
|
184 |
+
$css_builder->add_option( 'link-color', 'a, a:active, a:visited', 'color' );
|
185 |
+
$css_builder->add_option( 'link-color-hover', 'a:hover, a:focus', 'color' );
|
186 |
+
|
187 |
+
$css_builder->add_option( 'meta-color', '.amp-wp-meta li, .amp-wp-meta li a', 'color' );
|
188 |
+
|
189 |
+
echo $css_builder->build();
|
190 |
+
|
191 |
+
echo esc_html( $this->options['extra-css'] );
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Outputs extra code in the head, if set
|
196 |
+
*/
|
197 |
+
public function extra_head() {
|
198 |
+
$options = WPSEO_Options::get_option( 'wpseo_social' );
|
199 |
+
|
200 |
+
if ( $options['twitter'] === true ) {
|
201 |
+
WPSEO_Twitter::get_instance();
|
202 |
+
}
|
203 |
+
|
204 |
+
if ( $options['opengraph'] === true ) {
|
205 |
+
$GLOBALS['wpseo_og'] = new WPSEO_OpenGraph;
|
206 |
+
}
|
207 |
+
|
208 |
+
do_action( 'wpseo_opengraph' );
|
209 |
+
|
210 |
+
echo strip_tags($this->options['extra-head'], '<link><meta>');
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Outputs analytics code in the footer, if set
|
215 |
+
*/
|
216 |
+
public function extra_footer() {
|
217 |
+
echo $this->options['analytics-extra'];
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Builds the organization object if needed.
|
222 |
+
*
|
223 |
+
* @param array $metadata
|
224 |
+
*/
|
225 |
+
private function build_organization_object( &$metadata ) {
|
226 |
+
// While it's using the blog name, it's actually outputting the company name.
|
227 |
+
if ( ! empty( $this->wpseo_options['company_name'] ) ) {
|
228 |
+
$metadata['publisher']['name'] = $this->wpseo_options['company_name'];
|
229 |
+
}
|
230 |
+
|
231 |
+
// The logo needs to be 600px wide max, 60px high max.
|
232 |
+
$logo = $this->get_image_object( $this->wpseo_options['company_logo'], array( 600, 60 ) );
|
233 |
+
if ( is_array( $logo ) ) {
|
234 |
+
$metadata['publisher']['logo'] = $logo;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Builds an image object array from an image URL
|
240 |
+
*
|
241 |
+
* @param string $image_url
|
242 |
+
* @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width
|
243 |
+
* and height values in pixels (in that order). Default 'full'.
|
244 |
+
*
|
245 |
+
* @return array|false
|
246 |
+
*/
|
247 |
+
private function get_image_object( $image_url, $size = 'full' ) {
|
248 |
+
if ( empty( $image_url ) ) {
|
249 |
+
return false;
|
250 |
+
}
|
251 |
+
|
252 |
+
$image_id = attachment_url_to_postid( $image_url );
|
253 |
+
$image_src = wp_get_attachment_image_src( $image_id, $size );
|
254 |
+
|
255 |
+
if ( is_array( $image_src ) ) {
|
256 |
+
return array(
|
257 |
+
'@type' => 'ImageObject',
|
258 |
+
'url' => $image_src[0],
|
259 |
+
'width' => $image_src[1],
|
260 |
+
'height' => $image_src[2]
|
261 |
+
);
|
262 |
+
}
|
263 |
+
|
264 |
+
return false;
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Retrieve the Schema.org image for the post
|
269 |
+
*
|
270 |
+
* @param WP_Post $post
|
271 |
+
*
|
272 |
+
* @return array|false
|
273 |
+
*/
|
274 |
+
private function get_image( $post ) {
|
275 |
+
$image = $this->get_image_object( WPSEO_Meta::get_value( 'opengraph-image', $post->ID ) );
|
276 |
+
|
277 |
+
// Posts without an image fail validation in Google, leading to Search Console errors
|
278 |
+
if ( ! is_array( $image ) && isset( $this->options['default_image'] ) ) {
|
279 |
+
$image = $this->get_image_object( $this->options['default_image'] );
|
280 |
+
}
|
281 |
+
|
282 |
+
return $image;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Gets the Schema.org type for the post, based on the post type.
|
287 |
+
*
|
288 |
+
* @param WP_Post $post
|
289 |
+
*
|
290 |
+
* @return string
|
291 |
+
*/
|
292 |
+
private function get_post_schema_type( $post ) {
|
293 |
+
if ( 'post' === $post->post_type ) {
|
294 |
+
$type = 'Article';
|
295 |
+
}
|
296 |
+
else {
|
297 |
+
$type = 'WebPage';
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Filter: 'yoastseo_amp_schema_type' - Allow changing the Schema.org type for the post
|
302 |
+
*
|
303 |
+
* @api string $type The Schema.org type for the $post
|
304 |
+
* @param WP_Post $post
|
305 |
+
*/
|
306 |
+
$type = apply_filters( 'yoastseo_amp_schema_type', $type, $post );
|
307 |
+
|
308 |
+
return $type;
|
309 |
+
}
|
310 |
+
}
|
311 |
+
}
|
classes/class-options.php
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package YoastSEO_AMP_Glue\Options
|
4 |
+
* @author Jip Moors
|
5 |
+
* @copyright 2016 Yoast BV
|
6 |
+
* @license GPL-2.0+
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'YoastSEO_AMP_Options' ) ) {
|
10 |
+
|
11 |
+
class YoastSEO_AMP_Options {
|
12 |
+
|
13 |
+
/** @var string Name of the option in the database */
|
14 |
+
private $option_name = 'wpseo_amp';
|
15 |
+
|
16 |
+
/** @var array Current options */
|
17 |
+
private $options;
|
18 |
+
|
19 |
+
/** @var array Option defaults */
|
20 |
+
private $defaults = array(
|
21 |
+
'version' => 1,
|
22 |
+
'amp_site_icon' => '',
|
23 |
+
'default_image' => '',
|
24 |
+
'header-color' => '',
|
25 |
+
'headings-color' => '',
|
26 |
+
'text-color' => '',
|
27 |
+
'meta-color' => '',
|
28 |
+
'link-color' => '',
|
29 |
+
'link-color-hover' => '',
|
30 |
+
'underline' => 'underline',
|
31 |
+
'blockquote-text-color' => '',
|
32 |
+
'blockquote-bg-color' => '',
|
33 |
+
'blockquote-border-color' => '',
|
34 |
+
'extra-css' => '',
|
35 |
+
'extra-head' => '',
|
36 |
+
'analytics-extra' => '',
|
37 |
+
);
|
38 |
+
|
39 |
+
/** @var self Class instance */
|
40 |
+
private static $instance;
|
41 |
+
|
42 |
+
private function __construct() {
|
43 |
+
// Register settings
|
44 |
+
add_action( 'admin_init', array( $this, 'register_settings' ) );
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Register the premium settings
|
49 |
+
*/
|
50 |
+
public function register_settings() {
|
51 |
+
register_setting( 'wpseo_amp_settings', $this->option_name, array( $this, 'sanitize_options' ) );
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Sanitize options
|
56 |
+
*
|
57 |
+
* @param $options
|
58 |
+
*
|
59 |
+
* @return mixed
|
60 |
+
*/
|
61 |
+
public function sanitize_options( $options ) {
|
62 |
+
$options['version'] = 1;
|
63 |
+
|
64 |
+
return $options;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get the options
|
69 |
+
*
|
70 |
+
* @return array
|
71 |
+
*/
|
72 |
+
public static function get() {
|
73 |
+
|
74 |
+
$me = self::get_instance();
|
75 |
+
|
76 |
+
if ( ! isset( $me->options ) ) {
|
77 |
+
$me->fetch_options();
|
78 |
+
}
|
79 |
+
|
80 |
+
return $me->options;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @return YoastSEO_AMP_Options
|
85 |
+
*/
|
86 |
+
public static function get_instance() {
|
87 |
+
if ( ! isset( self::$instance ) ) {
|
88 |
+
self::$instance = new self();
|
89 |
+
}
|
90 |
+
|
91 |
+
return self::$instance;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Collect options
|
96 |
+
*/
|
97 |
+
private function fetch_options() {
|
98 |
+
|
99 |
+
$saved_options = get_option( 'wpseo_amp' );
|
100 |
+
|
101 |
+
// Apply defaults.
|
102 |
+
$this->options = wp_parse_args( $saved_options, $this->defaults );
|
103 |
+
|
104 |
+
// Make sure all post types are present.
|
105 |
+
$this->update_post_type_settings();
|
106 |
+
|
107 |
+
// Save changes to database.
|
108 |
+
if ( $this->options !== $saved_options ) {
|
109 |
+
update_option( $this->option_name, $this->options );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get post types
|
115 |
+
*/
|
116 |
+
private function update_post_type_settings() {
|
117 |
+
$post_type_names = array();
|
118 |
+
$post_types = get_post_types( array( 'public' => true ), 'objects' );
|
119 |
+
|
120 |
+
if ( is_array( $post_types ) && $post_types !== array() ) {
|
121 |
+
foreach ( $post_types as $post_type ) {
|
122 |
+
if ( ! isset( $this->options[ 'post_types-' . $post_type->name . '-amp' ] ) ) {
|
123 |
+
if ( 'post' === $post_type->name ) {
|
124 |
+
$this->options[ 'post_types-' . $post_type->name . '-amp' ] = 'on';
|
125 |
+
} else {
|
126 |
+
$this->options[ 'post_types-' . $post_type->name . '-amp' ] = 'off';
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
$post_type_names[] = $post_type->name;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
|
134 |
+
// Remove missing post types.
|
135 |
+
foreach ( $this->options as $key => $value ) {
|
136 |
+
if ( 0 === strpos( $key, 'post_types' ) ) {
|
137 |
+
$post_type = substr( substr( $key, 11 ), 0, -4 );
|
138 |
+
if ( ! in_array( $post_type, $post_type_names ) ) {
|
139 |
+
unset ( $this->options[ $key ] );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
}
|
classes/class-sanitizer.php
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! defined( 'AMP__DIR__' ) ) {
|
4 |
+
header( 'Status: 403 Forbidden' );
|
5 |
+
header( 'HTTP/1.1 403 Forbidden' );
|
6 |
+
exit();
|
7 |
+
}
|
8 |
+
|
9 |
+
require_once( AMP__DIR__ . '/includes/sanitizers/class-amp-base-sanitizer.php' );
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Strips blacklisted tags and attributes from content, on top of the ones the AMP plugin already removes.
|
13 |
+
*
|
14 |
+
* See following for blacklist:
|
15 |
+
* https://github.com/ampproject/amphtml/blob/master/spec/amp-html-format.md#html-tags
|
16 |
+
*/
|
17 |
+
class Yoast_AMP_Blacklist_Sanitizer extends AMP_Base_Sanitizer {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* The actual sanitization function
|
21 |
+
*/
|
22 |
+
public function sanitize() {
|
23 |
+
$blacklisted_tags = $this->get_blacklisted_tags();
|
24 |
+
$body = $this->get_body_node();
|
25 |
+
$this->strip_tags( $body, $blacklisted_tags );
|
26 |
+
$this->strip_attributes_recursive( $body );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Passes through the DOM and removes stuff that shouldn't be there.
|
31 |
+
*
|
32 |
+
* @param DOMNode $node
|
33 |
+
*/
|
34 |
+
private function strip_attributes_recursive( $node ) {
|
35 |
+
if ( $node->nodeType !== XML_ELEMENT_NODE ) {
|
36 |
+
return;
|
37 |
+
}
|
38 |
+
|
39 |
+
if ( $node->hasAttributes() ) {
|
40 |
+
$node_name = $node->nodeName;
|
41 |
+
$length = $node->attributes->length;
|
42 |
+
for ( $i = $length - 1; $i >= 0; $i -- ) {
|
43 |
+
$attribute = $node->attributes->item( $i );
|
44 |
+
|
45 |
+
switch ( $node_name ) {
|
46 |
+
case 'a':
|
47 |
+
$this->sanitize_a_attribute( $node, $attribute );
|
48 |
+
break;
|
49 |
+
case 'img':
|
50 |
+
$this->sanitize_img_attribute( $node, $attribute );
|
51 |
+
break;
|
52 |
+
case 'pre':
|
53 |
+
$this->sanitize_pre_attribute( $node, $attribute );
|
54 |
+
break;
|
55 |
+
case 'table':
|
56 |
+
$this->sanitize_table_attribute( $node, $attribute );
|
57 |
+
break;
|
58 |
+
case 'td':
|
59 |
+
case 'th':
|
60 |
+
$this->sanitize_cell_attribute( $node, $attribute );
|
61 |
+
break;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
foreach ( $node->childNodes as $child_node ) {
|
67 |
+
$this->strip_attributes_recursive( $child_node );
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Passes through the DOM and strips forbidden tags
|
73 |
+
*
|
74 |
+
* @param DOMNode $node
|
75 |
+
* @param array $tag_names
|
76 |
+
*/
|
77 |
+
private function strip_tags( $node, $tag_names ) {
|
78 |
+
foreach ( $tag_names as $tag_name ) {
|
79 |
+
$elements = $node->getElementsByTagName( $tag_name );
|
80 |
+
$length = $elements->length;
|
81 |
+
if ( 0 === $length ) {
|
82 |
+
continue;
|
83 |
+
}
|
84 |
+
|
85 |
+
for ( $i = $length - 1; $i >= 0; $i -- ) {
|
86 |
+
$element = $elements->item( $i );
|
87 |
+
$parent_node = $element->parentNode;
|
88 |
+
$parent_node->removeChild( $element );
|
89 |
+
|
90 |
+
if ( 'body' !== $parent_node->nodeName && AMP_DOM_Utils::is_node_empty( $parent_node ) ) {
|
91 |
+
$parent_node->parentNode->removeChild( $parent_node );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Sanitizes anchor attributes
|
99 |
+
*
|
100 |
+
* @param DOMNode $node
|
101 |
+
* @param object $attribute
|
102 |
+
*/
|
103 |
+
private function sanitize_a_attribute( $node, $attribute ) {
|
104 |
+
$attribute_name = strtolower( $attribute->name );
|
105 |
+
|
106 |
+
if ( 'rel' === $attribute_name ) {
|
107 |
+
if ( 'nofollow' !== $attribute->value ) {
|
108 |
+
$node->removeAttribute( $attribute_name );
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Sanitizes pre tag attributes
|
115 |
+
*
|
116 |
+
* @param DOMNode $node
|
117 |
+
* @param object $attribute
|
118 |
+
*/
|
119 |
+
private function sanitize_pre_attribute( $node, $attribute ) {
|
120 |
+
$attribute_name = strtolower( $attribute->name );
|
121 |
+
|
122 |
+
if ( 'line' === $attribute_name ) {
|
123 |
+
$node->removeAttribute( $attribute_name );
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Sanitizes td / th tag attributes
|
129 |
+
*
|
130 |
+
* @param DOMNode $node
|
131 |
+
* @param object $attribute
|
132 |
+
*/
|
133 |
+
private function sanitize_cell_attribute( $node, $attribute ) {
|
134 |
+
$attribute_name = strtolower( $attribute->name );
|
135 |
+
|
136 |
+
if ( in_array( $attribute_name, array( 'width', 'height' ) ) ) {
|
137 |
+
$node->removeAttribute( $attribute_name );
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Sanitize table tag
|
143 |
+
* attributes
|
144 |
+
*
|
145 |
+
* @param DOMNode $node
|
146 |
+
* @param object $attribute
|
147 |
+
*/
|
148 |
+
private function sanitize_table_attribute( $node, $attribute ) {
|
149 |
+
$attribute_name = strtolower( $attribute->name );
|
150 |
+
|
151 |
+
if ( in_array( $attribute_name, array( 'border', 'cellspacing', 'cellpadding', 'summary' ) ) ) {
|
152 |
+
$node->removeAttribute( $attribute_name );
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Sanitize img tag attributes
|
158 |
+
*
|
159 |
+
* @param DOMNode $node
|
160 |
+
* @param object $attribute
|
161 |
+
*/
|
162 |
+
private function sanitize_img_attribute( $node, $attribute ) {
|
163 |
+
$attribute_name = strtolower( $attribute->name );
|
164 |
+
|
165 |
+
if ( 'rel' === $attribute_name ) {
|
166 |
+
$node->removeAttribute( $attribute_name );
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Makes sure the following tags are removed
|
172 |
+
*/
|
173 |
+
private function get_blacklisted_tags() {
|
174 |
+
return array(
|
175 |
+
'embed',
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
}
|
classes/views/additional-css.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
td, th {
|
2 |
+
text-align: left;
|
3 |
+
}
|
4 |
+
|
5 |
+
a, a:active, a:visited {
|
6 |
+
text-decoration: <?php echo ( ( $this->options['underline'] ) ? 'none' : 'underline' ); ?>;
|
7 |
+
}
|
classes/views/admin-page.php
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
4 |
+
header( 'Status: 403 Forbidden' );
|
5 |
+
header( 'HTTP/1.1 403 Forbidden' );
|
6 |
+
exit();
|
7 |
+
}
|
8 |
+
|
9 |
+
$yform = Yoast_Form::get_instance();
|
10 |
+
$yform->admin_header( true, 'wpseo_amp', false, 'wpseo_amp_settings' );
|
11 |
+
|
12 |
+
// data-default-color="#0a89c0"
|
13 |
+
?>
|
14 |
+
|
15 |
+
<h2 class="nav-tab-wrapper" id="wpseo-tabs">
|
16 |
+
<a class="nav-tab" id="posttypes-tab" href="#top#posttypes"><?php echo esc_html( __( 'Post types', 'wordpress-seo' ) ); ?></a>
|
17 |
+
<a class="nav-tab" id="design-tab" href="#top#design"><?php echo esc_html( __( 'Design', 'wordpress-seo' ) ); ?></a>
|
18 |
+
<a class="nav-tab" id="analytics-tab" href="#top#analytics"><?php echo esc_html( __( 'Analytics', 'wordpress-seo' ) ); ?></a>
|
19 |
+
</h2>
|
20 |
+
|
21 |
+
<div class="tabwrapper">
|
22 |
+
|
23 |
+
<div id="posttypes" class="wpseotab">
|
24 |
+
<h2><?php echo esc_html( __( 'Post types that have AMP support', 'wordpress-seo' ) ); ?></h2>
|
25 |
+
<p><?php echo esc_html( __( 'Generally you\'d want this to be your news post types.', 'wordpress-seo' ) ); ?><br/>
|
26 |
+
<?php echo esc_html( __( 'Post is enabled by default, feel free to enable any of them.', 'wordpress-seo' ) ); ?></p>
|
27 |
+
<?php
|
28 |
+
|
29 |
+
$post_types = apply_filters( 'wpseo_sitemaps_supported_post_types', get_post_types( array( 'public' => true ), 'objects' ) );
|
30 |
+
if ( is_array( $post_types ) && $post_types !== array() ) {
|
31 |
+
foreach ( $post_types as $pt ) {
|
32 |
+
$yform->toggle_switch(
|
33 |
+
'post_types-' . $pt->name . '-amp',
|
34 |
+
array(
|
35 |
+
'on' => __( 'Enabled', 'wordpress-seo' ),
|
36 |
+
'off' => __( 'Disabled', 'wordpress-seo' )
|
37 |
+
),
|
38 |
+
$pt->labels->name . ' (<code>' . $pt->name . '</code>)'
|
39 |
+
);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
?>
|
44 |
+
</div>
|
45 |
+
|
46 |
+
<div id="design" class="wpseotab">
|
47 |
+
<h3><?php echo esc_html( __( 'Images', 'wordpress-seo' ) ); ?></h3>
|
48 |
+
|
49 |
+
<?php
|
50 |
+
$yform->media_input( 'amp_site_icon', __( 'AMP icon', 'wordpress-seo' ) ); ?>
|
51 |
+
<p class="desc"><?php echo esc_html( __( 'Must be at least 32px × 32px', 'wordpress-seo' ) ); ?></p>
|
52 |
+
<br/>
|
53 |
+
|
54 |
+
<?php
|
55 |
+
$yform->media_input( 'default_image', __( 'Default image', 'wordpress-seo' ) ); ?>
|
56 |
+
<p class="desc"><?php echo esc_html( __( 'Used when a post doesn\'t have an image associated with it.', 'wordpress-seo' ) ); ?>
|
57 |
+
<br><?php echo esc_html( __( 'The image must be at least 696px wide.', 'wordpress-seo' ) ) ?></p>
|
58 |
+
<br/>
|
59 |
+
|
60 |
+
<h3><?php echo esc_html( __( 'Content colors', 'wordpress-seo' ) ); ?></h3>
|
61 |
+
|
62 |
+
<?php
|
63 |
+
$this->color_picker( 'header-color', __( 'AMP Header color', 'wordpress-seo' ) );
|
64 |
+
$this->color_picker( 'headings-color', __( 'Title color', 'wordpress-seo' ) );
|
65 |
+
$this->color_picker( 'text-color', __( 'Text color', 'wordpress-seo' ) );
|
66 |
+
$this->color_picker( 'meta-color', __( 'Post meta info color', 'wordpress-seo' ) );
|
67 |
+
?>
|
68 |
+
<br/>
|
69 |
+
|
70 |
+
<h3><?php echo esc_html( __( 'Links', 'wordpress-seo' ) ); ?></h3>
|
71 |
+
<?php
|
72 |
+
$this->color_picker( 'link-color', __( 'Text color', 'wordpress-seo' ) );
|
73 |
+
$this->color_picker( 'link-color-hover', __( 'Hover color', 'wordpress-seo' ) );
|
74 |
+
?>
|
75 |
+
|
76 |
+
<?php $yform->light_switch( 'underline', __( 'Underline', 'wordpress-seo' ), array(
|
77 |
+
__( 'Underline', 'wordpress-seo' ),
|
78 |
+
__( 'No underline', 'wordpress-seo' )
|
79 |
+
) ); ?>
|
80 |
+
|
81 |
+
<br/>
|
82 |
+
|
83 |
+
<h3><?php echo esc_html( __( 'Blockquotes', 'wordpress-seo' ) ); ?></h3>
|
84 |
+
<?php
|
85 |
+
$this->color_picker( 'blockquote-text-color', __( 'Text color', 'wordpress-seo' ) );
|
86 |
+
$this->color_picker( 'blockquote-bg-color', __( 'Background color', 'wordpress-seo' ) );
|
87 |
+
$this->color_picker( 'blockquote-border-color', __( 'Border color', 'wordpress-seo' ) );
|
88 |
+
?>
|
89 |
+
<br/>
|
90 |
+
|
91 |
+
<h3><?php echo esc_html( __( 'Extra CSS', 'wordpress-seo' ) ); ?></h3>
|
92 |
+
<?php $yform->textarea( 'extra-css', __( 'Extra CSS', 'wordpress-seo' ), array(
|
93 |
+
'rows' => 5,
|
94 |
+
'cols' => 100
|
95 |
+
) ); ?>
|
96 |
+
|
97 |
+
<br/>
|
98 |
+
|
99 |
+
<h3><?php printf( esc_html( __( 'Extra code in %s', 'wordpress-seo' ) ), '<code><head></code>' ); ?></h3>
|
100 |
+
<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>
|
101 |
+
<?php $yform->textarea( 'extra-head', __( 'Extra code', 'wordpress-seo' ), array(
|
102 |
+
'rows' => 5,
|
103 |
+
'cols' => 100
|
104 |
+
) ); ?>
|
105 |
+
|
106 |
+
</div>
|
107 |
+
|
108 |
+
<div id="analytics" class="wpseotab">
|
109 |
+
<h2><?php echo esc_html( __( 'AMP Analytics', 'wordpress-seo' ) ); ?></h2>
|
110 |
+
|
111 |
+
<?php
|
112 |
+
if ( class_exists( 'Yoast_GA_Options' ) ) {
|
113 |
+
echo '<p>', esc_html( __( 'Because your Google Analytics plugin by Yoast is active, your AMP pages will also be tracked.', 'wordpress-seo' ) ), '<br>';
|
114 |
+
$UA = Yoast_GA_Options::instance()->get_tracking_code();
|
115 |
+
if ( $UA === null ) {
|
116 |
+
echo esc_html( __( 'Make sure to connect your Google Analytics plugin properly.', 'wordpress-seo' ) );
|
117 |
+
} else {
|
118 |
+
echo sprintf( esc_html( __( 'Pageviews will be tracked using the following account: %s.', 'wordpress-seo' ) ), '<code>' . $UA . '</code>' );
|
119 |
+
}
|
120 |
+
|
121 |
+
echo '</p>';
|
122 |
+
|
123 |
+
echo '<p>', esc_html( __( 'Optionally you can override the default AMP tracking code with your own by putting it below:', 'wordpress-seo' ) ), '</p>';
|
124 |
+
$yform->textarea( 'analytics-extra', __( 'Analytics code', 'wordpress-seo' ), array(
|
125 |
+
'rows' => 5,
|
126 |
+
'cols' => 100
|
127 |
+
) );
|
128 |
+
} else {
|
129 |
+
echo '<p>', esc_html( __( 'Optionally add a valid google analytics tracking code.', 'wordpress-seo' ) ), '</p>';
|
130 |
+
$yform->textarea( 'analytics-extra', __( 'Analytics code', 'wordpress-seo' ), array(
|
131 |
+
'rows' => 5,
|
132 |
+
'cols' => 100
|
133 |
+
) );
|
134 |
+
}
|
135 |
+
?>
|
136 |
+
</div>
|
137 |
+
</div>
|
138 |
+
|
139 |
+
<?php
|
140 |
+
|
141 |
+
$yform->admin_footer();
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: joostdevalk
|
|
3 |
Tags: AMP, SEO
|
4 |
Requires at least: 4.2
|
5 |
Tested up to: 4.4
|
6 |
-
Stable tag: 0.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -13,30 +13,7 @@ This plugin makes sure the default WordPress AMP plugin uses the proper Yoast SE
|
|
13 |
|
14 |
This plugin makes sure the default [WordPress AMP plugin](https://wordpress.org/plugins/amp/) uses the proper [Yoast SEO](https://wordpress.org/plugins/wordpress-seo/) metadata. Without this glue plugin things like canonical might go wrong.
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
* Organization name (uses the blog name by default, now replaced by the Company name from the SEO General settings, Your info tab)
|
19 |
-
* Organization logo (uses the blog icon by default, now replaced by the Company logo from the SEO General settings, Your info tab)
|
20 |
-
* Post canonical (replaced by the Yoast SEO canonical, usually the same but makes sure its consistent when changed through Yoast SEO)
|
21 |
-
* Post image (uses the featured image by default, replaced by the Facebook image if one is set)
|
22 |
-
* Post description (added from the meta description, if set, by default the WordPress AMP plugin doesn't add one)
|
23 |
-
|
24 |
-
> *Bugs? Ideas?*<br>
|
25 |
-
> File them [on the GitHub repo for this plugin](https://github.com/Yoast/yoastseo-amp) please!
|
26 |
-
|
27 |
-
== Frequently Asked Questions ==
|
28 |
-
|
29 |
-
= How do I test whether it all works? =
|
30 |
-
|
31 |
-
Use Google's [Structured Data testing tool](https://developers.google.com/structured-data/testing-tool/) and enter the AMP URL of one of your posts.
|
32 |
-
|
33 |
-
= How do I change the Organization name or logo? =
|
34 |
-
|
35 |
-
Go to SEO -> General -> Your Info tab.
|
36 |
-
|
37 |
-
== Screenshots ==
|
38 |
-
|
39 |
-
1. Screenshot of the structured data testing tool testing an AMP page with the Yoast SEO plugin and this glue plugin.
|
40 |
|
41 |
== Installation ==
|
42 |
|
@@ -46,5 +23,16 @@ Go to SEO -> General -> Your Info tab.
|
|
46 |
|
47 |
== Changelog ==
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
= 0.1 =
|
50 |
* Initial version.
|
3 |
Tags: AMP, SEO
|
4 |
Requires at least: 4.2
|
5 |
Tested up to: 4.4
|
6 |
+
Stable tag: 0.3
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
13 |
|
14 |
This plugin makes sure the default [WordPress AMP plugin](https://wordpress.org/plugins/amp/) uses the proper [Yoast SEO](https://wordpress.org/plugins/wordpress-seo/) metadata. Without this glue plugin things like canonical might go wrong.
|
15 |
|
16 |
+
To change your company name or logo, you now have to go to the SEO settings, General tab.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
== Installation ==
|
19 |
|
23 |
|
24 |
== Changelog ==
|
25 |
|
26 |
+
= 0.3 =
|
27 |
+
* Split the plugin into several classes.
|
28 |
+
* Added a settings page, found under SEO -> AMP
|
29 |
+
* This new settings page has:
|
30 |
+
* A post types settings tab;
|
31 |
+
* A design settings tab;
|
32 |
+
* An analytics integration tab.
|
33 |
+
* Added sanitization functions that further clean up AMP output to make sure more pages pass validation.
|
34 |
+
* Added a default image (settable on the design tab) to use when a post has no image. This because the image in the JSON+LD output is required by Google.
|
35 |
+
* The plugin now automatically enables AMP GA tracking when GA by Yoast is enabled, but also allows you to add custom tracking.
|
36 |
+
|
37 |
= 0.1 =
|
38 |
* Initial version.
|
yoastseo-amp.php
CHANGED
@@ -9,139 +9,45 @@
|
|
9 |
* Plugin Name: Glue for Yoast SEO & AMP
|
10 |
* Plugin URI: https://yoast.com/yoast-seo-amp-glue/
|
11 |
* Description: Makes sure the default WordPress AMP plugin uses the proper Yoast SEO metadata
|
12 |
-
* Version: 0.
|
13 |
* Author: Joost de Valk
|
14 |
* Author URI: https://yoast.com
|
15 |
*/
|
16 |
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
22 |
/**
|
23 |
-
*
|
24 |
*/
|
25 |
-
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var WPSEO_Frontend
|
29 |
-
*/
|
30 |
-
private $front;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* @var array
|
34 |
-
*/
|
35 |
-
private $options;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* YoastSEO_AMP constructor.
|
39 |
-
*/
|
40 |
-
public function __construct() {
|
41 |
-
$this->front = WPSEO_Frontend::get_instance();
|
42 |
-
$this->options = WPSEO_Options::get_all();
|
43 |
-
|
44 |
-
add_filter( 'amp_post_template_data', array( $this, 'fix_amp_post_data' ), 10, 2 );
|
45 |
-
add_filter( 'amp_post_template_metadata', array( $this, 'fix_amp_post_metadata' ), 10, 2 );
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Fix the basic AMP post data
|
50 |
-
*
|
51 |
-
* @param array $data
|
52 |
-
* @param object $post
|
53 |
-
*
|
54 |
-
* @return array
|
55 |
-
*/
|
56 |
-
public function fix_amp_post_data( $data, $post ) {
|
57 |
-
$data['canonical_url'] = $this->front->canonical( false );
|
58 |
-
|
59 |
-
return $data;
|
60 |
-
}
|
61 |
|
62 |
-
|
63 |
-
* Fix the AMP metadata for a post
|
64 |
-
*
|
65 |
-
* @param array $metadata
|
66 |
-
* @param object $post
|
67 |
-
*
|
68 |
-
* @return array
|
69 |
-
*/
|
70 |
-
public function fix_amp_post_metadata( $metadata, $post ) {
|
71 |
-
$this->build_organization_object( $metadata );
|
72 |
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
}
|
77 |
-
|
78 |
-
$og_img = $this->get_image_object( WPSEO_Meta::get_value( 'opengraph-image', $post->ID ) );
|
79 |
-
if ( is_array( $og_img ) ) {
|
80 |
-
$metadata['image'] = $og_img;
|
81 |
-
}
|
82 |
-
|
83 |
-
return $metadata;
|
84 |
}
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
* @param array $metadata
|
90 |
-
*/
|
91 |
-
private function build_organization_object( &$metadata ) {
|
92 |
-
// While it's using the blog name, it's actually outputting the company name
|
93 |
-
if ( ! empty( $this->options['company_name'] ) ) {
|
94 |
-
$metadata['publisher']['name'] = $this->options['company_name'];
|
95 |
-
}
|
96 |
-
|
97 |
-
// The logo needs to be 600px wide max, 60px high max
|
98 |
-
$logo = $this->get_image_object( $this->options['company_logo'], array( 600, 60 ) );
|
99 |
-
if ( is_array( $logo ) ) {
|
100 |
-
$metadata['publisher']['logo'] = $logo;
|
101 |
-
}
|
102 |
-
}
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Builds an image object array from an image URL
|
106 |
-
*
|
107 |
-
* @param string $image_url
|
108 |
-
* @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width
|
109 |
-
* and height values in pixels (in that order). Default 'full'.
|
110 |
-
*
|
111 |
-
* @return bool|array
|
112 |
-
*/
|
113 |
-
private function get_image_object( $image_url, $size = 'full' ) {
|
114 |
-
if ( empty( $image_url ) ) {
|
115 |
-
return false;
|
116 |
-
}
|
117 |
-
|
118 |
-
$image_id = attachment_url_to_postid( $image_url );
|
119 |
-
$image_src = wp_get_attachment_image_src( $image_id, $size );
|
120 |
-
|
121 |
-
if ( is_array( $image_src ) ) {
|
122 |
-
return array(
|
123 |
-
'@type' => 'ImageObject',
|
124 |
-
'url' => $image_src[0],
|
125 |
-
'width' => $image_src[1],
|
126 |
-
'height' => $image_src[2]
|
127 |
-
);
|
128 |
-
}
|
129 |
-
|
130 |
-
return false;
|
131 |
}
|
132 |
}
|
|
|
133 |
}
|
134 |
}
|
135 |
|
136 |
-
add_action( 'plugins_loaded', 'yoast_seo_amp_glue_define', 99 );
|
137 |
-
|
138 |
/**
|
139 |
* Initialize the Yoast SEO AMP Glue plugin
|
140 |
*/
|
141 |
function yoast_seo_amp_glue_init() {
|
142 |
-
if (
|
143 |
new YoastSEO_AMP();
|
144 |
}
|
145 |
}
|
146 |
|
147 |
-
add_action( 'init', 'yoast_seo_amp_glue_init',
|
9 |
* Plugin Name: Glue for Yoast SEO & AMP
|
10 |
* Plugin URI: https://yoast.com/yoast-seo-amp-glue/
|
11 |
* Description: Makes sure the default WordPress AMP plugin uses the proper Yoast SEO metadata
|
12 |
+
* Version: 0.3
|
13 |
* Author: Joost de Valk
|
14 |
* Author URI: https://yoast.com
|
15 |
*/
|
16 |
|
17 |
+
if ( ! class_exists( 'YoastSEO_AMP', false ) ) {
|
18 |
+
/**
|
19 |
+
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
|
20 |
+
*/
|
21 |
+
class YoastSEO_AMP {
|
22 |
+
|
23 |
/**
|
24 |
+
* YoastSEO_AMP constructor.
|
25 |
*/
|
26 |
+
public function __construct() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
require 'classes/class-options.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
+
if ( is_admin() ) {
|
31 |
+
require 'classes/class-backend.php';
|
32 |
+
new YoastSEO_AMP_Backend();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
}
|
34 |
+
else {
|
35 |
+
require 'classes/class-build-css.php';
|
36 |
+
require 'classes/class-frontend.php';
|
37 |
+
new YoastSEO_AMP_Frontend();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
}
|
39 |
}
|
40 |
+
|
41 |
}
|
42 |
}
|
43 |
|
|
|
|
|
44 |
/**
|
45 |
* Initialize the Yoast SEO AMP Glue plugin
|
46 |
*/
|
47 |
function yoast_seo_amp_glue_init() {
|
48 |
+
if ( defined( 'WPSEO_FILE' ) && defined( 'AMP__FILE__' ) ) {
|
49 |
new YoastSEO_AMP();
|
50 |
}
|
51 |
}
|
52 |
|
53 |
+
add_action( 'init', 'yoast_seo_amp_glue_init', 9 );
|