Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
45.45% covered (danger)
45.45%
10 / 22
44.44% covered (danger)
44.44%
4 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Speed_Score_History
45.45% covered (danger)
45.45%
10 / 22
44.44% covered (danger)
44.44%
4 / 9
35.37
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 get_option_name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 latest
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 latest_scores
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 get_stale_timestamp
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 mark_stale
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 is_stale
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 push
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Speed score history after Jetpack Boost
4 *
5 * @package automattic/jetpack-boost-speed-score
6 */
7
8namespace Automattic\Jetpack\Boost_Speed_Score;
9
10use Automattic\Jetpack\Boost_Core\Lib\Transient;
11
12/**
13 * Class Speed_Score_History
14 *
15 * @package Automattic\Jetpack\Boost_Speed_Score\Lib
16 */
17class Speed_Score_History {
18    const OPTION_PREFIX       = 'jetpack_boost_speed_score_history_';
19    const STALE_TRANSIENT_KEY = 'speed_score_stale_marker';
20
21    /**
22     * Limit the number of recent records to keep.
23     */
24    const LIMIT = 20;
25
26    /**
27     * The list of history entries.
28     *
29     * @var array
30     */
31    private $entries;
32
33    /**
34     * URL of the site the speed score belongs to.
35     *
36     * @var string
37     */
38    private $url;
39
40    /**
41     * Speed_Score_History constructor.
42     *
43     * @param string $url URL of the site the speed scores belong to.
44     */
45    public function __construct( $url ) {
46        $this->url     = $url;
47        $this->entries = get_option( $this->get_option_name(), array() );
48    }
49
50    /**
51     * Determine the option_name used to store the speed score data in options table.
52     *
53     * @return string
54     */
55    private function get_option_name() {
56        return static::OPTION_PREFIX . Speed_Score_Request::generate_cache_id_from_url( $this->url );
57    }
58
59    /**
60     * Get the number of history records currently stored.
61     *
62     * @return int
63     */
64    public function count() {
65        return count( $this->entries );
66    }
67
68    /**
69     * Find the latest available speed score history record.
70     *
71     * @param int $offset Instead of receiving the last one, you can use offset to receive a slightly older speed score.
72     *
73     * @return array|null
74     */
75    public function latest( $offset = 0 ) {
76        $index = $this->count() - ( $offset + 1 );
77
78        if ( $index >= 0 ) {
79            return $this->entries[ $index ];
80        }
81
82        return null;
83    }
84
85    /**
86     * Find the latest available speed scores.
87     *
88     * @param int $offset Instead of receiving the last one, you can use offset to receive a slightly older speed score.
89     *
90     * @return array|null
91     */
92    public function latest_scores( $offset = 0 ) {
93        $index = $this->count() - ( $offset + 1 );
94
95        if ( $index >= 0 ) {
96            return $this->entries[ $index ]['scores'];
97        }
98
99        return null;
100    }
101
102    /**
103     * Get a timestamp that marks previous history stale.
104     *
105     * All speed score before this timestamp are considered stale.
106     *
107     * @return array
108     */
109    public static function get_stale_timestamp() {
110        $last_stale_marker = Transient::get( static::STALE_TRANSIENT_KEY, 0 );
111
112        // Any score that is older than 24 hours or before the last stale marker is considered stale.
113        return max( $last_stale_marker, time() - DAY_IN_SECONDS );
114    }
115
116    /**
117     * Mark previous speed score as stale.
118     *
119     * If a there were significant changes to the site, we want to mark prior speed scores as stale.
120     */
121    public static function mark_stale() {
122        Transient::set( static::STALE_TRANSIENT_KEY, time() );
123    }
124
125    /**
126     * Check if the last item in history is stale.
127     */
128    public function is_stale() {
129        $last_entry = $this->latest();
130
131        if ( ! $last_entry ) {
132            return true;
133        }
134
135        return $last_entry['timestamp'] < self::get_stale_timestamp();
136    }
137
138    /**
139     * Record a new history entry for speed scores.
140     *
141     * @param array $entry The new entry to save.
142     */
143    public function push( $entry ) {
144        $this->entries[] = $entry;
145        $this->entries   = array_slice( $this->entries, - static::LIMIT );
146        update_option( $this->get_option_name(), $this->entries, false );
147    }
148}