Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
Expiry_Wpcom
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
2 / 2
8
100.00% covered (success)
100.00%
1 / 1
 remember
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 get_as_blog
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * Expiry_Wpcom: what the expiry notices ask WordPress.com, and remember.
4 *
5 * @package automattic/jetpack-mu-wpcom
6 */
7
8declare( strict_types = 1 );
9
10namespace Automattic\Jetpack\Jetpack_Mu_Wpcom\Expiry_Notices;
11
12use Automattic\Jetpack\Connection\Client;
13
14/**
15 * Every lookup here runs during a page load, so an answer is kept for hours
16 * and a failure for minutes: long enough not to retry an outage on every
17 * pageview, short enough not to hide a fact for half a day over one blip.
18 */
19class Expiry_Wpcom {
20
21    const CACHE_TTL   = 12 * HOUR_IN_SECONDS;
22    const FAILURE_TTL = 5 * MINUTE_IN_SECONDS;
23
24    // Stored in place of an answer so a failed lookup is remembered too.
25    const NONE = 'none';
26
27    /**
28     * The remembered answer to a lookup, asking it once per cache period.
29     *
30     * @param string   $cache_key Transient name.
31     * @param callable $lookup    Returns the answer, or null when it could not be established.
32     * @return string|null
33     */
34    public static function remember( string $cache_key, callable $lookup ): ?string {
35        $cached = get_transient( $cache_key );
36        if ( false !== $cached ) {
37            return self::NONE === $cached ? null : (string) $cached;
38        }
39
40        $value = $lookup();
41        set_transient( $cache_key, $value ?? self::NONE, null === $value ? self::FAILURE_TTL : self::CACHE_TTL );
42        return $value;
43    }
44
45    /**
46     * GET a REST v1.2 path with the site's blog token, decoded, or null on any failure.
47     *
48     * @param string $path Path under the REST base; `%d` stands for the site's WordPress.com ID.
49     * @return mixed Decoded JSON body, or null.
50     */
51    public static function get_as_blog( string $path ) {
52        $site_id = \Jetpack_Options::get_option( 'id' );
53        if ( ! $site_id ) {
54            return null;
55        }
56
57        $response = Client::wpcom_json_api_request_as_blog(
58            sprintf( $path, (int) $site_id ),
59            '1.2',
60            array(
61                'method'  => 'GET',
62                // A slow answer must not become a slow page.
63                'timeout' => 5,
64            ),
65            null,
66            'rest'
67        );
68
69        if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
70            return null;
71        }
72
73        return json_decode( wp_remote_retrieve_body( $response ) );
74    }
75}