diff --git a/.dev-lib b/.dev-lib index cb76151efe1..ac8f8ff8bb4 100644 --- a/.dev-lib +++ b/.dev-lib @@ -1 +1,2 @@ -SYNC_README_MD=0 \ No newline at end of file +SYNC_README_MD=0 +PATH_EXCLUDES_PATTERN=includes/lib/* diff --git a/amp.php b/amp.php index db1abae1f12..1707e70499a 100644 --- a/amp.php +++ b/amp.php @@ -17,16 +17,12 @@ define( 'AMP__DIR__', dirname( __FILE__ ) ); define( 'AMP__VERSION', '0.6.0-alpha' ); +require_once AMP__DIR__ . '/includes/class-amp-autoloader.php'; +AMP_Autoloader::register(); + require_once AMP__DIR__ . '/back-compat/back-compat.php'; require_once AMP__DIR__ . '/includes/amp-helper-functions.php'; -require_once AMP__DIR__ . '/includes/class-amp-post-type-support.php'; require_once AMP__DIR__ . '/includes/admin/functions.php'; -require_once AMP__DIR__ . '/includes/admin/class-amp-customizer.php'; -require_once AMP__DIR__ . '/includes/admin/class-amp-post-meta-box.php'; -require_once AMP__DIR__ . '/includes/settings/class-amp-customizer-settings.php'; -require_once AMP__DIR__ . '/includes/settings/class-amp-customizer-design-settings.php'; -require_once AMP__DIR__ . '/includes/actions/class-amp-frontend-actions.php'; -require_once AMP__DIR__ . '/includes/actions/class-amp-paired-post-actions.php'; register_activation_hook( __FILE__, 'amp_activate' ); function amp_activate() { @@ -150,7 +146,7 @@ function amp_maybe_add_actions() { } function amp_load_classes() { - require_once( AMP__DIR__ . '/includes/class-amp-post-template.php' ); // this loads everything else + _deprecated_function( __FUNCTION__, '0.6.0' ); } function amp_add_frontend_actions() { @@ -196,8 +192,6 @@ function amp_render_post( $post ) { } $post_id = $post->ID; - amp_load_classes(); - /** * Fires before rendering a post in AMP. * @@ -246,9 +240,3 @@ function amp_redirect_old_slug_to_new_url( $link ) { return $link; } - -// Unconditionally load code required when running unit tests. -if ( function_exists( 'tests_add_filter' ) ) { - amp_load_classes(); - require_once dirname( __FILE__ ) . '/tests/stubs.php'; -} diff --git a/composer.json b/composer.json new file mode 100644 index 00000000000..8cbf0c809f4 --- /dev/null +++ b/composer.json @@ -0,0 +1,7 @@ +{ + "name": "automattic/amp-wp", + "description": "WordPress plugin for adding AMP support.", + "homepage": "https://github.com/Automattic/amp-wp", + "type": "wordpress-plugin", + "license": "GPL-2.0" +} diff --git a/dev-lib b/dev-lib index 52874e44d9e..4ac4bd20b5a 160000 --- a/dev-lib +++ b/dev-lib @@ -1 +1 @@ -Subproject commit 52874e44d9e737dfc8f1e9ca33381f45deb9b636 +Subproject commit 4ac4bd20b5a4b3953eb81a8d2536baef2bf60dcb diff --git a/includes/actions/class-amp-frontend-actions.php b/includes/actions/class-amp-frontend-actions.php index baf9a5d441e..8fa8ef1cfab 100644 --- a/includes/actions/class-amp-frontend-actions.php +++ b/includes/actions/class-amp-frontend-actions.php @@ -1,14 +1,27 @@ <?php echo esc_html( $amp_template->get( 'document_title' ) ); ?> get( 'amp_component_scripts', array() ); foreach ( $scripts as $element => $script ) : - $custom_type = ($element == 'amp-mustache') ? 'template' : 'element'; ?> + $custom_type = ( 'amp-mustache' === $element ) ? 'template' : 'element'; + ?> get( 'font_urls', array() ); - foreach ( $font_urls as $slug => $url ) : ?> + ?> + $url ) : ?> - + get( 'metadata' ); if ( empty( $metadata ) ) { @@ -62,54 +104,70 @@ public static function add_schemaorg_metadata( $amp_template ) { get( 'post_amp_styles' ); if ( ! empty( $styles ) ) { - echo '/* Inline styles */' . PHP_EOL; + echo '/* Inline styles */' . PHP_EOL; // WPCS: XSS OK. foreach ( $styles as $selector => $declarations ) { $declarations = implode( ';', $declarations ) . ';'; - printf( '%1$s{%2$s}', $selector, $declarations ); + printf( '%1$s{%2$s}', $selector, $declarations ); // WPCS: XSS OK. } } } - + + /** + * Add analytics scripts. + * + * @param array $data Data. + * @return array Data. + */ public static function add_analytics_scripts( $data ) { if ( ! empty( $data['amp_analytics'] ) ) { $data['amp_component_scripts']['amp-analytics'] = 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js'; } return $data; } - - public static function add_analytics_data( $amp_template ) { + + /** + * Print analytics data. + * + * @param AMP_Post_Template $amp_template Template. + */ + public static function add_analytics_data( $amp_template ) { $analytics_entries = $amp_template->get( 'amp_analytics' ); if ( empty( $analytics_entries ) ) { return; } - + foreach ( $analytics_entries as $id => $analytics_entry ) { if ( ! isset( $analytics_entry['type'], $analytics_entry['attributes'], $analytics_entry['config_data'] ) ) { /* translators: %1$s is analytics entry ID, %2$s is actual entry keys. */ _doing_it_wrong( __FUNCTION__, sprintf( esc_html__( 'Analytics entry for %1$s is missing one of the following keys: `type`, `attributes`, or `config_data` (array keys: %2$s)', 'amp' ), esc_html( $id ), esc_html( implode( ', ', array_keys( $analytics_entry ) ) ) ), '0.3.2' ); continue; } - + $script_element = AMP_HTML_Utils::build_tag( 'script', array( 'type' => 'application/json', ), wp_json_encode( $analytics_entry['config_data'] ) ); - + $amp_analytics_attr = array_merge( array( 'id' => $id, 'type' => $analytics_entry['type'], ), $analytics_entry['attributes'] ); - - echo AMP_HTML_Utils::build_tag( 'amp-analytics', $amp_analytics_attr, $script_element ); + + echo AMP_HTML_Utils::build_tag( 'amp-analytics', $amp_analytics_attr, $script_element ); // WPCS: XSS OK. } } /** - * Add AMP generator metadata. + * Print AMP generator metadata. * - * @param object $amp_template AMP_Post_Template object. + * @param AMP_Post_Template $amp_template AMP_Post_Template object. * @since 0.6 */ public static function add_generator_metadata( $amp_template ) { diff --git a/includes/admin/functions.php b/includes/admin/functions.php index 62bbc0e69f8..f033a620d0b 100644 --- a/includes/admin/functions.php +++ b/includes/admin/functions.php @@ -1,9 +1,6 @@ 'subdir-of-includes/filename1', + * 'Class_Name2' => '2nd-subdir-of-includes/filename2', + * ); + * + * @var string[] + */ + private static $_classmap = array( + 'AMP_Actions' => 'includes/actions/class-amp-actions', + 'AMP_Frontend_Actions' => 'includes/actions/class-amp-frontend-actions', + 'AMP_Paired_Post_Actions' => 'includes/actions/class-amp-paired-post-actions', + 'AMP_Template_Customizer' => 'includes/admin/class-amp-customizer', + 'AMP_Post_Meta_Box' => 'includes/admin/class-amp-post-meta-box', + 'AMP_Post_Type_Support' => 'includes/class-amp-post-type-support', + 'AMP_Base_Embed_Handler' => 'includes/embeds/class-amp-base-embed-handler', + 'AMP_DailyMotion_Embed_Handler' => 'includes/embeds/class-amp-dailymotion-embed', + 'AMP_Facebook_Embed_Handler' => 'includes/embeds/class-amp-facebook-embed', + 'AMP_Gallery_Embed_Handler' => 'includes/embeds/class-amp-gallery-embed', + 'AMP_Instagram_Embed_Handler' => 'includes/embeds/class-amp-instagram-embed', + 'AMP_Pinterest_Embed_Handler' => 'includes/embeds/class-amp-pinterest-embed', + 'AMP_SoundCloud_Embed_Handler' => 'includes/embeds/class-amp-soundcloud-embed', + 'AMP_Twitter_Embed_Handler' => 'includes/embeds/class-amp-twitter-embed', + 'AMP_Vimeo_Embed_Handler' => 'includes/embeds/class-amp-vimeo-embed', + 'AMP_Vine_Embed_Handler' => 'includes/embeds/class-amp-vine-embed', + 'AMP_YouTube_Embed_Handler' => 'includes/embeds/class-amp-youtube-embed', + 'FastImage' => 'includes/lib/fastimage/class-fastimage', + 'WillWashburn\\Stream\\Exception\\StreamBufferTooSmallException' => 'includes/lib/fasterimage/Stream/Exception/StreamBufferTooSmallException', + 'WillWashburn\\Stream\\StreamableInterface' => 'includes/lib/fasterimage/Stream/StreamableInterface', + 'WillWashburn\\Stream\\Stream' => 'includes/lib/fasterimage/Stream/Stream', + 'FasterImage\\Exception\\InvalidImageException' => 'includes/lib/fasterimage/Exception/InvalidImageException', + 'FasterImage\\ExifParser' => 'includes/lib/fasterimage/ExifParser', + 'FasterImage\\ImageParser' => 'includes/lib/fasterimage/ImageParser', + 'FasterImage\\FasterImage' => 'includes/lib/fasterimage/FasterImage', + 'AMP_Analytics_Options_Submenu' => 'includes/options/class-amp-analytics-options-submenu', + 'AMP_Options_Menu' => 'includes/options/class-amp-options-menu', + 'AMP_Options_Manager' => 'includes/options/class-amp-options-manager', + 'AMP_Analytics_Options_Submenu_Page' => 'includes/options/views/class-amp-analytics-options-submenu-page', + 'AMP_Options_Menu_Page' => 'includes/options/views/class-amp-options-menu-page', + 'AMP_Rule_Spec' => 'includes/sanitizers/class-amp-rule-spec', + 'AMP_Allowed_Tags_Generated' => 'includes/sanitizers/class-amp-allowed-tags-generated', + 'AMP_Audio_Sanitizer' => 'includes/sanitizers/class-amp-audio-sanitizer', + 'AMP_Base_Sanitizer' => 'includes/sanitizers/class-amp-base-sanitizer', + 'AMP_Blacklist_Sanitizer' => 'includes/sanitizers/class-amp-blacklist-sanitizer', + 'AMP_Iframe_Sanitizer' => 'includes/sanitizers/class-amp-iframe-sanitizer', + 'AMP_Img_Sanitizer' => 'includes/sanitizers/class-amp-img-sanitizer', + 'AMP_Playbuzz_Sanitizer' => 'includes/sanitizers/class-amp-playbuzz-sanitizer', + 'AMP_Style_Sanitizer' => 'includes/sanitizers/class-amp-style-sanitizer', + 'AMP_Tag_And_Attribute_Sanitizer' => 'includes/sanitizers/class-amp-tag-and-attribute-sanitizer', + 'AMP_Video_Sanitizer' => 'includes/sanitizers/class-amp-video-sanitizer', + 'AMP_Customizer_Design_Settings' => 'includes/settings/class-amp-customizer-design-settings', + 'AMP_Customizer_Settings' => 'includes/settings/class-amp-customizer-settings', + 'AMP_Content' => 'includes/templates/class-amp-content', + 'AMP_Content_Sanitizer' => 'includes/templates/class-amp-content-sanitizer', + 'AMP_Post_Template' => 'includes/templates/class-amp-post-template', + 'AMP_DOM_Utils' => 'includes/utils/class-amp-dom-utils', + 'AMP_HTML_Utils' => 'includes/utils/class-amp-html-utils', + 'AMP_Image_Dimension_Extractor' => 'includes/utils/class-amp-image-dimension-extractor', + 'AMP_String_Utils' => 'includes/utils/class-amp-string-utils', + 'AMP_WP_Utils' => 'includes/utils/class-amp-wp-utils', + 'WPCOM_AMP_Polldaddy_Embed' => 'includes/wpcom/class-amp-polldaddy-embed', + 'AMP_Test_Stub_Sanitizer' => 'tests/stubs', + 'AMP_Test_World_Sanitizer' => 'tests/stubs', + ); + + /** + * Is registered. + * + * @var bool + */ + public static $is_registered = false; + + /** + * Perform the autoload on demand when requested by PHP runtime. + * + * Design Goal: Execute as few lines of code as possible each call. + * + * @since 0.6.0 + * + * @param string $class_name Class name. + */ + protected static function autoload( $class_name ) { + if ( ! isset( self::$_classmap[ $class_name ] ) ) { + return; + } + $filepath = self::$_classmap[ $class_name ]; + require AMP__DIR__ . "/{$filepath}.php"; + } + + /** + * Registers this autoloader to PHP. + * + * @since 0.6.0 + * + * Called at the end of this file; calling a second time has no effect. + */ + public static function register() { + if ( ! self::$is_registered ) { + spl_autoload_register( array( __CLASS__, 'autoload' ) ); + self::$is_registered = true; + } + } + + /** + * Allows an extensions plugin to register a class and its file for autoloading + * + * @since 0.6.0 + * + * @param string $class_name Full classname (include namespace if applicable). + * @param string $filepath Absolute filepath to class file, including .php extension. + */ + public static function register_autoload_class( $class_name, $filepath ) { + self::$_classmap[ $class_name ] = '!' . $filepath; + } +} diff --git a/includes/embeds/class-amp-base-embed-handler.php b/includes/embeds/class-amp-base-embed-handler.php index d9152d0a420..8e3133e62d2 100644 --- a/includes/embeds/class-amp-base-embed-handler.php +++ b/includes/embeds/class-amp-base-embed-handler.php @@ -1,8 +1,15 @@ tags to + */ class AMP_Audio_Sanitizer extends AMP_Base_Sanitizer { + + /** + * Tag. + * + * @var string HTML audio tag to identify and replace with AMP version. + * @since 0.2 + */ public static $tag = 'audio'; + /** + * Script slug. + * + * @var string AMP HTML audio tag to use in place of HTML's 'audio' tag. + * + * @since 0.2 + */ private static $script_slug = 'amp-audio'; + + /** + * Script src. + * + * @var string URL to AMP Project's Audio element javascript file found at cdn.ampproject.org + * + * @since 0.2 + */ private static $script_src = 'https://cdn.ampproject.org/v0/amp-audio-0.1.js'; + /** + * Return one element array containing AMP HTML audio tag and respective Javascript URL + * + * HTML tags and Javascript URLs found at cdn.ampproject.org + * + * @since 0.2 + * + * @return string[] Returns AMP HTML audio tag as array key and Javascript URL as array value, + * respectively. Will return an empty array if sanitization has yet to be run + * or if it did not find any HTML audio elements to convert to AMP equivalents. + */ public function get_scripts() { if ( ! $this->did_convert_elements ) { return array(); } - return array( self::$script_slug => self::$script_src ); } + /** + * Sanitize the