PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 1.9.7.9
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v1.9.7.9
3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 All 194 releases
convertkit / lib / class-convertkit-resource.php

class-convertkit-resource.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 1.9.7.9, at lib/class-convertkit-resource.php

392 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Resource class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Abstract class defining variables and functions for a ConvertKit API Resource
11 * (forms, landing pages, tags), which is stored in the WordPress option table.
12 *
13 * @since 1.9.6
14 */
15 class ConvertKit_Resource {
16
17 /**
18 * Holds the key that stores the resources in the option database table.
19 *
20 * @var string
21 */
22 public $settings_name = '';
23
24 /**
25 * The type of resource
26 *
27 * @var string
28 */
29 public $type = '';
30
31 /**
32 * The API class
33 *
34 * @var bool|ConvertKit_API
35 */
36 public $api = false;
37
38 /**
39 * The number of seconds resources are valid, before they should be
40 * fetched again from the API.
41 *
42 * @var int
43 */
44 public $cache_duration = YEAR_IN_SECONDS;
45
46 /**
47 * How often to refresh this resource through WordPress' Cron.
48 * If false, won't be refreshed through WordPress' Cron
49 * If a string, must be a value from wp_get_schedules().
50 *
51 * @since 1.9.7.4
52 *
53 * @var bool|string
54 */
55 public $wp_cron_schedule = false;
56
57 /**
58 * Holds the resources from the ConvertKit API
59 *
60 * @var WP_Error|array
61 */
62 public $resources = array();
63
64 /**
65 * Timestamp for when the resources stored in the option database table
66 * were last queried from the API.
67 *
68 * @since 1.9.7.4
69 *
70 * @var int
71 */
72 public $last_queried = 0;
73
74 /**
75 * Constructor.
76 *
77 * @since 1.9.6
78 */
79 public function __construct() {
80
81 // Initialize the API if the API Key and Secret have been defined in the Plugin Settings.
82 $settings = new ConvertKit_Settings();
83 if ( $settings->has_api_key_and_secret() ) {
84 $this->api = new ConvertKit_API(
85 $settings->get_api_key(),
86 $settings->get_api_secret(),
87 $settings->debug_enabled()
88 );
89 }
90
91 $this->init();
92
93 }
94
95 /**
96 * Initialization routine. Populate the resources array of e.g. forms, landing pages or tags,
97 * depending on whether resources are already cached, if the resources have expired etc.
98 *
99 * @since 1.9.7.4
100 */
101 public function init() {
102
103 // Get last query time and existing resources.
104 $this->last_queried = get_option( $this->settings_name . '_last_queried' );
105 $this->resources = get_option( $this->settings_name );
106
107 // If no last query time exists, refresh the resources now, which will set
108 // a last query time. This handles upgrades from < 1.9.7.4 where resources
109 // would never expire.
110 if ( ! $this->last_queried ) {
111 $this->refresh();
112 return;
113 }
114
115 // If no resources exist, refresh them now.
116 if ( ! $this->resources ) {
117 $this->refresh();
118 return;
119 }
120
121 // If the resources have expired, refresh them now.
122 if ( time() > ( $this->last_queried + $this->cache_duration ) ) {
123 $this->refresh();
124 return;
125 }
126
127 }
128
129 /**
130 * Returns all resources.
131 *
132 * @since 1.9.6
133 *
134 * @return array
135 */
136 public function get() {
137
138 return $this->resources;
139
140 }
141
142 /**
143 * Returns an individual resource by its ID.
144 *
145 * @since 1.9.7.7
146 *
147 * @param int $id Resource ID (Form, Tag, Sequence).
148 * @return mixed bool | array
149 */
150 public function get_by_id( $id ) {
151
152 foreach ( $this->get() as $resource ) {
153 // If this resource's ID matches the ID we're looking for, return it.
154 if ( $resource['id'] == $id ) { // phpcs:ignore
155 return $resource;
156 }
157 }
158
159 return false;
160
161 }
162
163
164 /**
165 * Returns a paginated subset of resources, including whether
166 * previous and next resources in the array exist.
167 *
168 * @since 1.9.7.6
169 *
170 * @param int $page Current Page.
171 * @param int $per_page Number of resources to return per page.
172 * @return array
173 */
174 public function get_paginated_subset( $page, $per_page ) {
175
176 // Calculate the maximum value for $page.
177 $total_pages = ( ( $per_page > 0 ) ? ceil( $this->count() / $per_page ) : 1 );
178
179 // If $page exceeds the total number of possible pages, reduce it.
180 if ( $page > $total_pages ) {
181 $page = $total_pages;
182 }
183
184 // If $page is less than 1, set it to 1.
185 if ( $page < 1 ) {
186 $page = 1;
187 }
188
189 return array(
190 // The subset of items based on the pagination.
191 'items' => array_slice( $this->resources, ( $page * $per_page ) - $per_page, $per_page ),
192
193 // Sanitized inputs.
194 'page' => $page,
195 'per_page' => $per_page,
196
197 // The total number of pages in the pagination.
198 'total_pages' => $total_pages,
199
200 // If the request page is lower than the total number of pages in the pagination, there's a next page.
201 'has_next_page' => ( ( $page < $total_pages ) ? true : false ),
202
203 // If the request page is higher than 1, there's a previous page.
204 'has_prev_page' => ( ( $page > 1 ) ? true : false ),
205 );
206
207 }
208
209 /**
210 * Returns the number of resources.
211 *
212 * @since 1.9.7.6
213 *
214 * @return int
215 */
216 public function count() {
217
218 return count( $this->resources );
219
220 }
221
222 /**
223 * Returns whether any resources exist in the options table.
224 *
225 * @since 1.9.6
226 *
227 * @return bool
228 */
229 public function exist() {
230
231 if ( $this->resources === false ) { // @phpstan-ignore-line.
232 return false;
233 }
234
235 if ( is_wp_error( $this->resources ) ) {
236 return false;
237 }
238
239 if ( is_null( $this->resources ) ) {
240 return false;
241 }
242
243 return ( count( $this->resources ) ? true : false );
244
245 }
246
247 /**
248 * Fetches resources (forms, landing pages or tags) from the API, storing them in the options table
249 * with a last queried timestamp.
250 *
251 * @since 1.9.6
252 *
253 * @return bool|WP_Error|array
254 */
255 public function refresh() {
256
257 // Bail if no API class was defined.
258 if ( ! $this->api ) {
259 return false;
260 }
261
262 // Fetch resources.
263 switch ( $this->type ) {
264 case 'forms':
265 $results = $this->api->get_forms();
266 break;
267
268 case 'landing_pages':
269 $results = $this->api->get_landing_pages();
270 break;
271
272 case 'tags':
273 $results = $this->api->get_tags();
274 break;
275
276 case 'sequences':
277 $results = $this->api->get_sequences();
278 break;
279
280 case 'custom_fields':
281 $results = $this->api->get_custom_fields();
282 break;
283
284 case 'posts':
285 $results = $this->api->get_all_posts();
286 break;
287
288 default:
289 $results = new WP_Error(
290 'convertkit_resource_refresh_error',
291 sprintf(
292 'Resource type %s is not supported in ConvertKit_Resource class.',
293 $this->type
294 )
295 );
296 break;
297 }
298
299 // Bail if an error occured.
300 if ( is_wp_error( $results ) ) {
301 return $results;
302 }
303
304 // Define last query time now.
305 $last_queried = time();
306
307 // Store resources and their last query timestamp in the options table.
308 // We don't use WordPress' Transients API (i.e. auto expiring options), because they're prone to being
309 // flushed by some third party "optimization" Plugins. They're also not guaranteed to remain in the options
310 // table for the amount of time specified; any expiry is a maximum, not a minimum.
311 // We don't want to keep querying the ConvertKit API for a list of e.g. forms, tags that rarely change as
312 // a result of transients not being honored, so storing them as options with a separate, persistent expiry
313 // value is more reliable here.
314 update_option( $this->settings_name, $results );
315 update_option( $this->settings_name . '_last_queried', $last_queried );
316
317 // Store resources and last queried time in class variables.
318 $this->resources = $results;
319 $this->last_queried = $last_queried;
320
321 // Return resources.
322 return $results;
323
324 }
325
326 /**
327 * Schedules a WordPress Cron event to refresh this resource based on
328 * the resource's $wp_cron_schedule.
329 *
330 * @since 1.9.7.4
331 */
332 public function schedule_cron_event() {
333
334 // Bail if no cron schedule is defined for this resource.
335 if ( ! $this->wp_cron_schedule ) {
336 return;
337 }
338
339 // Bail if the event already exists; we don't need to schedule it again.
340 if ( $this->get_cron_event() !== false ) {
341 return;
342 }
343
344 // Schedule event, starting in an hour's time and recurring for the given $wp_cron_schedule.
345 wp_schedule_event(
346 strtotime( '+1 hour' ), // Start in an hour's time.
347 $this->wp_cron_schedule, // Repeat based on the given schedule e.g. hourly.
348 'convertkit_resource_refresh_' . $this->type // Hook name; see includes/cron-functions.php for function that listens to this hook.
349 );
350
351 }
352
353 /**
354 * Unschedules a WordPress Cron event to refresh this resource.
355 *
356 * @since 1.9.7.4
357 */
358 public function unschedule_cron_event() {
359
360 wp_clear_scheduled_hook( 'convertkit_resource_refresh_' . $this->type );
361
362 }
363
364 /**
365 * Returns how often the WordPress Cron event will recur for (e.g. daily).
366 *
367 * Returns false if no schedule exists i.e. wp_schedule_event() has not been
368 * called or failed to register a scheduled event.
369 *
370 * @since 1.9.7.4
371 *
372 * @return bool|string
373 */
374 public function get_cron_event() {
375
376 return wp_get_schedule( 'convertkit_resource_refresh_' . $this->type );
377
378 }
379
380 /**
381 * Deletes resources (forms, landing pages or tags) from the options table.
382 *
383 * @since 1.9.7.8
384 */
385 public function delete() {
386
387 delete_option( $this->settings_name );
388
389 }
390
391 }
392