Skip to content

Commit

Permalink
Lift and shift app shell service worker from ampproject/amp-wp#1519
Browse files Browse the repository at this point in the history
  • Loading branch information
delawski committed Aug 6, 2020
1 parent 3593cb9 commit 3e814fd
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 7 deletions.
1 change: 1 addition & 0 deletions amp-app-shell.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ function _amp_app_shell_incorrect_plugin_slug_admin_notice() {
}

require_once AMP_APP_SHELL__DIR__ . '/includes/amp-app-shell-helper-functions.php';
require_once AMP_APP_SHELL__DIR__ . '/includes/class-amp-app-shell-service-worker.php';
require_once AMP_APP_SHELL__DIR__ . '/includes/class-amp-app-shell.php';

register_activation_hook( __FILE__, 'amp_app_shell_activate' );
Expand Down
47 changes: 47 additions & 0 deletions assets/src/js/amp-service-worker-offline-commenting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* global ERROR_MESSAGES, SITE_URL */
{
const queue = new wp.serviceWorker.backgroundSync.Queue( 'amp-wpPendingComments' );
const errorMessages = ERROR_MESSAGES;

const commentHandler = ( { event } ) => {
const clonedRequest = event.request.clone();
return fetch( event.request ).catch( () => {
return clonedRequest.blob().then( ( body ) => {
const queuedRequest = new Request( event.request.url, {
method: event.request.method,
headers: event.request.headers,
mode: event.request.mode,
credentials: event.request.credentials,
referrer: event.request.referrer,
redirect: 'follow',
body: body
} );

// Add request to queue.
queue.pushRequest( {
request: queuedRequest
} );

const jsonBody = JSON.stringify( { message: errorMessages.comment } );
return new Response( jsonBody, {
status: 202,
statusText: 'Accepted',
headers: {
'Access-Control-Allow-Origin': SITE_URL,
'Access-Control-Allow-Credentials': 'true',
'Content-Type': 'application/json; charset=UTF-8',
'Access-Control-Expose-Headers': 'AMP-Access-Control-Allow-Source-Origin',
'AMP-Access-Control-Allow-Source-Origin': SITE_URL,
'Cache-Control': 'no-cache, must-revalidate, max-age=0'
}
} );
} );
} );
};

wp.serviceWorker.routing.registerRoute(
/\/wp-comments-post\.php\?.*_wp_amp_action_xhr_converted.*/,
commentHandler,
'POST'
);
}
9 changes: 2 additions & 7 deletions includes/amp-app-shell-helper-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ function amp_app_shell_activate() {

/**
* Bootstrap plugin.
*
* @since 1.5
*/
function amp_app_shell_bootstrap_plugin() {
/*
Expand All @@ -36,8 +34,6 @@ function amp_app_shell_bootstrap_plugin() {

/**
* Init AMP App Shell.
*
* @since 0.1
*/
function amp_app_shell_init() {
/**
Expand All @@ -48,6 +44,8 @@ function amp_app_shell_init() {
add_filter( 'wp_redirect', [ 'AMP_App_Shell', 'purge_app_shell_query_var' ], 10, 1 );
AMP_App_Shell::purge_app_shell_query_var();

AMP_App_Shell_Service_Worker::init();

add_action( 'parse_query', [ 'AMP_App_Shell', 'init' ], 9 );
}

Expand Down Expand Up @@ -142,7 +140,6 @@ function amp_app_shell_filter_script_loader_tag( $tag, $handle ) {
*
* Depends on adding app_shell to the amp theme support args.
*
* @since 1.1
* @todo Should this take an argument for the content placeholder?
*/
function amp_start_app_shell_content() {
Expand Down Expand Up @@ -177,8 +174,6 @@ function amp_start_app_shell_content() {
* Mark the end of the content that will be displayed inside the app shell.
*
* Depends on adding app_shell to the amp theme support args.
*
* @since 1.1
*/
function amp_end_app_shell_content() {
$support_args = AMP_Theme_Support::get_theme_support_args();
Expand Down
137 changes: 137 additions & 0 deletions includes/class-amp-app-shell-service-worker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php
/**
* AMP_App_Shell_Service_Worker.
*
* @package AMP_App_Shell
*/

/**
* Class AMP_App_Shell_Service_Worker.
*/
class AMP_App_Shell_Service_Worker {

/**
* Init.
*/
public static function init() {
if ( ! class_exists( 'WP_Service_Workers' ) || ! class_exists( 'AMP_Theme_Support' ) ) {
return;
}

$theme_support = AMP_Theme_Support::get_theme_support_args();
if ( isset( $theme_support['service_worker'] ) && false === $theme_support['service_worker'] ) {
return;
}

if ( ! isset( $theme_support['app_shell'] ) ) {
return;
}

// App shell is mutually exclusive with navigation preload.
add_filter( 'wp_service_worker_navigation_preload', '__return_false' );

// Opt to route all navigation requests through the app shell.
add_filter(
'wp_service_worker_navigation_route',
function ( $navigation_route ) {
$navigation_route['url'] = add_query_arg( AMP_App_Shell::COMPONENT_QUERY_VAR, 'outer', home_url( '/' ) );
return $navigation_route;
}
);

/**
* Add the query var to designate that the inner app shell is being requested.
*
* @param array $precache_entry Precache entry.
* @return array Modified precache entry.
*/
$add_inner_app_shell_component = function( $precache_entry ) {
$precache_entry['url'] = add_query_arg(
AMP_App_Shell::COMPONENT_QUERY_VAR,
'inner',
$precache_entry['url']
);
return $precache_entry;
};
add_filter( 'wp_offline_error_precache_entry', $add_inner_app_shell_component, 100 );
add_filter( 'wp_server_error_precache_entry', $add_inner_app_shell_component, 100 );

// @todo There should be some query var that is used to disable navigation routing entirely so that there is no need to bypass for network.
// Prevent app shell from being served when requesting AMP version directly.
add_filter(
'wp_service_worker_navigation_route_blacklist_patterns',
function ( $blacklist_patterns ) {
$blacklist_patterns[] = '\?(.+&)*' . preg_quote( amp_get_slug(), '/' ) . '(=|&|$)';
return $blacklist_patterns;
}
);

// Make sure the offline template is added to list of templates in AMP.
add_filter(
'amp_supportable_templates',
function( $supportable_templates ) {
if ( ! isset( $supportable_templates['is_offline'] ) ) {
$supportable_templates['is_offline'] = [
'label' => __( 'Offline', 'amp' ),
];
}
return $supportable_templates;
},
1000
);

/*
* The default-enabled options reflect which features are not commented-out in the AMP-by-Example service worker.
* See <https://github.com/ampproject/amp-by-example/blob/e093edb401b1617859b5365e80b639d81b06f058/boilerplate-generator/templates/files/serviceworkerJs.js>.
*/
$enabled_options = [
'live_list_offline_commenting' => false,
];
if ( isset( $theme_support['service_worker'] ) && is_array( $theme_support['service_worker'] ) ) {
$enabled_options = array_merge(
$enabled_options,
$theme_support['service_worker']
);
}

if ( $enabled_options['live_list_offline_commenting'] ) {
add_action( 'wp_front_service_worker', [ __CLASS__, 'add_live_list_offline_commenting' ] );
}
}

/**
* Add live list offline commenting service worker script.
*
* @param WP_Service_Worker_Scripts $service_workers WP Service Workers object.
*/
public static function add_live_list_offline_commenting( $service_workers ) {
if ( ! ( $service_workers instanceof WP_Service_Worker_Scripts ) ) {
_doing_it_wrong( __METHOD__, esc_html__( 'Expected argument to be WP_Service_Worker_Scripts.', 'amp' ), '1.0' );
return;
}

$theme_support = AMP_Theme_Support::get_theme_support_args();
if ( empty( $theme_support['comments_live_list'] ) ) {
return;
}

$service_workers->register(
'amp-offline-commenting',
function() {
$js = file_get_contents( AMP_APP_SHELL__DIR__ . '/assets/js/amp-service-worker-offline-commenting.js' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.WP.AlternativeFunctions.file_system_read_file_get_contents
$js = preg_replace( '#/\*\s*global.+?\*/#', '', $js );
$js = str_replace(
'ERROR_MESSAGES',
wp_json_encode( wp_service_worker_get_error_messages() ),
$js
);
$js = str_replace(
'SITE_URL',
wp_json_encode( site_url() ),
$js
);
return $js;
}
);
}
}

0 comments on commit 3e814fd

Please sign in to comment.