You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.3 KiB
PHP
187 lines
6.3 KiB
PHP
<?php
|
|
/**
|
|
* Class Optimization
|
|
*
|
|
* @link https://github.com/googleforcreators/web-stories-wp
|
|
*
|
|
* @copyright 2020 Google LLC
|
|
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
|
*/
|
|
|
|
/**
|
|
* Copyright 2020 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
declare(strict_types = 1);
|
|
|
|
namespace Google\Web_Stories\AMP;
|
|
|
|
use Google\Web_Stories_Dependencies\AmpProject\AmpWP\RemoteRequest\CachedRemoteGetRequest;
|
|
use Google\Web_Stories_Dependencies\AmpProject\AmpWP\RemoteRequest\WpHttpRemoteGetRequest;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Dom\Document;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Configuration;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Configuration\AmpStoryCssOptimizerConfiguration;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\DefaultConfiguration;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Error;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\ErrorCollection;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\LocalFallback;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\TransformationEngine;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\AmpRuntimeCss;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\AmpStoryCssOptimizer;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\MinifyHtml;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\OptimizeAmpBind;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\OptimizeHeroImages;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\RewriteAmpUrls;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\ServerSideRendering;
|
|
use Google\Web_Stories_Dependencies\AmpProject\Optimizer\Transformer\TransformedIdentifier;
|
|
use Google\Web_Stories_Dependencies\AmpProject\RemoteRequest\FallbackRemoteGetRequest;
|
|
use Google\Web_Stories_Dependencies\AmpProject\RemoteRequest\FilesystemRemoteGetRequest;
|
|
|
|
/**
|
|
* Optimization class.
|
|
*
|
|
* @since 1.1.0
|
|
*/
|
|
class Optimization {
|
|
/**
|
|
* Optimizes a document.
|
|
*
|
|
* @since 1.1.0
|
|
*
|
|
* @param Document $document Document instance.
|
|
*/
|
|
public function optimize_document( Document $document ): void {
|
|
$errors = new ErrorCollection();
|
|
$this->get_optimizer()->optimizeDom( $document, $errors );
|
|
if ( \count( $errors ) > 0 ) {
|
|
/**
|
|
* Error list.
|
|
*
|
|
* @var Error[] $errors_array Error list.
|
|
*/
|
|
$errors_array = iterator_to_array( $errors );
|
|
|
|
$error_messages = array_filter(
|
|
array_map(
|
|
static function ( Error $error ) {
|
|
// Hidden because amp-story is a render-delaying extension.
|
|
if ( 'CannotRemoveBoilerplate' === $error->getCode() ) {
|
|
return '';
|
|
}
|
|
|
|
return ' - ' . $error->getCode() . ': ' . $error->getMessage();
|
|
},
|
|
$errors_array
|
|
)
|
|
);
|
|
|
|
if ( ! empty( $error_messages ) ) {
|
|
$document->head->appendChild(
|
|
$document->createComment( "\n" . __( 'AMP optimization could not be completed due to the following:', 'web-stories' ) . "\n" . implode( "\n", $error_messages ) . "\n" )
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optimizer instance to use.
|
|
*
|
|
* @since 1.1.0
|
|
*
|
|
* @link https://github.com/ampproject/amp-wp/blob/8856284d90fc8558c30acc029becd352ae26e4e1/includes/class-amp-theme-support.php#L2235-L2255
|
|
* @see AMP_Theme_Support::get_optimizer
|
|
*
|
|
* @return TransformationEngine Optimizer transformation engine to use.
|
|
*/
|
|
private function get_optimizer(): TransformationEngine {
|
|
$configuration = self::get_optimizer_configuration();
|
|
|
|
$fallback_remote_request_pipeline = new FallbackRemoteGetRequest(
|
|
new WpHttpRemoteGetRequest(),
|
|
new FilesystemRemoteGetRequest( LocalFallback::getMappings() )
|
|
);
|
|
|
|
$cached_remote_request = new CachedRemoteGetRequest( $fallback_remote_request_pipeline, WEEK_IN_SECONDS );
|
|
|
|
return new TransformationEngine(
|
|
$configuration,
|
|
$cached_remote_request
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the AmpProject\Optimizer configuration object to use.
|
|
*
|
|
* @since 1.1.0
|
|
*
|
|
* @link https://github.com/ampproject/amp-wp/blob/5405daa38e65f0ec16ffc920014d0110b03ee773/src/Optimizer/AmpWPConfiguration.php#L43-L78
|
|
* @see AmpWPConfiguration::apply_filters()
|
|
*
|
|
* @return Configuration Optimizer configuration to use.
|
|
*/
|
|
private static function get_optimizer_configuration(): Configuration {
|
|
$transformers = Configuration::DEFAULT_TRANSFORMERS;
|
|
|
|
$transformers[] = AmpStoryCssOptimizer::class;
|
|
|
|
/**
|
|
* Filter whether the AMP Optimizer should use server-side rendering or not.
|
|
*
|
|
* @since 1.1.0
|
|
*
|
|
* @param bool $enable_ssr Whether the AMP Optimizer should use server-side rendering or not.
|
|
*/
|
|
$enable_ssr = apply_filters( 'web_stories_enable_ssr', true );
|
|
|
|
// In debugging mode, we don't use server-side rendering, as it further obfuscates the HTML markup.
|
|
if ( ! $enable_ssr ) {
|
|
$transformers = array_diff(
|
|
$transformers,
|
|
[
|
|
AmpRuntimeCss::class,
|
|
OptimizeHeroImages::class,
|
|
OptimizeAmpBind::class,
|
|
RewriteAmpUrls::class,
|
|
ServerSideRendering::class,
|
|
TransformedIdentifier::class,
|
|
AmpStoryCssOptimizer::class,
|
|
]
|
|
);
|
|
}
|
|
|
|
$configuration = [
|
|
Configuration::KEY_TRANSFORMERS => $transformers,
|
|
AmpStoryCssOptimizer::class => [
|
|
AmpStoryCssOptimizerConfiguration::OPTIMIZE_AMP_STORY => true,
|
|
],
|
|
MinifyHtml::class => [
|
|
// Prevents issues with rounding floats, relevant for things like shopping (product prices).
|
|
Configuration\MinifyHtmlConfiguration::MINIFY_JSON => false,
|
|
],
|
|
];
|
|
|
|
/**
|
|
* Filter the configuration to be used for the AMP Optimizer.
|
|
*
|
|
* @since 1.1.0
|
|
*
|
|
* @param array $configuration Associative array of configuration data.
|
|
*/
|
|
$configuration = apply_filters( 'web_stories_amp_optimizer_config', $configuration );
|
|
|
|
return new DefaultConfiguration( $configuration );
|
|
}
|
|
}
|