AMP for WordPress - Version 2.0.11

Version Description

Download this release

Release Info

Developer westonruter
Plugin Icon 128x128 AMP for WordPress
Version 2.0.11
Comparing to
See all releases

Code changes from version 2.0.10 to 2.0.11

amp.php CHANGED
@@ -5,7 +5,7 @@
5
  * Plugin URI: https://amp-wp.org
6
  * Author: AMP Project Contributors
7
  * Author URI: https://github.com/ampproject/amp-wp/graphs/contributors
8
- * Version: 2.0.10
9
  * License: GPLv2 or later
10
  * Requires at least: 4.9
11
  * Requires PHP: 5.6
@@ -15,7 +15,7 @@
15
 
16
  define( 'AMP__FILE__', __FILE__ );
17
  define( 'AMP__DIR__', dirname( __FILE__ ) );
18
- define( 'AMP__VERSION', '2.0.10' );
19
 
20
  /**
21
  * Errors encountered while loading the plugin.
5
  * Plugin URI: https://amp-wp.org
6
  * Author: AMP Project Contributors
7
  * Author URI: https://github.com/ampproject/amp-wp/graphs/contributors
8
+ * Version: 2.0.11
9
  * License: GPLv2 or later
10
  * Requires at least: 4.9
11
  * Requires PHP: 5.6
15
 
16
  define( 'AMP__FILE__', __FILE__ );
17
  define( 'AMP__DIR__', dirname( __FILE__ ) );
18
+ define( 'AMP__VERSION', '2.0.11' );
19
 
20
  /**
21
  * Errors encountered while loading the plugin.
includes/admin/class-amp-post-meta-box.php CHANGED
@@ -209,7 +209,7 @@ class AMP_Post_Meta_Box {
209
  */
210
  public function enqueue_block_assets() {
211
  $post = get_post();
212
- if ( ! in_array( $post->post_type, AMP_Post_Type_Support::get_eligible_post_types(), true ) ) {
213
  return;
214
  }
215
 
@@ -438,7 +438,10 @@ class AMP_Post_Meta_Box {
438
  if ( in_array( 'skip-post', $errors, true ) ) {
439
  $error_messages[] = __( 'A plugin or theme has disabled AMP support.', 'amp' );
440
  }
441
- if ( count( array_diff( $errors, [ 'post-type-support', 'skip-post', 'template_unsupported', 'no_matching_template' ] ) ) > 0 ) {
 
 
 
442
  $error_messages[] = __( 'Unavailable for an unknown reason.', 'amp' );
443
  }
444
 
209
  */
210
  public function enqueue_block_assets() {
211
  $post = get_post();
212
+ if ( ! $post instanceof WP_Post || ! in_array( $post->post_type, AMP_Post_Type_Support::get_eligible_post_types(), true ) ) {
213
  return;
214
  }
215
 
438
  if ( in_array( 'skip-post', $errors, true ) ) {
439
  $error_messages[] = __( 'A plugin or theme has disabled AMP support.', 'amp' );
440
  }
441
+ if ( in_array( 'invalid-post', $errors, true ) ) {
442
+ $error_messages[] = __( 'The post data could not be successfully retrieved.', 'amp' );
443
+ }
444
+ if ( count( array_diff( $errors, [ 'post-type-support', 'skip-post', 'template_unsupported', 'no_matching_template', 'invalid-post' ] ) ) > 0 ) {
445
  $error_messages[] = __( 'Unavailable for an unknown reason.', 'amp' );
446
  }
447
 
includes/amp-post-template-functions.php CHANGED
@@ -11,7 +11,11 @@
11
  * @internal
12
  */
13
  function amp_post_template_init_hooks() {
14
- add_action( 'amp_post_template_head', 'noindex' );
 
 
 
 
15
  add_action( 'amp_post_template_head', 'amp_post_template_add_title' );
16
  add_action( 'amp_post_template_head', 'amp_post_template_add_canonical' );
17
  add_action( 'amp_post_template_head', 'amp_post_template_add_fonts' );
11
  * @internal
12
  */
13
  function amp_post_template_init_hooks() {
14
+ if ( version_compare( strtok( get_bloginfo( 'version' ), '-' ), '5.7', '>=' ) ) {
15
+ add_action( 'amp_post_template_head', 'wp_robots' );
16
+ } else {
17
+ add_action( 'amp_post_template_head', 'noindex' );
18
+ }
19
  add_action( 'amp_post_template_head', 'amp_post_template_add_title' );
20
  add_action( 'amp_post_template_head', 'amp_post_template_add_canonical' );
21
  add_action( 'amp_post_template_head', 'amp_post_template_add_fonts' );
includes/class-amp-post-type-support.php CHANGED
@@ -119,9 +119,15 @@ class AMP_Post_Type_Support {
119
  * @return array Error codes for why a given post does not have AMP support.
120
  */
121
  public static function get_support_errors( $post ) {
122
- if ( ! ( $post instanceof WP_Post ) ) {
123
  $post = get_post( $post );
124
  }
 
 
 
 
 
 
125
  $errors = [];
126
 
127
  if ( ! in_array( $post->post_type, self::get_supported_post_types(), true ) ) {
119
  * @return array Error codes for why a given post does not have AMP support.
120
  */
121
  public static function get_support_errors( $post ) {
122
+ if ( ! $post instanceof WP_Post ) {
123
  $post = get_post( $post );
124
  }
125
+
126
+ // If there's still not a valid post, then we have to abort.
127
+ if ( ! $post instanceof WP_Post ) {
128
+ return [ 'invalid-post' ];
129
+ }
130
+
131
  $errors = [];
132
 
133
  if ( ! in_array( $post->post_type, self::get_supported_post_types(), true ) ) {
includes/embeds/class-amp-core-block-handler.php CHANGED
@@ -215,7 +215,9 @@ class AMP_Core_Block_Handler extends AMP_Base_Embed_Handler {
215
  /**
216
  * Ampify cover block.
217
  *
218
- * This specifically fixes the layout of the block when a background video is assigned.
 
 
219
  *
220
  * @see \AMP_Video_Sanitizer::filter_video_dimensions()
221
  *
@@ -224,14 +226,59 @@ class AMP_Core_Block_Handler extends AMP_Base_Embed_Handler {
224
  * @return string Filtered block content.
225
  */
226
  public function ampify_cover_block( $block_content, $block ) {
227
- if ( isset( $block['attrs']['backgroundType'] ) && 'video' === $block['attrs']['backgroundType'] ) {
228
- $block_content = preg_replace(
229
- '/(?<=<video\s)/',
230
- 'layout="fill" object-fit="cover" ',
231
- $block_content
232
- );
 
 
 
 
 
 
 
 
 
 
233
  }
234
- return $block_content;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
  /**
215
  /**
216
  * Ampify cover block.
217
  *
218
+ * This ensures that the background img/video in a cover block has object-fit=cover and the appropriate object-position
219
+ * attribute so that they will be carried over to to the amp-img/amp-video and propagated to the img/video in the
220
+ * light shadow DOM.
221
  *
222
  * @see \AMP_Video_Sanitizer::filter_video_dimensions()
223
  *
226
  * @return string Filtered block content.
227
  */
228
  public function ampify_cover_block( $block_content, $block ) {
229
+ $is_video_background = (
230
+ isset( $block['attrs']['backgroundType'] )
231
+ &&
232
+ 'video' === $block['attrs']['backgroundType']
233
+ );
234
+ $is_image_element = ! (
235
+ ! empty( $block['attrs']['hasParallax'] )
236
+ ||
237
+ ! empty( $block['attrs']['isRepeated'] )
238
+ );
239
+
240
+ // Object fit/position is not relevant when background image has fixed positioning or is repeated.
241
+ // In other words, it is not relevant when a <video> or a <img> is not going to be used.
242
+ // See <https://github.com/WordPress/gutenberg/blob/54c9066d4/packages/block-library/src/cover/save.js#L54-L72>.
243
+ if ( ! ( $is_video_background || $is_image_element ) ) {
244
+ return $block_content;
245
  }
246
+
247
+ $pattern = sprintf(
248
+ '#<%s(?= )[^>]*? class="(?:[^"]*? )?wp-block-cover__%s-background(?: [^"]*?)?"#',
249
+ $is_video_background ? 'video' : 'img',
250
+ $is_video_background ? 'video' : 'image'
251
+ );
252
+ return preg_replace_callback(
253
+ $pattern,
254
+ static function ( $matches ) use ( $block ) {
255
+ $replacement = $matches[0];
256
+
257
+ // The background image/video for the cover block by definition needs object-fit="cover" on the resulting amp-ing/amp-video.
258
+ $replacement .= ' object-fit="cover"';
259
+
260
+ // Add the fill layout to skip needlessly obtaining the dimensions.
261
+ $replacement .= ' layout="fill"';
262
+
263
+ // Add object-position from the block's attributes to add to the img/video to be copied onto the amp-img/amp-video.
264
+ // The AMP runtime copies object-position attribute onto the underlying img/video for a given amp-img/amp-video.
265
+ // This is needed since the object-position property directly on an amp-img/amp-video will have no effect since
266
+ // since it is merely a wrapper for the underlying img/video element which actually supports the CSS property.
267
+ if ( isset( $block['attrs']['focalPoint']['x'], $block['attrs']['focalPoint']['y'] ) ) {
268
+ // See logic in Gutenberg for writing focal point to object-position attr:
269
+ // <https://github.com/WordPress/gutenberg/blob/54c9066/packages/block-library/src/cover/save.js#L71>.
270
+ $replacement .= sprintf(
271
+ ' object-position="%d%% %d%%"',
272
+ round( (float) $block['attrs']['focalPoint']['x'] * 100 ),
273
+ round( (float) $block['attrs']['focalPoint']['y'] * 100 )
274
+ );
275
+ }
276
+
277
+ return $replacement;
278
+ },
279
+ $block_content,
280
+ 1
281
+ );
282
  }
283
 
284
  /**
includes/sanitizers/class-amp-base-sanitizer.php CHANGED
@@ -595,14 +595,34 @@ abstract class AMP_Base_Sanitizer {
595
  }
596
 
597
  // Capture element contents.
598
- if (
599
- ( 'script' === $node->nodeName && ! $node->hasAttribute( 'src' ) )
600
- ||
601
- // Include stylesheet text except for amp-custom and amp-keyframes since it is large and since it should
602
- // already be detailed in the stylesheets metabox.
603
- ( 'style' === $node->nodeName && ! $node->hasAttribute( 'amp-custom' ) && ! $node->hasAttribute( 'amp-keyframes' ) )
604
- ) {
605
- $error['text'] = $node->textContent;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
  }
607
 
608
  // Suppress 'ver' param from enqueued scripts and styles.
595
  }
596
 
597
  // Capture element contents.
598
+ $is_inline_script = ( 'script' === $node->nodeName && ! $node->hasAttribute( 'src' ) );
599
+ $is_inline_style = ( 'style' === $node->nodeName && ! $node->hasAttribute( 'amp-custom' ) && ! $node->hasAttribute( 'amp-keyframes' ) );
600
+ if ( $is_inline_script || $is_inline_style ) {
601
+ $text_content = $node->textContent;
602
+ if ( $is_inline_script ) {
603
+ // For inline scripts, normalize string and number literals to prevent nonces, random numbers, and timestamps
604
+ // from generating endless number of validation errors.
605
+ $error['text'] = preg_replace(
606
+ [
607
+ // Regex credit to <https://stackoverflow.com/a/5696141/93579>.
608
+ '/"[^"\\\\\n]*(?:\\\\.[^"\\\\\n]*)*"/s',
609
+ '/\'[^\'\\\\\n]*(?:\\\\.[^\'\\\\\n]*)*\'/s',
610
+ '/(\b|-)\d+\.\d+\b/',
611
+ '/(\b|-)\d+\b/',
612
+ ],
613
+ [
614
+ '__DOUBLE_QUOTED_STRING__',
615
+ '__SINGLE_QUOTED_STRING__',
616
+ '__FLOAT__',
617
+ '__INT__',
618
+ ],
619
+ $text_content
620
+ );
621
+ } elseif ( $is_inline_style ) {
622
+ // Include stylesheet text except for amp-custom and amp-keyframes since it is large and since it should
623
+ // already be detailed in the stylesheets metabox.
624
+ $error['text'] = $text_content;
625
+ }
626
  }
627
 
628
  // Suppress 'ver' param from enqueued scripts and styles.
includes/sanitizers/class-amp-comments-sanitizer.php CHANGED
@@ -66,31 +66,27 @@ class AMP_Comments_Sanitizer extends AMP_Base_Sanitizer {
66
  * @param DOMElement $comment_form Comment form.
67
  */
68
  protected function process_comment_form( $comment_form ) {
69
- /**
70
- * Element.
71
- *
72
- * @var DOMElement $element
73
- */
74
-
75
- /**
76
- * Named input elements.
77
- *
78
- * @var DOMElement[][] $form_fields
79
- */
80
  $form_fields = [];
81
  foreach ( $comment_form->getElementsByTagName( 'input' ) as $element ) {
 
82
  $name = $element->getAttribute( 'name' );
83
  if ( $name ) {
84
  $form_fields[ $name ][] = $element;
85
  }
86
  }
87
  foreach ( $comment_form->getElementsByTagName( 'textarea' ) as $element ) {
 
88
  $name = $element->getAttribute( 'name' );
89
  if ( $name ) {
90
  $form_fields[ $name ][] = $element;
91
  }
92
  }
93
 
 
 
 
 
 
94
  if ( empty( $form_fields['comment_post_ID'] ) ) {
95
  return;
96
  }
66
  * @param DOMElement $comment_form Comment form.
67
  */
68
  protected function process_comment_form( $comment_form ) {
 
 
 
 
 
 
 
 
 
 
 
69
  $form_fields = [];
70
  foreach ( $comment_form->getElementsByTagName( 'input' ) as $element ) {
71
+ /** @var DOMElement $element */
72
  $name = $element->getAttribute( 'name' );
73
  if ( $name ) {
74
  $form_fields[ $name ][] = $element;
75
  }
76
  }
77
  foreach ( $comment_form->getElementsByTagName( 'textarea' ) as $element ) {
78
+ /** @var DOMElement $element */
79
  $name = $element->getAttribute( 'name' );
80
  if ( $name ) {
81
  $form_fields[ $name ][] = $element;
82
  }
83
  }
84
 
85
+ /**
86
+ * Named input elements.
87
+ *
88
+ * @var DOMElement[][] $form_fields
89
+ */
90
  if ( empty( $form_fields['comment_post_ID'] ) ) {
91
  return;
92
  }
includes/sanitizers/class-amp-video-sanitizer.php CHANGED
@@ -294,6 +294,12 @@ class AMP_Video_Sanitizer extends AMP_Base_Sanitizer {
294
  $out['noloading'] = $value;
295
  break;
296
 
 
 
 
 
 
 
297
  default:
298
  $out[ $name ] = $value;
299
  }
294
  $out['noloading'] = $value;
295
  break;
296
 
297
+ // Skip copying playsinline attributes which are automatically added by amp-video:
298
+ // <https://github.com/ampproject/amphtml/blob/264e5c0/extensions/amp-video/0.1/amp-video.js#L234-L236>.
299
+ case 'playsinline':
300
+ case 'webkit-playsinline':
301
+ break;
302
+
303
  default:
304
  $out[ $name ] = $value;
305
  }
includes/utils/class-amp-dom-utils.php CHANGED
@@ -13,7 +13,7 @@ use AmpProject\Tag;
13
  *
14
  * Functionality to simplify working with Dom\Documents and DOMElements.
15
  *
16
- * @internal
17
  */
18
  class AMP_DOM_Utils {
19
 
13
  *
14
  * Functionality to simplify working with Dom\Documents and DOMElements.
15
  *
16
+ * @since 0.2
17
  */
18
  class AMP_DOM_Utils {
19
 
includes/validation/class-amp-validation-manager.php CHANGED
@@ -79,10 +79,9 @@ class AMP_Validation_Manager {
79
  /**
80
  * The errors encountered when validating.
81
  *
82
- * @var array[][] {
83
- * @type array $error Error code.
84
- * @type bool $sanitized Whether sanitized.
85
- * @type string $slug Hash of the error.
86
  * }
87
  */
88
  public static $validation_results = [];
79
  /**
80
  * The errors encountered when validating.
81
  *
82
+ * @var array[] {
83
+ * @type array $error Error data.
84
+ * @type bool $sanitized Whether sanitized.
 
85
  * }
86
  */
87
  public static $validation_results = [];
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: google, xwp, automattic, westonruter, albertomedina, schlessera, swissspidy, pierlo, johnwatkins0, joshuawold, ryankienstra
3
  Tags: amp, mobile, optimization, accelerated mobile pages, framework, components, blocks, performance, ux, seo, official
4
  Requires at least: 4.9
5
- Tested up to: 5.6
6
- Stable tag: 2.0.10
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 5.6
2
  Contributors: google, xwp, automattic, westonruter, albertomedina, schlessera, swissspidy, pierlo, johnwatkins0, joshuawold, ryankienstra
3
  Tags: amp, mobile, optimization, accelerated mobile pages, framework, components, blocks, performance, ux, seo, official
4
  Requires at least: 4.9
5
+ Tested up to: 5.7
6
+ Stable tag: 2.0.11
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Requires PHP: 5.6
src/Admin/OnboardingWizardSubmenuPage.php CHANGED
@@ -9,13 +9,11 @@
9
  namespace AmpProject\AmpWP\Admin;
10
 
11
  use AMP_Options_Manager;
12
- use AmpProject\AmpWP\AmpSlugCustomizationWatcher;
13
  use AmpProject\AmpWP\DevTools\UserAccess;
14
  use AmpProject\AmpWP\Infrastructure\Conditional;
15
  use AmpProject\AmpWP\Infrastructure\Delayed;
16
  use AmpProject\AmpWP\Infrastructure\Registerable;
17
  use AmpProject\AmpWP\Infrastructure\Service;
18
- use AmpProject\AmpWP\Option;
19
  use AmpProject\AmpWP\QueryVar;
20
  use AmpProject\AmpWP\Services;
21
 
@@ -217,7 +215,7 @@ final class OnboardingWizardSubmenuPage implements Conditional, Delayed, Registe
217
  $theme = wp_get_theme();
218
  $is_reader_theme = $this->reader_themes->theme_data_exists( get_stylesheet() );
219
 
220
- $exit_link = menu_page_url( AMP_Options_Manager::OPTION_NAME, false );
221
 
222
  $setup_wizard_data = [
223
  'AMP_OPTIONS_KEY' => AMP_Options_Manager::OPTION_NAME,
@@ -228,11 +226,11 @@ final class OnboardingWizardSubmenuPage implements Conditional, Delayed, Registe
228
  'APP_ROOT_ID' => self::APP_ROOT_ID,
229
  'CUSTOMIZER_LINK' => add_query_arg(
230
  [
231
- 'return' => rawurlencode( $exit_link ),
232
  ],
233
  admin_url( 'customize.php' )
234
  ),
235
- 'CLOSE_LINK' => wp_get_referer() ?: $exit_link,
236
  // @todo As of June 2020, an upcoming WP release will allow this to be retrieved via REST.
237
  'CURRENT_THEME' => [
238
  'name' => $theme->get( 'Name' ),
@@ -242,7 +240,7 @@ final class OnboardingWizardSubmenuPage implements Conditional, Delayed, Registe
242
  'url' => $theme->get( 'ThemeURI' ),
243
  ],
244
  'USING_FALLBACK_READER_THEME' => $this->reader_themes->using_fallback_theme(),
245
- 'FINISH_LINK' => $exit_link,
246
  'OPTIONS_REST_PATH' => '/amp/v1/options',
247
  'READER_THEMES_REST_PATH' => '/amp/v1/reader-themes',
248
  'UPDATES_NONCE' => wp_create_nonce( 'updates' ),
@@ -290,4 +288,20 @@ final class OnboardingWizardSubmenuPage implements Conditional, Delayed, Registe
290
  $this->rest_preloader->add_preloaded_path( $path );
291
  }
292
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  }
9
  namespace AmpProject\AmpWP\Admin;
10
 
11
  use AMP_Options_Manager;
 
12
  use AmpProject\AmpWP\DevTools\UserAccess;
13
  use AmpProject\AmpWP\Infrastructure\Conditional;
14
  use AmpProject\AmpWP\Infrastructure\Delayed;
15
  use AmpProject\AmpWP\Infrastructure\Registerable;
16
  use AmpProject\AmpWP\Infrastructure\Service;
 
17
  use AmpProject\AmpWP\QueryVar;
18
  use AmpProject\AmpWP\Services;
19
 
215
  $theme = wp_get_theme();
216
  $is_reader_theme = $this->reader_themes->theme_data_exists( get_stylesheet() );
217
 
218
+ $amp_settings_link = menu_page_url( AMP_Options_Manager::OPTION_NAME, false );
219
 
220
  $setup_wizard_data = [
221
  'AMP_OPTIONS_KEY' => AMP_Options_Manager::OPTION_NAME,
226
  'APP_ROOT_ID' => self::APP_ROOT_ID,
227
  'CUSTOMIZER_LINK' => add_query_arg(
228
  [
229
+ 'return' => rawurlencode( $amp_settings_link ),
230
  ],
231
  admin_url( 'customize.php' )
232
  ),
233
+ 'CLOSE_LINK' => $this->get_close_link(),
234
  // @todo As of June 2020, an upcoming WP release will allow this to be retrieved via REST.
235
  'CURRENT_THEME' => [
236
  'name' => $theme->get( 'Name' ),
240
  'url' => $theme->get( 'ThemeURI' ),
241
  ],
242
  'USING_FALLBACK_READER_THEME' => $this->reader_themes->using_fallback_theme(),
243
+ 'FINISH_LINK' => $amp_settings_link,
244
  'OPTIONS_REST_PATH' => '/amp/v1/options',
245
  'READER_THEMES_REST_PATH' => '/amp/v1/reader-themes',
246
  'UPDATES_NONCE' => wp_create_nonce( 'updates' ),
288
  $this->rest_preloader->add_preloaded_path( $path );
289
  }
290
  }
291
+
292
+ /**
293
+ * Determine URL that should be used to close the Onboarding Wizard.
294
+ *
295
+ * @return string Close link.
296
+ */
297
+ public function get_close_link() {
298
+ $referer = wp_get_referer();
299
+
300
+ if ( $referer && 'wp-login.php' !== wp_basename( wp_parse_url( $referer, PHP_URL_PATH ) ) ) {
301
+ return $referer;
302
+ }
303
+
304
+ // Default to the AMP Settings page if a referrer link could not be determined.
305
+ return menu_page_url( AMP_Options_Manager::OPTION_NAME, false );
306
+ }
307
  }
src/Admin/OptionsMenu.php CHANGED
@@ -13,7 +13,6 @@ use AMP_Theme_Support;
13
  use AmpProject\AmpWP\Infrastructure\Conditional;
14
  use AmpProject\AmpWP\Infrastructure\Registerable;
15
  use AmpProject\AmpWP\Infrastructure\Service;
16
- use AmpProject\AmpWP\Option;
17
 
18
  /**
19
  * OptionsMenu class.
@@ -134,6 +133,8 @@ class OptionsMenu implements Conditional, Service, Registerable {
134
  * Add menu.
135
  */
136
  public function add_menu_items() {
 
 
137
  /*
138
  * Note that the admin items for Validated URLs and Validation Errors will also be placed under this admin menu
139
  * page when the current user can manage_options.
13
  use AmpProject\AmpWP\Infrastructure\Conditional;
14
  use AmpProject\AmpWP\Infrastructure\Registerable;
15
  use AmpProject\AmpWP\Infrastructure\Service;
 
16
 
17
  /**
18
  * OptionsMenu class.
133
  * Add menu.
134
  */
135
  public function add_menu_items() {
136
+ require_once ABSPATH . '/wp-admin/includes/plugin.php';
137
+
138
  /*
139
  * Note that the admin items for Validated URLs and Validation Errors will also be placed under this admin menu
140
  * page when the current user can manage_options.
src/Admin/PluginRowMeta.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class PluginRowMeta.
4
+ *
5
+ * @package AmpProject\AmpWP
6
+ */
7
+
8
+ namespace AmpProject\AmpWP\Admin;
9
+
10
+ use AmpProject\AmpWP\Infrastructure\Delayed;
11
+ use AmpProject\AmpWP\Infrastructure\Registerable;
12
+ use AmpProject\AmpWP\Infrastructure\Service;
13
+
14
+ /**
15
+ * Updates the plugin row meta for the plugin.
16
+ *
17
+ * @since 2.1
18
+ * @internal
19
+ */
20
+ final class PluginRowMeta implements Delayed, Service, Registerable {
21
+
22
+ /**
23
+ * Get the action to use for registering the service.
24
+ *
25
+ * @return string Registration action to use.
26
+ */
27
+ public static function get_registration_action() {
28
+ return 'admin_init';
29
+ }
30
+
31
+ /**
32
+ * Runs on instantiation.
33
+ */
34
+ public function register() {
35
+ add_filter( 'plugin_row_meta', [ $this, 'get_plugin_row_meta' ], 10, 2 );
36
+ }
37
+
38
+ /**
39
+ * Updates the plugin row meta with links to review plugin and get support.
40
+ *
41
+ * @param string[] $meta An array of the plugin's metadata, including the version, author, author URI,
42
+ * and plugin URI.
43
+ * @param string $plugin_file Path to the plugin file relative to the plugins directory.
44
+ * @return string[] Plugin row meta.
45
+ */
46
+ public function get_plugin_row_meta( $meta, $plugin_file ) {
47
+ if ( plugin_basename( AMP__FILE__ ) !== $plugin_file ) {
48
+ return $meta;
49
+ }
50
+
51
+ $additional_meta = [
52
+ '<a href="https://wordpress.org/support/plugin/amp/" target="_blank" rel="noreferrer noopener">' . esc_html__( 'Contact support', 'amp' ) . '</a>',
53
+ '<a href="https://wordpress.org/support/plugin/amp/reviews/#new-post" target="_blank" rel="noreferrer noopener">' . esc_html__( 'Leave review', 'amp' ) . '</a>',
54
+ ];
55
+
56
+ return array_merge( $meta, $additional_meta );
57
+ }
58
+ }
src/AmpWpPlugin.php CHANGED
@@ -61,6 +61,7 @@ final class AmpWpPlugin extends ServiceBasedPlugin {
61
  'admin.onboarding_wizard' => Admin\OnboardingWizardSubmenuPage::class,
62
  'admin.options_menu' => Admin\OptionsMenu::class,
63
  'admin.polyfills' => Admin\Polyfills::class,
 
64
  'amp_slug_customization_watcher' => AmpSlugCustomizationWatcher::class,
65
  'css_transient_cache.ajax_handler' => Admin\ReenableCssTransientCachingAjaxAction::class,
66
  'css_transient_cache.monitor' => BackgroundTask\MonitorCssTransientCaching::class,
61
  'admin.onboarding_wizard' => Admin\OnboardingWizardSubmenuPage::class,
62
  'admin.options_menu' => Admin\OptionsMenu::class,
63
  'admin.polyfills' => Admin\Polyfills::class,
64
+ 'admin.plugin_row_meta' => Admin\PluginRowMeta::class,
65
  'amp_slug_customization_watcher' => AmpSlugCustomizationWatcher::class,
66
  'css_transient_cache.ajax_handler' => Admin\ReenableCssTransientCachingAjaxAction::class,
67
  'css_transient_cache.monitor' => BackgroundTask\MonitorCssTransientCaching::class,
src/BackgroundTask/MonitorCssTransientCaching.php CHANGED
@@ -92,21 +92,21 @@ final class MonitorCssTransientCaching extends CronBasedBackgroundTask {
92
  * @todo This has arbitrary arguments to allow for testing, as we don't have dependency injection for services.
93
  * With dependency injection, we could for example inject a Clock object and mock it for testing.
94
  *
95
- * @param DateTimeInterface $date Optional. Date to use for timestamping the processing (for testing).
96
- * @param int $transient_count Optional. Count of transients to use for the processing (for testing).
97
  * @return void
98
  * @throws Exception If a date could not be instantiated.
99
  */
100
- public function process( DateTimeInterface $date = null, $transient_count = null ) {
101
  if ( wp_using_ext_object_cache() || $this->is_css_transient_caching_disabled() ) {
102
  return;
103
  }
104
 
105
- if ( null === $date ) {
106
  $date = new DateTimeImmutable();
107
  }
108
 
109
- if ( null === $transient_count ) {
110
  $transient_count = $this->query_css_transient_count();
111
  }
112
 
92
  * @todo This has arbitrary arguments to allow for testing, as we don't have dependency injection for services.
93
  * With dependency injection, we could for example inject a Clock object and mock it for testing.
94
  *
95
+ * @param DateTimeInterface|string $date Optional. Date to use for timestamping the processing (for testing). An empty string is provided during cron.
96
+ * @param int|string $transient_count Optional. Count of transients to use for the processing (for testing). An empty string is provided during cron.
97
  * @return void
98
  * @throws Exception If a date could not be instantiated.
99
  */
100
+ public function process( $date = '', $transient_count = '' ) {
101
  if ( wp_using_ext_object_cache() || $this->is_css_transient_caching_disabled() ) {
102
  return;
103
  }
104
 
105
+ if ( ! $date instanceof DateTimeInterface ) {
106
  $date = new DateTimeImmutable();
107
  }
108
 
109
+ if ( ! is_int( $transient_count ) ) {
110
  $transient_count = $this->query_css_transient_count();
111
  }
112
 
src/Instrumentation/Event.php CHANGED
@@ -96,6 +96,16 @@ class Event {
96
  }
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
99
  /**
100
  * Get the server timing header string.
101
  *
@@ -108,19 +118,19 @@ class Event {
108
  if ( is_float( $value ) ) {
109
  $property_strings[] = sprintf(
110
  ';%s="%.1f"',
111
- addslashes( $property ),
112
  $value
113
  );
114
  } else {
115
  $property_strings[] = sprintf(
116
  ';%s="%s"',
117
- addslashes( $property ),
118
  addslashes( $value )
119
  );
120
  }
121
  }
122
 
123
- $event_string = addslashes( $this->get_name() );
124
 
125
  $description = $this->get_description();
126
  if ( ! empty( $description ) ) {
96
  }
97
  }
98
 
99
+ /**
100
+ * Sanitize key to use it for an HTTP header label (alphanumeric and dashes/underscores only).
101
+ *
102
+ * @param string $key Unsanitized key.
103
+ * @return string Sanitized key.
104
+ */
105
+ private function sanitize_key( $key ) {
106
+ return preg_replace( '/[^a-zA-Z0-9_-]+/', '_', $key );
107
+ }
108
+
109
  /**
110
  * Get the server timing header string.
111
  *
118
  if ( is_float( $value ) ) {
119
  $property_strings[] = sprintf(
120
  ';%s="%.1f"',
121
+ $this->sanitize_key( $property ),
122
  $value
123
  );
124
  } else {
125
  $property_strings[] = sprintf(
126
  ';%s="%s"',
127
+ $this->sanitize_key( $property ),
128
  addslashes( $value )
129
  );
130
  }
131
  }
132
 
133
+ $event_string = $this->sanitize_key( $this->get_name() );
134
 
135
  $description = $this->get_description();
136
  if ( ! empty( $description ) ) {
src/Instrumentation/ServerTiming.php CHANGED
@@ -158,7 +158,7 @@ final class ServerTiming implements Service, Registerable, Delayed {
158
  return implode(
159
  ',',
160
  array_map(
161
- static function ( $event ) {
162
  return $event->get_header_string();
163
  },
164
  $this->events
158
  return implode(
159
  ',',
160
  array_map(
161
+ static function ( Event $event ) {
162
  return $event->get_header_string();
163
  },
164
  $this->events
src/MobileRedirection.php CHANGED
@@ -386,7 +386,63 @@ final class MobileRedirection implements Service, Registerable {
386
 
387
  $source = preg_replace( '/\bAMP_MOBILE_REDIRECTION\b/', wp_json_encode( $exports ), $source );
388
 
389
- printf( '<script>%s</script>', $source ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  }
391
 
392
  /**
386
 
387
  $source = preg_replace( '/\bAMP_MOBILE_REDIRECTION\b/', wp_json_encode( $exports ), $source );
388
 
389
+ if ( function_exists( 'wp_print_inline_script_tag' ) ) {
390
+ wp_print_inline_script_tag( $source );
391
+ } else {
392
+ echo $this->get_inline_script_tag( $source ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Wraps inline JavaScript in `<script>` tag.
398
+ *
399
+ * This is copied from WordPress 5.7, the version in which it was introduced.
400
+ *
401
+ * @see wp_get_inline_script_tag()
402
+ *
403
+ * @param string $javascript Inline JavaScript code.
404
+ * @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.
405
+ * @return string String containing inline JavaScript code wrapped around `<script>` tag.
406
+ */
407
+ private function get_inline_script_tag( $javascript, $attributes = [] ) {
408
+ if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
409
+ $attributes['type'] = 'text/javascript';
410
+ }
411
+
412
+ /** This filter is documented in wp-includes/script-loader.php */
413
+ $attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $javascript );
414
+
415
+ $javascript = "\n" . trim( $javascript, "\n\r " ) . "\n";
416
+
417
+ return sprintf( "<script%s>%s</script>\n", $this->sanitize_script_attributes( $attributes ), $javascript );
418
+ }
419
+
420
+ /**
421
+ * Sanitizes an attributes array into an attributes string to be placed inside a `<script>` tag.
422
+ *
423
+ * This is copied from WordPress 5.7, the version in which it was introduced.
424
+ *
425
+ * @see wp_sanitize_script_attributes()
426
+ *
427
+ * @param array $attributes Key-value pairs representing `<script>` tag attributes.
428
+ * @return string String made of sanitized `<script>` tag attributes.
429
+ */
430
+ private function sanitize_script_attributes( $attributes ) {
431
+ $html5_script_support = ! is_admin() && ! current_theme_supports( 'html5', 'script' );
432
+ $attributes_string = '';
433
+
434
+ // If HTML5 script tag is supported, only the attribute name is added
435
+ // to $attributes_string for entries with a boolean value, and that are true.
436
+ foreach ( $attributes as $attribute_name => $attribute_value ) {
437
+ if ( is_bool( $attribute_value ) ) {
438
+ if ( $attribute_value ) {
439
+ $attributes_string .= $html5_script_support ? sprintf( ' %1$s="%2$s"', esc_attr( $attribute_name ), esc_attr( $attribute_name ) ) : ' ' . $attribute_name;
440
+ }
441
+ } else {
442
+ $attributes_string .= sprintf( ' %1$s="%2$s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) );
443
+ }
444
+ }
445
+ return $attributes_string;
446
  }
447
 
448
  /**
vendor/ampproject/optimizer/src/Transformer/ServerSideRendering.php CHANGED
@@ -163,7 +163,7 @@ final class ServerSideRendering implements Transformer
163
  }
164
 
165
  // Skip tags inside a template tag.
166
- if ($this->hasAncestorWithTag($ampElement, Tag::TEMPLATE)) {
167
  continue;
168
  }
169
 
@@ -682,21 +682,27 @@ final class ServerSideRendering implements Transformer
682
  }
683
 
684
  /**
685
- * Check whether the element has an ancestor of a given tag type.
686
  *
687
- * @param DOMElement $element Element to check the ancestor tree of.
688
- * @param string $tagName Name of the tag to look for.
689
- * @return bool Whether the element has an ancestor of the given tag name.
690
  */
691
- private function hasAncestorWithTag(DOMElement $element, $tagName)
692
  {
693
  $parent = $element->parentNode;
694
  while ($parent !== null) {
695
- if ($parent instanceof DOMElement && $parent->tagName === $tagName) {
696
- return true;
 
 
 
 
 
 
697
  }
698
  $parent = $parent->parentNode;
699
  }
 
700
  return false;
701
  }
702
 
163
  }
164
 
165
  // Skip tags inside a template tag.
166
+ if ($this->isWithinTemplate($ampElement)) {
167
  continue;
168
  }
169
 
682
  }
683
 
684
  /**
685
+ * Check whether the element is within a template.
686
  *
687
+ * @param DOMElement $element Element to check.
688
+ * @return bool Whether the element is within a template.
 
689
  */
690
+ private function isWithinTemplate(DOMElement $element)
691
  {
692
  $parent = $element->parentNode;
693
  while ($parent !== null) {
694
+ if ($parent instanceof DOMElement) {
695
+ if ($parent->tagName === Tag::TEMPLATE) {
696
+ return true;
697
+ }
698
+
699
+ if ($parent->tagName === Tag::SCRIPT && $parent->hasAttribute(Attribute::TEMPLATE)) {
700
+ return true;
701
+ }
702
  }
703
  $parent = $parent->parentNode;
704
  }
705
+
706
  return false;
707
  }
708
 
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit8b9bf7226e6b67e213fc141a441d71b6::getLoader();
vendor/composer/ClassLoader.php CHANGED
@@ -60,7 +60,7 @@ class ClassLoader
60
  public function getPrefixes()
61
  {
62
  if (!empty($this->prefixesPsr0)) {
63
- return call_user_func_array('array_merge', $this->prefixesPsr0);
64
  }
65
 
66
  return array();
60
  public function getPrefixes()
61
  {
62
  if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
64
  }
65
 
66
  return array();
vendor/composer/autoload_classmap.php CHANGED
@@ -93,6 +93,7 @@ return array(
93
  'AmpProject\\AmpWP\\Admin\\OnboardingWizardSubmenuPage' => $baseDir . '/src/Admin/OnboardingWizardSubmenuPage.php',
94
  'AmpProject\\AmpWP\\Admin\\OptionsMenu' => $baseDir . '/src/Admin/OptionsMenu.php',
95
  'AmpProject\\AmpWP\\Admin\\PluginActivationNotice' => $baseDir . '/src/Admin/PluginActivationNotice.php',
 
96
  'AmpProject\\AmpWP\\Admin\\Polyfills' => $baseDir . '/src/Admin/Polyfills.php',
97
  'AmpProject\\AmpWP\\Admin\\RESTPreloader' => $baseDir . '/src/Admin/RESTPreloader.php',
98
  'AmpProject\\AmpWP\\Admin\\ReaderThemes' => $baseDir . '/src/Admin/ReaderThemes.php',
93
  'AmpProject\\AmpWP\\Admin\\OnboardingWizardSubmenuPage' => $baseDir . '/src/Admin/OnboardingWizardSubmenuPage.php',
94
  'AmpProject\\AmpWP\\Admin\\OptionsMenu' => $baseDir . '/src/Admin/OptionsMenu.php',
95
  'AmpProject\\AmpWP\\Admin\\PluginActivationNotice' => $baseDir . '/src/Admin/PluginActivationNotice.php',
96
+ 'AmpProject\\AmpWP\\Admin\\PluginRowMeta' => $baseDir . '/src/Admin/PluginRowMeta.php',
97
  'AmpProject\\AmpWP\\Admin\\Polyfills' => $baseDir . '/src/Admin/Polyfills.php',
98
  'AmpProject\\AmpWP\\Admin\\RESTPreloader' => $baseDir . '/src/Admin/RESTPreloader.php',
99
  'AmpProject\\AmpWP\\Admin\\ReaderThemes' => $baseDir . '/src/Admin/ReaderThemes.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInit74ae9b1e5d841728c62963ae6b648805::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
@@ -51,19 +51,19 @@ class ComposerAutoloaderInit74ae9b1e5d841728c62963ae6b648805
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
- $includeFiles = Composer\Autoload\ComposerStaticInit74ae9b1e5d841728c62963ae6b648805::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
- composerRequire74ae9b1e5d841728c62963ae6b648805($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
- function composerRequire74ae9b1e5d841728c62963ae6b648805($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit8b9bf7226e6b67e213fc141a441d71b6
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInit8b9bf7226e6b67e213fc141a441d71b6', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit8b9bf7226e6b67e213fc141a441d71b6', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
51
  $loader->register(true);
52
 
53
  if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6::$files;
55
  } else {
56
  $includeFiles = require __DIR__ . '/autoload_files.php';
57
  }
58
  foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequire8b9bf7226e6b67e213fc141a441d71b6($fileIdentifier, $file);
60
  }
61
 
62
  return $loader;
63
  }
64
  }
65
 
66
+ function composerRequire8b9bf7226e6b67e213fc141a441d71b6($fileIdentifier, $file)
67
  {
68
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit74ae9b1e5d841728c62963ae6b648805
8
  {
9
  public static $files = array (
10
  '6f5653f9af3eab04254ad2c7f20515c8' => __DIR__ . '/../..' . '/back-compat/back-compat.php',
@@ -141,6 +141,7 @@ class ComposerStaticInit74ae9b1e5d841728c62963ae6b648805
141
  'AmpProject\\AmpWP\\Admin\\OnboardingWizardSubmenuPage' => __DIR__ . '/../..' . '/src/Admin/OnboardingWizardSubmenuPage.php',
142
  'AmpProject\\AmpWP\\Admin\\OptionsMenu' => __DIR__ . '/../..' . '/src/Admin/OptionsMenu.php',
143
  'AmpProject\\AmpWP\\Admin\\PluginActivationNotice' => __DIR__ . '/../..' . '/src/Admin/PluginActivationNotice.php',
 
144
  'AmpProject\\AmpWP\\Admin\\Polyfills' => __DIR__ . '/../..' . '/src/Admin/Polyfills.php',
145
  'AmpProject\\AmpWP\\Admin\\RESTPreloader' => __DIR__ . '/../..' . '/src/Admin/RESTPreloader.php',
146
  'AmpProject\\AmpWP\\Admin\\ReaderThemes' => __DIR__ . '/../..' . '/src/Admin/ReaderThemes.php',
@@ -338,9 +339,9 @@ class ComposerStaticInit74ae9b1e5d841728c62963ae6b648805
338
  public static function getInitializer(ClassLoader $loader)
339
  {
340
  return \Closure::bind(function () use ($loader) {
341
- $loader->prefixLengthsPsr4 = ComposerStaticInit74ae9b1e5d841728c62963ae6b648805::$prefixLengthsPsr4;
342
- $loader->prefixDirsPsr4 = ComposerStaticInit74ae9b1e5d841728c62963ae6b648805::$prefixDirsPsr4;
343
- $loader->classMap = ComposerStaticInit74ae9b1e5d841728c62963ae6b648805::$classMap;
344
 
345
  }, null, ClassLoader::class);
346
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6
8
  {
9
  public static $files = array (
10
  '6f5653f9af3eab04254ad2c7f20515c8' => __DIR__ . '/../..' . '/back-compat/back-compat.php',
141
  'AmpProject\\AmpWP\\Admin\\OnboardingWizardSubmenuPage' => __DIR__ . '/../..' . '/src/Admin/OnboardingWizardSubmenuPage.php',
142
  'AmpProject\\AmpWP\\Admin\\OptionsMenu' => __DIR__ . '/../..' . '/src/Admin/OptionsMenu.php',
143
  'AmpProject\\AmpWP\\Admin\\PluginActivationNotice' => __DIR__ . '/../..' . '/src/Admin/PluginActivationNotice.php',
144
+ 'AmpProject\\AmpWP\\Admin\\PluginRowMeta' => __DIR__ . '/../..' . '/src/Admin/PluginRowMeta.php',
145
  'AmpProject\\AmpWP\\Admin\\Polyfills' => __DIR__ . '/../..' . '/src/Admin/Polyfills.php',
146
  'AmpProject\\AmpWP\\Admin\\RESTPreloader' => __DIR__ . '/../..' . '/src/Admin/RESTPreloader.php',
147
  'AmpProject\\AmpWP\\Admin\\ReaderThemes' => __DIR__ . '/../..' . '/src/Admin/ReaderThemes.php',
339
  public static function getInitializer(ClassLoader $loader)
340
  {
341
  return \Closure::bind(function () use ($loader) {
342
+ $loader->prefixLengthsPsr4 = ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6::$prefixLengthsPsr4;
343
+ $loader->prefixDirsPsr4 = ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6::$prefixDirsPsr4;
344
+ $loader->classMap = ComposerStaticInit8b9bf7226e6b67e213fc141a441d71b6::$classMap;
345
 
346
  }, null, ClassLoader::class);
347
  }
vendor/composer/installed.json CHANGED
@@ -1,12 +1,12 @@
1
  [
2
  {
3
  "name": "ampproject/common",
4
- "version": "dev-fix/docs-generation-2.0",
5
- "version_normalized": "dev-fix/docs-generation-2.0",
6
  "dist": {
7
  "type": "path",
8
  "url": "lib/common",
9
- "reference": "68d6534c512a0ebcd6b3fed94131d4b1738d929a"
10
  },
11
  "require": {
12
  "ext-dom": "*",
@@ -76,17 +76,18 @@
76
  ],
77
  "description": "PHP library with common base functionality for AMP integrations.",
78
  "transport-options": {
79
- "symlink": true
 
80
  }
81
  },
82
  {
83
  "name": "ampproject/optimizer",
84
- "version": "dev-fix/docs-generation-2.0",
85
- "version_normalized": "dev-fix/docs-generation-2.0",
86
  "dist": {
87
  "type": "path",
88
  "url": "lib/optimizer",
89
- "reference": "3c1c51d680d561801981294086d13be509327cc4"
90
  },
91
  "require": {
92
  "ampproject/common": "*",
@@ -164,7 +165,8 @@
164
  ],
165
  "description": "PHP library for optimizing AMP pages.",
166
  "transport-options": {
167
- "symlink": true
 
168
  }
169
  },
170
  {
1
  [
2
  {
3
  "name": "ampproject/common",
4
+ "version": "2.0.x-dev",
5
+ "version_normalized": "2.0.9999999.9999999-dev",
6
  "dist": {
7
  "type": "path",
8
  "url": "lib/common",
9
+ "reference": "9ae4d10f085d41c46ae00ee0c32db2f96165a877"
10
  },
11
  "require": {
12
  "ext-dom": "*",
76
  ],
77
  "description": "PHP library with common base functionality for AMP integrations.",
78
  "transport-options": {
79
+ "symlink": true,
80
+ "relative": true
81
  }
82
  },
83
  {
84
  "name": "ampproject/optimizer",
85
+ "version": "2.0.x-dev",
86
+ "version_normalized": "2.0.9999999.9999999-dev",
87
  "dist": {
88
  "type": "path",
89
  "url": "lib/optimizer",
90
+ "reference": "d4658dac3e58a9377314cb340f8cafe3b892d06f"
91
  },
92
  "require": {
93
  "ampproject/common": "*",
165
  ],
166
  "description": "PHP library for optimizing AMP pages.",
167
  "transport-options": {
168
+ "symlink": true,
169
+ "relative": true
170
  }
171
  },
172
  {