Skip to content

Commit

Permalink
Rename CachedData to CacheResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
pierlon committed Apr 2, 2020
1 parent 78b7bcd commit 83a14b3
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 127 deletions.
71 changes: 0 additions & 71 deletions src/RemoteRequest/CachedData.php

This file was deleted.

29 changes: 13 additions & 16 deletions src/RemoteRequest/CachedRemoteGetRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class CachedRemoteGetRequest implements RemoteGetRequest {
*
* @var string
*/
const TRANSIENT_PREFIX = 'amp_remote_request_';
const TRANSIENT_PREFIX = 'amp_remote_request_v2_';

/**
* Cache control header directive name.
Expand Down Expand Up @@ -102,24 +102,23 @@ public function __construct(
*
* @param string $url URL to get.
* @return Response Response for the executed request.
* @throws FailedToGetFromRemoteUrl If retrieving the contents from the URL failed.
* @throws FailedToGetCachedResponseData If retrieving the contents from the cache failed.
* @throws FailedToGetFromRemoteUrl|FailedToGetCachedResponseData If retrieving the contents from the reponse failed.
*/
public function get( $url ) {
$cache_key = self::TRANSIENT_PREFIX . md5( __CLASS__ . $url );
$cached_data = get_transient( $cache_key );
$headers = [];
$cache_key = self::TRANSIENT_PREFIX . md5( __CLASS__ . $url );
$cached_response = get_transient( $cache_key );
$headers = [];

if ( false !== $cached_data ) {
if ( false !== $cached_response ) {
if ( PHP_MAJOR_VERSION >= 7 ) {
$cached_data = unserialize( $cached_data, [ CachedData::class, DateTimeImmutable::class ] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize,PHPCompatibility.FunctionUse.NewFunctionParameters.unserialize_optionsFound
$cached_response = unserialize( $cached_response, [ CachedResponse::class, DateTimeImmutable::class ] ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize,PHPCompatibility.FunctionUse.NewFunctionParameters.unserialize_optionsFound
} else {
// PHP 5.6 does not provide the second $options argument yet.
$cached_data = unserialize( $cached_data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
$cached_response = unserialize( $cached_response ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
}
}

if ( false === $cached_data || $cached_data->is_expired() ) {
if ( false === $cached_response || $cached_response->is_expired() ) {
try {
$response = $this->remote_request->get( $url );
$status = $response->getStatusCode();
Expand All @@ -133,20 +132,18 @@ public function get( $url ) {
$response = new RemoteGetRequestResponse( $body, $headers, $status );
}

$cached_data = new CachedData( compact( 'body', 'status', 'headers' ), $expiry );
$cached_response = new CachedResponse( $body, $headers, $status, $expiry );

set_transient( $cache_key, serialize( $cached_data ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
set_transient( $cache_key, serialize( $cached_response ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize

return $response;
}

$cached_value = $cached_data->get_value();

if ( ! isset( $cached_value['body'], $cached_value['headers'], $cached_value['status'] ) ) {
if ( ! $cached_response->is_valid() ) {
throw new FailedToGetCachedResponseData( $url );
}

return new RemoteGetRequestResponse( $cached_value['body'], $cached_value['headers'], $cached_value['status'] );
return new RemoteGetRequestResponse( $cached_response->get_body(), $cached_response->get_headers(), $cached_response->get_status_code() );
}

/**
Expand Down
117 changes: 117 additions & 0 deletions src/RemoteRequest/CachedResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php
/**
* Class CachedResponse.
*
* @package AmpProject\AmpWP
*/

namespace AmpProject\AmpWP\RemoteRequest;

use DateTimeImmutable;
use DateTimeInterface;

/**
* Serializable object that represents a cached response together with its expiry time.
*
* @package AmpProject\AmpWP
*/
final class CachedResponse {

/**
* Cached body.
*
* @var string
*/
private $body;

/**
* Cached headers.
*
* @var array
*/
private $headers;

/**
* Cached status code.
*
* @var int
*/
private $status_code;

/**
* Expiry time of the cached value.
*
* @var DateTimeInterface
*/
private $expiry;

/**
* Instantiate a CachedResponse object.
*
* @param string $body Cached body.
* @param array $headers Cached headers.
* @param int $status_code Cached status code.
* @param DateTimeInterface $expiry Expiry of the cached value.
*/
public function __construct( $body, array $headers, $status_code, DateTimeInterface $expiry ) {
$this->body = $body;
$this->headers = $headers;
$this->status_code = $status_code;
$this->expiry = $expiry;
}

/**
* Get the cached body.
*
* @return string Cached body.
*/
public function get_body() {
return $this->body;
}

/**
* Get the cached headers.
*
* @return array Cached headers.
*/
public function get_headers() {
return $this->headers;
}

/**
* Get the cached status code.
*
* @return int Cached status code.
*/
public function get_status_code() {
return $this->status_code;
}

/**
* Determine the validity of the cached response.
*
* @return bool Whether the cached response if valid.
*/
public function is_valid() {
// $this->headers is typed so no need for sanity check.
return null !== $this->body && is_int( $this->status_code );
}

/**
* Get the expiry of the cached value.
*
* @return DateTimeInterface Expiry of the cached value.
*/
public function get_expiry() {
return $this->expiry;
}

/**
* Check whether the cached value is expired.
*
* @return bool Whether the cached value is expired.
*/
public function is_expired() {
return new DateTimeImmutable( 'now' ) > $this->expiry;
}
}
73 changes: 33 additions & 40 deletions tests/php/test-amp-style-sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// phpcs:disable WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned

use AmpProject\AmpWP\RemoteRequest\CachedData;
use AmpProject\AmpWP\RemoteRequest\CachedResponse;
use AmpProject\AmpWP\RemoteRequest\CachedRemoteGetRequest;
use AmpProject\AmpWP\Tests\AssertContainsCompatibility;
use AmpProject\Dom\Document;
Expand Down Expand Up @@ -1647,23 +1647,18 @@ function( $preempt, $request, $url ) use ( $href, &$request_count, $response_bod
$this->assertNotFalse( $transient );

/**
* Cached data.
* Cached response.
*
* @var CachedData
* @var CachedResponse
*/
$cached_data = unserialize( $transient ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
$this->assertInstanceOf( CachedData::class, $cached_data );
$cached_response = unserialize( $transient ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
$this->assertInstanceOf( CachedResponse::class, $cached_response );

$this->assertEquals(
[
'body' => $response_body,
'headers' => $headers,
'status' => $status_code,
],
$cached_data->get_value()
);
$this->assertEquals( $response_body, $cached_response->get_body() );
$this->assertEquals( $headers, $cached_response->get_headers() );
$this->assertEquals( $status_code, $cached_response->get_status_code() );

$expiry = $cached_data->get_expiry();
$expiry = $cached_response->get_expiry();
$this->assertGreaterThan( ( new DateTimeImmutable( '+ 1 year' ) )->getTimestamp(), $expiry->getTimestamp() );

$sanitize_and_get_stylesheets();
Expand All @@ -1689,15 +1684,13 @@ public function get_external_stylesheet_data() {
],
'expected_styles' => [ 'body{color:#fff}' ],
'expected_errors' => [],
'cached_data' => new CachedData(
'cached_data' => new CachedResponse(
'body { color: #fff }',
[
'body' => 'body { color: #fff }',
'headers' => [
'cache-control' => 'max-age=1441',
'content-type' => 'text/css',
],
'status' => 200,
'cache-control' => 'max-age=1441',
'content-type' => 'text/css',
],
200,
new DateTimeImmutable( '+ 1441 seconds' )
),
],
Expand All @@ -1712,12 +1705,10 @@ public function get_external_stylesheet_data() {
],
'expected_styles' => [],
'expected_errors' => [ AMP_Style_Sanitizer::STYLESHEET_FETCH_ERROR ],
'cached_data' => new CachedData(
[
'body' => FailedToGetFromRemoteUrl::withHttpStatus( 'https://www.example.com/not-found/styles.css', 404 )->getMessage(),
'headers' => [],
'status' => 404,
],
'cached_data' => new CachedResponse(
FailedToGetFromRemoteUrl::withHttpStatus( 'https://www.example.com/not-found/styles.css', 404 )->getMessage(),
[],
404,
new DateTimeImmutable( '+ ' . DAY_IN_SECONDS . ' seconds' )
),
],
Expand All @@ -1730,13 +1721,13 @@ public function get_external_stylesheet_data() {
* @dataProvider get_external_stylesheet_data
* @covers AMP_Style_Sanitizer::process_link_element()
*
* @param string $style_url Stylesheet URL.
* @param array $http_response Mocked HTTP response.
* @param array $expected_styles Expected minified stylesheets.
* @param array $expected_errors Expected error codes.
* @param CachedData $expected_cached_data Expected cache data.
* @param string $style_url Stylesheet URL.
* @param array $http_response Mocked HTTP response.
* @param array $expected_styles Expected minified stylesheets.
* @param array $expected_errors Expected error codes.
* @param CachedResponse $expected_cached_response Expected cache response.
*/
public function test_external_stylesheet( $style_url, $http_response, $expected_styles, $expected_errors, $expected_cached_data ) {
public function test_external_stylesheet( $style_url, $http_response, $expected_styles, $expected_errors, $expected_cached_response ) {
$request_count = 0;

add_filter(
Expand Down Expand Up @@ -1792,17 +1783,19 @@ function( $preempt, $request, $url ) use ( $style_url, $http_response, &$request
$this->assertNotFalse( $transient );

/**
* Cached data.
* Cached response.
*
* @var CachedData
* @var CachedResponse
*/
$cached_data = unserialize( $transient ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
$this->assertInstanceOf( CachedData::class, $cached_data );
$cached_response = unserialize( $transient ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
$this->assertInstanceOf( CachedResponse::class, $cached_response );

$this->assertEquals( $expected_cached_data->get_value(), $cached_data->get_value() );
$this->assertEquals( $expected_cached_response->get_body(), $cached_response->get_body() );
$this->assertEquals( $expected_cached_response->get_headers(), $cached_response->get_headers() );
$this->assertEquals( $expected_cached_response->get_status_code(), $cached_response->get_status_code() );

$expiry = $cached_data->get_expiry();
$this->assertEquals( $cached_data->get_expiry()->getTimestamp(), $expiry->getTimestamp() );
$expiry = $cached_response->get_expiry();
$this->assertEquals( $cached_response->get_expiry()->getTimestamp(), $expiry->getTimestamp() );

$sanitize_and_get_stylesheets( $style_url );
$this->assertEquals( 1, $request_count, 'Expected HTTP request to be cached.' );
Expand Down

0 comments on commit 83a14b3

Please sign in to comment.