PDF rausgenommen
This commit is contained in:
339
msd2/wordpress/wp-content/plugins/glue-for-yoast-seo-amp/LICENSE
Normal file
339
msd2/wordpress/wp-content/plugins/glue-for-yoast-seo-amp/LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
@ -0,0 +1,8 @@
|
||||
.yst_colorpicker {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
label.checkbox {
|
||||
display: block;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
jQuery(document).ready(function($){
|
||||
$('.yst_colorpicker').wpColorPicker();
|
||||
});
|
@ -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();
|
||||
} );
|
||||
} );
|
||||
}
|
||||
);
|
@ -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/>';
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
td, th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
a, a:active, a:visited {
|
||||
text-decoration: <?php echo ( ( 'underline' === $this->options['underline'] ) ? 'underline' : 'none' ); ?>;
|
||||
}
|
@ -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 × 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><head></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();
|
@ -0,0 +1,91 @@
|
||||
=== Glue for Yoast SEO & AMP ===
|
||||
Contributors: joostdevalk
|
||||
Tags: AMP, SEO
|
||||
Requires at least: 4.8
|
||||
Tested up to: 4.9.5
|
||||
Stable tag: 0.4.3
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
This plugin makes sure the default WordPress AMP plugin uses the proper Yoast SEO metadata and allows modification of the AMP page design.
|
||||
|
||||
== Description ==
|
||||
|
||||
Google is currently working on the "Accelerated Mobile Pages" or AMP project. The [WordPress AMP plugin](https://wordpress.org/plugins/amp/) provides the technical implementation of the AMP specifications. This makes sure that your pages contain valid AMP code.
|
||||
|
||||
The Yoast SEO: AMP Glue plugin integrates [Yoast SEO](https://wordpress.org/plugins/wordpress-seo/) into your AMP pages. This makes sure your meta-data is implemented correctly.
|
||||
|
||||
Next to the technical SEO improvements, the Yoast SEO: AMP Glue plugin also provides a simple way to customize your AMP pages.
|
||||
It adds rudimental styling in the form of colors and link styles, so your AMP pages can maintain the feeling your main pages have.
|
||||
To change your AMP page design, go to SEO -> AMP, and look at the design tab.
|
||||
|
||||
== Installation ==
|
||||
|
||||
1. Upload the plugin files to the `/wp-content/plugins/yoast-seo-amp` directory, or install the plugin through the WordPress plugins screen directly.
|
||||
1. Activate the plugin through the 'Plugins' screen in WordPress
|
||||
1. Go to SEO -> AMP to change your design and enable custom post types.
|
||||
1. You're done.
|
||||
|
||||
== Screenshots ==
|
||||
|
||||
1. Example AMP page, design changed with this plugin.
|
||||
2. Post type support in the plugin.
|
||||
3. Design settings in the plugin.
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 0.4.3 =
|
||||
* Bugfixes:
|
||||
* Fixes a fatal error in combination with `AMP for WordPress` version 0.7.0. Props [Ryan Kienstra](https://github.com/kienstra).
|
||||
|
||||
= 0.4.2 =
|
||||
* Bugfixes:
|
||||
* Reverts the canonical removal.
|
||||
|
||||
= 0.4.1 =
|
||||
* Bugfixes:
|
||||
* Fix styling of design tab.
|
||||
|
||||
= 0.4.0 =
|
||||
* Bugfixes:
|
||||
* Removed page from post-type list to avoid unwanted canonical link.
|
||||
|
||||
* Enhancements:
|
||||
* Removed canonical feature because it is being handled by the AMP plugin.
|
||||
* Removed sanitizations which are already being done by the AMP plugin.
|
||||
* Added a check for Monster Insights analytics implementation and disables our implementation if present.
|
||||
* Added class selector implementation for AMP 0.4.x compatibility.
|
||||
|
||||
= 0.3.3 =
|
||||
* Bugfixes:
|
||||
* Fixes bug where AMP was only activated for the first post type in the list.
|
||||
* Made sure that the function is not declared multiple times.
|
||||
|
||||
= 0.3.2 =
|
||||
* Bugfixes:
|
||||
* Fixed underline setting that wasn't working.
|
||||
* Added screenshots to plugin page.
|
||||
|
||||
= 0.3.1 =
|
||||
* Bugfixes:
|
||||
* Fixed bug where featured image wouldn't be used properly anymore.
|
||||
* Fixed bug where CSS in Extra CSS field could be wrongly escaped.
|
||||
* Fixed bug where wrong hook was used to `add_post_type_support`, causing integration issues.
|
||||
* Fixed bug where post type settings wouldn't save properly.
|
||||
* Enhancement:
|
||||
* Added some more escaping to color picker functionality.
|
||||
* Made sure no notice is thrown on frontend when post type setting isn't available.
|
||||
|
||||
= 0.3 =
|
||||
* 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.
|
||||
|
||||
= 0.1 =
|
||||
* Initial version.
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* @package YoastSEO_AMP_Glue
|
||||
* @author Joost de Valk
|
||||
* @copyright 2016 Yoast BV
|
||||
* @license GPL-2.0+
|
||||
*
|
||||
* @wordpress-plugin
|
||||
* Plugin Name: Glue for Yoast SEO & AMP
|
||||
* Plugin URI: https://wordpress.org/plugins/glue-for-yoast-seo-amp/
|
||||
* Description: Makes sure the default WordPress AMP plugin uses the proper Yoast SEO metadata
|
||||
* Version: 0.4.3
|
||||
* Author: Joost de Valk
|
||||
* Author URI: https://yoast.com
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'YoastSEO_AMP', false ) ) {
|
||||
/**
|
||||
* This class improves upon the AMP output by the default WordPress AMP plugin using Yoast SEO metadata.
|
||||
*/
|
||||
class YoastSEO_AMP {
|
||||
|
||||
/**
|
||||
* YoastSEO_AMP constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
require 'classes/class-options.php';
|
||||
|
||||
if ( is_admin() ) {
|
||||
require 'classes/class-backend.php';
|
||||
new YoastSEO_AMP_Backend();
|
||||
return;
|
||||
}
|
||||
|
||||
require 'classes/class-build-css.php';
|
||||
require 'classes/class-frontend.php';
|
||||
new YoastSEO_AMP_Frontend();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists('yoast_seo_amp_glue_init' ) ) {
|
||||
/**
|
||||
* Initialize the Yoast SEO AMP Glue plugin
|
||||
*/
|
||||
function yoast_seo_amp_glue_init() {
|
||||
if ( defined( 'WPSEO_FILE' ) && defined( 'AMP__FILE__' ) ) {
|
||||
new YoastSEO_AMP();
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'init', 'yoast_seo_amp_glue_init', 9 );
|
||||
}
|
Reference in New Issue
Block a user