| 1 |
<?php |
| 2 |
/** |
| 3 |
* Cache class file. |
| 4 |
*/ |
| 5 |
|
| 6 |
// Exit if accessed directly. |
| 7 |
if ( !defined( 'ABSPATH' ) ) { |
| 8 |
exit; |
| 9 |
} |
| 10 |
|
| 11 |
|
| 12 |
/** |
| 13 |
* Initialize the class |
| 14 |
*/ |
| 15 |
|
| 16 |
new BLNOTIFIER_CACHE(); |
| 17 |
|
| 18 |
|
| 19 |
/** |
| 20 |
* Cache class. |
| 21 |
*/ |
| 22 |
class BLNOTIFIER_CACHE { |
| 23 |
|
| 24 |
/** |
| 25 |
* The table name |
| 26 |
* |
| 27 |
* @var string |
| 28 |
*/ |
| 29 |
protected $table; |
| 30 |
|
| 31 |
|
| 32 |
/** |
| 33 |
* Length of time to cache links |
| 34 |
* |
| 35 |
* @var int |
| 36 |
*/ |
| 37 |
public $cache_time_in_seconds; |
| 38 |
|
| 39 |
|
| 40 |
/** |
| 41 |
* Whether to mark (cached) at the end of the text response |
| 42 |
* |
| 43 |
* @var boolean |
| 44 |
*/ |
| 45 |
private $mark_cached_in_text = false; |
| 46 |
|
| 47 |
|
| 48 |
/** |
| 49 |
* Constructor |
| 50 |
*/ |
| 51 |
public function __construct() { |
| 52 |
|
| 53 |
$this->cache_time_in_seconds = absint( get_option( 'blnotifier_cache', 0 ) ); |
| 54 |
|
| 55 |
global $wpdb; |
| 56 |
$this->table = $wpdb->prefix . 'blnotifier_cache'; |
| 57 |
$this->maybe_create_table(); |
| 58 |
$this->maybe_cleanup_cache(); |
| 59 |
$this->maybe_delete_table_if_disabled(); |
| 60 |
|
| 61 |
} // End __construct() |
| 62 |
|
| 63 |
|
| 64 |
/** |
| 65 |
* Create the cache table if it doesn't already exist. |
| 66 |
*/ |
| 67 |
public function maybe_create_table() { |
| 68 |
if ( $this->cache_time_in_seconds === 0 ) { |
| 69 |
return; |
| 70 |
} |
| 71 |
|
| 72 |
global $wpdb; |
| 73 |
|
| 74 |
if ( $wpdb->get_var( "SHOW TABLES LIKE '{$this->table}'" ) !== $this->table ) { // phpcs:ignore |
| 75 |
require_once ABSPATH . 'wp-admin/includes/upgrade.php'; |
| 76 |
|
| 77 |
$charset_collate = $wpdb->get_charset_collate(); |
| 78 |
|
| 79 |
$sql = "CREATE TABLE {$this->table} ( |
| 80 |
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, |
| 81 |
link TEXT NOT NULL, |
| 82 |
http_code SMALLINT UNSIGNED NOT NULL, |
| 83 |
type VARCHAR(20) NOT NULL, |
| 84 |
status_text TEXT, |
| 85 |
last_checked DATETIME NOT NULL, |
| 86 |
PRIMARY KEY (id), |
| 87 |
UNIQUE KEY link_unique (link(191)) |
| 88 |
) $charset_collate;"; |
| 89 |
|
| 90 |
dbDelta( $sql ); |
| 91 |
} |
| 92 |
} // End maybe_create_table() |
| 93 |
|
| 94 |
|
| 95 |
/** |
| 96 |
* Delete the table if cache is disabled |
| 97 |
* |
| 98 |
* @return void |
| 99 |
*/ |
| 100 |
public function maybe_delete_table_if_disabled() { |
| 101 |
if ( $this->cache_time_in_seconds === 0 ) { |
| 102 |
$this->delete_cache_table(); |
| 103 |
} |
| 104 |
} // End maybe_delete_table_if_disabled() |
| 105 |
|
| 106 |
|
| 107 |
/** |
| 108 |
* Delete the cache table from the database. |
| 109 |
*/ |
| 110 |
public function delete_cache_table() { |
| 111 |
global $wpdb; |
| 112 |
|
| 113 |
$wpdb->query( "DROP TABLE IF EXISTS {$this->table}" ); // phpcs:ignore |
| 114 |
} // End delete_cache_table() |
| 115 |
|
| 116 |
|
| 117 |
/** |
| 118 |
* Remove expired cache entries older than 8 hours. |
| 119 |
*/ |
| 120 |
public function maybe_cleanup_cache() { |
| 121 |
if ( $this->cache_time_in_seconds === 0 ) { |
| 122 |
return; |
| 123 |
} |
| 124 |
|
| 125 |
global $wpdb; |
| 126 |
|
| 127 |
$expiration_time = gmdate( 'Y-m-d H:i:s', time() - $this->cache_time_in_seconds ); |
| 128 |
|
| 129 |
$wpdb->query( $wpdb->prepare( // phpcs:ignore |
| 130 |
"DELETE FROM {$this->table} WHERE last_checked < %s", |
| 131 |
$expiration_time |
| 132 |
) ); |
| 133 |
} // End maybe_cleanup_cache() |
| 134 |
|
| 135 |
|
| 136 |
/** |
| 137 |
* Retrieve a cached link if it's still valid. |
| 138 |
* |
| 139 |
* @param string $link The URL to look up. |
| 140 |
* @return array|false The cached status or false if not found or expired. |
| 141 |
*/ |
| 142 |
public function get_cached_link( $link ) { |
| 143 |
if ( $this->cache_time_in_seconds === 0 ) { |
| 144 |
return false; |
| 145 |
} |
| 146 |
|
| 147 |
global $wpdb; |
| 148 |
|
| 149 |
$row = $wpdb->get_row( $wpdb->prepare( // phpcs:ignore |
| 150 |
"SELECT * FROM {$this->table} WHERE link = %s AND last_checked >= %s LIMIT 1", |
| 151 |
$link, |
| 152 |
gmdate( 'Y-m-d H:i:s', time() - $this->cache_time_in_seconds ) |
| 153 |
), ARRAY_A ); |
| 154 |
|
| 155 |
if ( $row ) { |
| 156 |
$mark_cached = $this->mark_cached_in_text ? ' (cached)' : ''; |
| 157 |
return [ |
| 158 |
'type' => $row[ 'type' ], |
| 159 |
'code' => (int) $row[ 'http_code' ], |
| 160 |
'text' => $row[ 'status_text' ] . $mark_cached, |
| 161 |
'link' => $row[ 'link' ] |
| 162 |
]; |
| 163 |
} |
| 164 |
|
| 165 |
return false; |
| 166 |
} // End get_cached_link() |
| 167 |
|
| 168 |
|
| 169 |
/** |
| 170 |
* Store a link in the cache if it's good (not broken or warning). |
| 171 |
* |
| 172 |
* @param array $status The link status array. |
| 173 |
*/ |
| 174 |
public function set_cached_link( $status ) { |
| 175 |
if ( $this->cache_time_in_seconds === 0 ) { |
| 176 |
return; |
| 177 |
} |
| 178 |
|
| 179 |
if ( ! is_array( $status ) || ! isset( $status[ 'type' ], $status[ 'code' ], $status[ 'text' ], $status[ 'link' ] ) ) { |
| 180 |
return; |
| 181 |
} |
| 182 |
|
| 183 |
if ( in_array( $status[ 'type' ], [ 'broken', 'warning' ], true ) ) { |
| 184 |
return; |
| 185 |
} |
| 186 |
|
| 187 |
global $wpdb; |
| 188 |
|
| 189 |
$wpdb->replace( // phpcs:ignore |
| 190 |
$this->table, |
| 191 |
[ |
| 192 |
'link' => $status[ 'link' ], |
| 193 |
'http_code' => absint( $status[ 'code' ] ), |
| 194 |
'type' => sanitize_text_field( $status[ 'type' ] ), |
| 195 |
'status_text' => sanitize_text_field( $status[ 'text' ] ), |
| 196 |
'last_checked' => current_time( 'mysql', 1 ) |
| 197 |
], |
| 198 |
[ |
| 199 |
'%s', |
| 200 |
'%d', |
| 201 |
'%s', |
| 202 |
'%s', |
| 203 |
'%s' |
| 204 |
] |
| 205 |
); |
| 206 |
} // End set_cached_link() |
| 207 |
|
| 208 |
} |