Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions amp/homepage-articles/view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
let isFetching = false;
let isEndOfData = false;
buildLoadMoreHandler( document.querySelector( '.wp-block-newspack-blocks-homepage-articles') );
function buildLoadMoreHandler( blockWrapperEl ) {
const btnEl = blockWrapperEl.querySelector( '[data-next]' );
if ( ! btnEl ) {
return;
}
const postsContainerEl = blockWrapperEl.querySelector( '[data-posts]' );
btnEl.addEventListener( 'click', function( e ) {
if ( isFetching || isEndOfData ) {
return false;
}
isFetching = true;
blockWrapperEl.classList.remove( 'is-error' );
blockWrapperEl.classList.add( 'is-loading' );
AMP.getState( 'newspackHomepagePosts.exclude_ids' ).then( function( exclude_ids ) {
const requestURL = new URL( btnEl.getAttribute( 'data-next' ) );
requestURL.searchParams.set( 'exclude_ids', JSON.parse( exclude_ids ).join( ',' ) );
apiFetchWithRetry( { url: requestURL.toString(), onSuccess, onError }, 3 );
} );
function onSuccess( data ) {
AMP.getState( 'newspackHomepagePosts.exclude_ids' ).then( function( exclude_ids ) {
AMP.setState( {
newspackHomepagePosts: { exclude_ids: JSON.parse( exclude_ids ).concat( data.ids ) },
} );
} );
if ( isPostsDataValid( data ) ) {
const postsHTML = data.items.map( item => item.html ).join( '' );
const ampLayout = document.createElement( 'amp-layout' );
ampLayout.innerHTML = postsHTML;
postsContainerEl.appendChild( ampLayout );
if ( data.next ) {
btnEl.setAttribute( 'data-next', data.next );
}
if ( ! data.items.length || ! data.next ) {
isEndOfData = true;
blockWrapperEl.classList.remove( 'has-more-button' );
}
isFetching = false;
blockWrapperEl.classList.remove( 'is-loading' );
}
};
function onError() {
isFetching = false;
blockWrapperEl.classList.remove( 'is-loading' );
blockWrapperEl.classList.add( 'is-error' );
}
} );
}
function apiFetchWithRetry( options, n ) {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if ( xhr.readyState !== 4 || n === 0 ) {
return;
}
if ( xhr.status >= 200 && xhr.status < 300 ) {
const data = JSON.parse( xhr.responseText );
options.onSuccess( data );
return;
}
options.onError();
apiFetchWithRetry( options, n - 1 );
};
xhr.open( 'GET', options.url );
xhr.send();
}
function isPostsDataValid( data ) {
if (
data &&
hasOwnProp( data, 'items' ) &&
hasOwnProp( data, 'next' ) &&
Array.isArray( data.items ) &&
data.items.length &&
hasOwnProp( data.items[ 0 ], 'html' ) &&
typeof data.items[ 0 ].html === 'string'
) {
return true;
}

return false;
}
function hasOwnProp( obj, prop ) {
return Object.prototype.hasOwnProperty.call( obj, prop );
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,24 @@ public function get_items( $request ) {

// Defaults.
$items = [];
$ids = [];
$next_url = '';

// The Loop.
while ( $article_query->have_posts() ) {
$article_query->the_post();
$items[]['html'] = Newspack_Blocks::template_inc(
$html = Newspack_Blocks::template_inc(
__DIR__ . '/templates/article.php',
[
'attributes' => $attributes,
]
);

if ( $request->get_param( 'amp' ) ) {
$html = $this->generate_amp_partial( $html );
}
$items[]['html'] = $html;
$ids[] = get_the_ID();
}

// Provide next URL if there are more pages.
Expand All @@ -95,11 +102,14 @@ public function get_items( $request ) {
array_merge(
array_map(
function( $attribute ) {
return false === $attribute ? '0' : $attribute;
return false === $attribute ? '0' : str_replace( '#', '%23', $attribute );
},
$attributes
),
[ 'page' => $next_page ] // phpcs:ignore PHPCompatibility.Syntax.NewShortArray.Found
[
'page' => $next_page,
'amp' => $request->get_param( 'amp' ),
]
),
rest_url( '/newspack-blocks/v1/articles' )
);
Expand All @@ -108,6 +118,7 @@ function( $attribute ) {
return rest_ensure_response(
[
'items' => $items,
'ids' => $ids,
'next' => $next_url,
]
);
Expand Down Expand Up @@ -140,4 +151,27 @@ public function get_attribute_schema() {
}
return $this->attribute_schema;
}

/**
* Use AMP Plugin functions to render markup as valid AMP.
*
* @param string $html Markup to convert to AMP.
* @return string
*/
public function generate_amp_partial( $html ) {
$dom = AMP_DOM_Utils::get_dom_from_content( $html );

AMP_Content_Sanitizer::sanitize_document(
$dom,
amp_get_content_sanitizers(),
[
'use_document_element' => false,
]
);
$xpath = new DOMXPath( $dom );
foreach ( iterator_to_array( $xpath->query( '//noscript | //comment()' ) ) as $node ) {
$node->parentNode->removeChild( $node ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
}
return AMP_DOM_Utils::get_content_from_dom( $dom );
}
}
1 change: 0 additions & 1 deletion src/blocks/homepage-articles/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ class Edit extends Component {
label={ __( 'Show "More" Button', 'newspack-blocks' ) }
checked={ moreButton }
onChange={ () => setAttributes( { moreButton: ! moreButton } ) }
help={ __( 'Only available for non-AMP requests.', 'newspack-blocks' ) }
/>
) }
</PanelBody>
Expand Down
61 changes: 41 additions & 20 deletions src/blocks/homepage-articles/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,18 @@ function newspack_blocks_render_block_homepage_articles( $attributes ) {
if ( '' !== $attributes['customTextColor'] ) {
$styles = 'color: ' . $attributes['customTextColor'] . ';';
}

$articles_rest_url = add_query_arg(
array_merge(
array_map(
function( $attribute ) {
return false === $attribute ? '0' : $attribute;
return false === $attribute ? '0' : str_replace( '#', '%23', $attribute );
},
$attributes
),
[ 'page' => 2 ]
[
'page' => 2,
'amp' => Newspack_Blocks::is_amp(),
]
),
rest_url( '/newspack-blocks/v1/articles' )
);
Expand All @@ -78,7 +80,7 @@ function( $attribute ) {

$has_more_pages = ( ++$page ) <= $article_query->max_num_pages;

$has_more_button = ! Newspack_Blocks::is_amp() && $has_more_pages && boolval( $attributes['moreButton'] );
$has_more_button = $has_more_pages && boolval( $attributes['moreButton'] );

if ( $has_more_button ) {
$classes .= ' has-more-button';
Expand All @@ -87,6 +89,9 @@ function( $attribute ) {
ob_start();

if ( $article_query->have_posts() ) : ?>
<?php if ( $has_more_button && Newspack_Blocks::is_amp() ) : ?>
<amp-script layout="container" src="<?php echo esc_url( plugins_url( '/newspack-blocks/amp/homepage-articles/view.js' ) ); ?>">
<?php endif; ?>
<div
class="<?php echo esc_attr( $classes ); ?>"
style="<?php echo esc_attr( $styles ); ?>"
Expand All @@ -98,13 +103,6 @@ class="<?php echo esc_attr( $classes ); ?>"
</h2>
<?php endif; ?>
<?php

/*
* We are not using an AMP-based renderer on AMP requests because it has limitations
* around dynamically calculating the height of the the article list on load.
* As a result we render the same standards-based markup for all requests.
*/

echo Newspack_Blocks::template_inc(
__DIR__ . '/templates/articles-list.php',
[
Expand All @@ -117,15 +115,6 @@ class="<?php echo esc_attr( $classes ); ?>"
</div>
<?php

/*
* AMP-requests cannot contain client-side scripting (eg: JavaScript). As a result
* we do not display the "More" button on AMP-requests. This feature is deliberately
* disabled.
*
* @see https://github.com/Automattic/newspack-blocks/pull/226#issuecomment-558695909
* @see https://wp.me/paYJgx-jW
*/

if ( $has_more_button ) :
?>
<button type="button" data-next="<?php echo esc_url( $articles_rest_url ); ?>">
Expand All @@ -143,9 +132,13 @@ class="<?php echo esc_attr( $classes ); ?>"
<p class="error">
<?php _e( 'Something went wrong. Please refresh the page and/or try again.', 'newspack-blocks' ); ?>
</p>

<?php endif; ?>

</div>
<?php if ( $has_more_button && Newspack_Blocks::is_amp() ) : ?>
</amp-script>
<?php endif; ?>
<?php
endif;

Expand Down Expand Up @@ -235,3 +228,31 @@ function ( $accumulator, $author ) use ( $author_info, &$index ) {

return implode( '', $elements );
}


/**
* Inject amp-state containing all post IDs visible on page load.
*/
function newspack_blocks_inject_amp_state() {
if ( ! Newspack_Blocks::is_amp() ) {
return;
}
global $newspack_blocks_post_id;
if ( ! $newspack_blocks_post_id || ! count( $newspack_blocks_post_id ) ) {
return;
}
$post_ids = implode( ', ', array_keys( $newspack_blocks_post_id ) );
ob_start();
?>
<amp-state id='newspackHomepagePosts'>
<script type="application/json">
{
"exclude_ids": [ <?php echo esc_attr( $post_ids ); ?> ]
}
</script>
</amp-state>
<?php
echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}

add_action( 'wp_footer', 'newspack_blocks_inject_amp_state' );
Loading