• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / d0576c9d7b9d3bb14e757d43db2e5deceb39bba3

27 Oct 2025 12:02PM UTC coverage: 52.599% (-0.09%) from 52.692%
d0576c9d7b9d3bb14e757d43db2e5deceb39bba3

Pull #22675

github

web-flow
Merge 4c38ba824 into 337402506
Pull Request #22675: 804 add caching

8147 of 15270 branches covered (53.35%)

Branch coverage included in aggregate %.

0 of 146 new or added lines in 5 files covered. (0.0%)

56 existing lines in 2 files now uncovered.

31468 of 60045 relevant lines covered (52.41%)

39772.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/nlweb/schema-aggregator/application/cache/manager.php
1
<?php
2

3
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4
// phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
5
namespace Yoast\WP\SEO\Nlweb\Schema_Aggregator\Application\Cache;
6

7
use Exception;
8
use Yoast\WP\SEO\Nlweb\Schema_Aggregator\Infrastructure\Config;
9

10
/**
11
 * Cache manager
12
 *
13
 * Manages cache storage/retrieval/invalidation using WordPress Transients API.
14
 */
15
class Manager {
16
        /**
17
         * Cache key prefix
18
         *
19
         * @var string
20
         */
21
        private const CACHE_PREFIX = 'yoast_nlweb_schema';
22

23
        /**
24
         * Cache version for invalidation
25
         *
26
         * @var int
27
         */
28
        private const CACHE_VERSION = 1;
29

30
        /**
31
         * Configuration provider
32
         *
33
         * @var Config
34
         */
35
        private $config;
36

37
        /**
38
         * Constructor
39
         *
40
         * @param Config $config Configuration provider.
41
         */
NEW
42
        public function __construct( Config $config ) {
×
NEW
43
                $this->config = $config;
×
44
        }
45

46
        /**
47
         * Get cached data for a page
48
         *
49
         * @param int $page     Page number.
50
         * @param int $per_page Items per page.
51
         *
52
         * @return array<string>|null Cached data or null.
53
         */
NEW
54
        public function get( int $page, int $per_page ): ?array {
×
55
                try {
NEW
56
                        if ( ! $this->config->cache_enabled() ) {
×
NEW
57
                                return null;
×
58
                        }
NEW
59
                        if ( $page < 1 || $per_page < 1 ) {
×
NEW
60
                                return null;
×
61
                        }
62

NEW
63
                        $key = $this->get_cache_key( $page, $per_page );
×
64

NEW
65
                        $data = \get_transient( $key );
×
66

NEW
67
                        if ( $data === false ) {
×
NEW
68
                                return null;
×
69
                        }
NEW
70
                        if ( ! \is_array( $data ) ) {
×
NEW
71
                                \delete_transient( $key );
×
72

NEW
73
                                return null;
×
74
                        }
75

NEW
76
                        return $data;
×
77

NEW
78
                } catch ( Exception $e ) {
×
NEW
79
                        return null;
×
80
                }
81
        }
82

83
        /**
84
         * Set cache data for a page
85
         *
86
         * @param int           $page     Page number.
87
         * @param int           $per_page Items per page.
88
         * @param array<string> $data     Data to cache.
89
         *
90
         * @return bool Success.
91
         */
NEW
92
        public function set( int $page, int $per_page, array $data ): bool {
×
93
                try {
NEW
94
                        if ( $page < 1 || $per_page < 1 || ! \is_array( $data ) ) {
×
NEW
95
                                return false;
×
96
                        }
97

NEW
98
                        $key        = $this->get_cache_key( $page, $per_page );
×
NEW
99
                        $expiration = $this->config->get_expiration( $data );
×
100

NEW
101
                        return \set_transient( $key, $data, $expiration );
×
102

NEW
103
                } catch ( Exception $e ) {
×
NEW
104
                        return false;
×
105
                }
106
        }
107

108
        /**
109
         * Invalidate cache for specific page/per_page combination or all pages
110
         *
111
         * Note: When invalidating a specific page without per_page, this clears
112
         * ALL per_page variations for that page using a wildcard pattern.
113
         *
114
         * @param int|null $page     Page number or null for all.
115
         * @param int|null $per_page Items per page or null to clear all per_page variations.
116
         *
117
         * @return bool Success.
118
         */
NEW
119
        public function invalidate( ?int $page = null, ?int $per_page = null ): bool {
×
NEW
120
                if ( $page !== null && $per_page !== null ) {
×
121
                        // Clear specific page/per_page combination.
NEW
122
                        return \delete_transient( $this->get_cache_key( $page, $per_page ) );
×
123
                }
124

NEW
125
                if ( $page !== null && $per_page === null ) {
×
126
                        // Clear all per_page variations for this page.
NEW
127
                        global $wpdb;
×
128

NEW
129
                        if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) {
×
NEW
130
                                return false;
×
131
                        }
132

NEW
133
                        $pattern         = '_transient_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%';
×
NEW
134
                        $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_' . $page . '_per_%';
×
135
                        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
NEW
136
                        $deleted = $wpdb->query(
×
NEW
137
                                $wpdb->prepare(
×
NEW
138
                                        "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
×
NEW
139
                                        $pattern,
×
NEW
140
                                        $timeout_pattern
×
NEW
141
                                )
×
NEW
142
                        );
×
143

NEW
144
                        return $deleted !== false;
×
145
                }
NEW
146
                return $this->invalidate_all();
×
147
        }
148

149
        /**
150
         * Invalidate all cache pages
151
         *
152
         * @return bool Success.
153
         */
NEW
154
        public function invalidate_all(): bool {
×
155
                try {
NEW
156
                        global $wpdb;
×
157

NEW
158
                        if ( ! isset( $wpdb ) || ! \is_object( $wpdb ) ) {
×
NEW
159
                                return false;
×
160
                        }
161

162
                        // Pattern matches: yoast_nlweb_schema_page_{n}_per_{m}_v{version}.
NEW
163
                        $pattern         = '_transient_' . self::CACHE_PREFIX . '_page_%';
×
NEW
164
                        $timeout_pattern = '_transient_timeout_' . self::CACHE_PREFIX . '_page_%';
×
165
                        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
NEW
166
                        $deleted = $wpdb->query(
×
NEW
167
                                $wpdb->prepare(
×
NEW
168
                                        "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s",
×
NEW
169
                                        $pattern,
×
NEW
170
                                        $timeout_pattern
×
NEW
171
                                )
×
NEW
172
                        );
×
173

NEW
174
                        if ( $deleted === false ) {
×
NEW
175
                                return false;
×
176
                        }
177

NEW
178
                        return true;
×
179

NEW
180
                } catch ( Exception $e ) {
×
181

NEW
182
                        return false;
×
183
                }
184
        }
185

186
        /**
187
         * Generate cache key for page.
188
         *
189
         * @param int $page     Page number.
190
         * @param int $per_page Items per page.
191
         *
192
         * @return string Cache key.
193
         */
NEW
194
        private function get_cache_key( int $page, int $per_page ): string {
×
NEW
195
                return \sprintf(
×
NEW
196
                        '%s_page_%d_per_%d_v%d',
×
NEW
197
                        self::CACHE_PREFIX,
×
NEW
198
                        $page,
×
NEW
199
                        $per_page,
×
NEW
200
                        self::CACHE_VERSION
×
NEW
201
                );
×
202
        }
203
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc