Skip to content

Commit d20b584

Browse files
committed
Add updater diagnostics and improve updater cache
Add a self-update diagnostics card to the Diagnostics page that queries the GitHub releases API and displays installed vs latest version, cache/transient status, download URL and API response info. Refactor Updater to use a version-scoped cache key (workos_wp_update_<md5>) and delete the legacy workos_wp_update_check transient during registration. Ensure update/no_update arrays exist on the WP transient, avoid bailing when the "checked" array is empty, remove the plugin from no_update when an update is available, and bypass/delete the cache for forced checks (e.g. ?force-check or DOING_CRON). Also bump plugin version to 1.1.3.
1 parent 7c3503f commit d20b584

3 files changed

Lines changed: 188 additions & 13 deletions

File tree

includes/Plugin.php

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,161 @@ private function render_diagnostics(): void {
19941994
</tbody>
19951995
</table>
19961996
</div>
1997+
1998+
<?php $this->render_updater_diagnostics(); ?>
1999+
<?php
2000+
}
2001+
2002+
/**
2003+
* Render self-update diagnostics card on the Diagnostics page.
2004+
*/
2005+
private function render_updater_diagnostics(): void {
2006+
$github_repo = 'AlwaysCuriousCo/workos-for-wordpress';
2007+
$api_url = "https://api.github.com/repos/{$github_repo}/releases/latest";
2008+
$current_version = WORKOS_WP_VERSION;
2009+
$plugin_slug = plugin_basename(WORKOS_WP_PLUGIN_FILE);
2010+
2011+
// Fetch from GitHub directly (no cache).
2012+
$response = wp_remote_get($api_url, [
2013+
'headers' => [
2014+
'Accept' => 'application/vnd.github.v3+json',
2015+
'User-Agent' => 'WorkOS-WordPress-Plugin/' . $current_version,
2016+
],
2017+
'timeout' => 10,
2018+
]);
2019+
2020+
$github_ok = false;
2021+
$github_error = '';
2022+
$remote_version = '';
2023+
$zip_url = '';
2024+
$http_code = 0;
2025+
2026+
if (is_wp_error($response)) {
2027+
$github_error = $response->get_error_message();
2028+
} else {
2029+
$http_code = wp_remote_retrieve_response_code($response);
2030+
if ($http_code !== 200) {
2031+
$github_error = sprintf('HTTP %d', $http_code);
2032+
} else {
2033+
$body = json_decode(wp_remote_retrieve_body($response), true);
2034+
if (!empty($body['tag_name'])) {
2035+
$github_ok = true;
2036+
$remote_version = ltrim($body['tag_name'], 'v');
2037+
// Find zip asset.
2038+
foreach ($body['assets'] ?? [] as $asset) {
2039+
if (str_starts_with($asset['name'], 'workos-for-wordpress') && str_ends_with($asset['name'], '.zip')) {
2040+
$zip_url = $asset['browser_download_url'];
2041+
break;
2042+
}
2043+
}
2044+
if (empty($zip_url)) {
2045+
$zip_url = "https://github.com/{$github_repo}/releases/latest/download/workos-for-wordpress.zip";
2046+
}
2047+
} else {
2048+
$github_error = 'No tag_name in response';
2049+
}
2050+
}
2051+
}
2052+
2053+
// Check transient cache state (version-scoped key matches Updater).
2054+
$cache_key = 'workos_wp_update_' . md5($current_version);
2055+
$cached = get_transient($cache_key);
2056+
$cache_status = 'empty';
2057+
if ($cached === 'none') {
2058+
$cache_status = 'failure sentinel (none)';
2059+
} elseif (is_array($cached) && !empty($cached['tag_name'])) {
2060+
$cache_status = 'cached: ' . $cached['tag_name'];
2061+
} elseif ($cached !== false) {
2062+
$cache_status = 'unexpected: ' . gettype($cached) . ' = ' . var_export($cached, true);
2063+
}
2064+
2065+
// Check WordPress update transient.
2066+
$update_transient = get_site_transient('update_plugins');
2067+
$wp_sees_update = false;
2068+
$wp_no_update = false;
2069+
if (is_object($update_transient)) {
2070+
if (isset($update_transient->response[$plugin_slug])) {
2071+
$wp_sees_update = true;
2072+
}
2073+
if (isset($update_transient->no_update[$plugin_slug])) {
2074+
$wp_no_update = true;
2075+
}
2076+
}
2077+
$checked_version = $update_transient->checked[$plugin_slug] ?? 'not in checked array';
2078+
2079+
$update_available = $github_ok && version_compare($current_version, $remote_version, '<');
2080+
?>
2081+
<div class="workos-card">
2082+
<div class="workos-card-header">
2083+
<h2><?php esc_html_e('Self-Update Check', 'workos-for-wordpress'); ?></h2>
2084+
</div>
2085+
2086+
<?php if ($github_ok): ?>
2087+
<div class="workos-alert <?php echo $update_available ? 'workos-alert-warning' : 'workos-alert-success'; ?>">
2088+
<?php if ($update_available): ?>
2089+
<?php echo esc_html(sprintf(__('Update available: %s → %s', 'workos-for-wordpress'), $current_version, $remote_version)); ?>
2090+
<?php else: ?>
2091+
<?php echo esc_html(sprintf(__('You are running the latest version (%s).', 'workos-for-wordpress'), $current_version)); ?>
2092+
<?php endif; ?>
2093+
</div>
2094+
<?php else: ?>
2095+
<div class="workos-alert workos-alert-error">
2096+
<?php echo esc_html(sprintf(__('GitHub API error: %s', 'workos-for-wordpress'), $github_error)); ?>
2097+
</div>
2098+
<?php endif; ?>
2099+
2100+
<table class="workos-table">
2101+
<tbody>
2102+
<tr>
2103+
<td class="workos-table-label"><?php esc_html_e('Installed Version', 'workos-for-wordpress'); ?></td>
2104+
<td><span class="workos-diag-value"><?php echo esc_html($current_version); ?></span></td>
2105+
</tr>
2106+
<tr>
2107+
<td class="workos-table-label"><?php esc_html_e('GitHub Latest', 'workos-for-wordpress'); ?></td>
2108+
<td><span class="workos-diag-value"><?php echo esc_html($remote_version ?: ''); ?></span></td>
2109+
</tr>
2110+
<tr>
2111+
<td class="workos-table-label"><?php esc_html_e('Plugin Basename', 'workos-for-wordpress'); ?></td>
2112+
<td><span class="workos-diag-value"><?php echo esc_html($plugin_slug); ?></span></td>
2113+
</tr>
2114+
<tr>
2115+
<td class="workos-table-label"><?php esc_html_e('WP Checked Version', 'workos-for-wordpress'); ?></td>
2116+
<td><span class="workos-diag-value"><?php echo esc_html($checked_version); ?></span></td>
2117+
</tr>
2118+
<tr>
2119+
<td class="workos-table-label"><?php esc_html_e('Updater Cache', 'workos-for-wordpress'); ?></td>
2120+
<td><span class="workos-diag-value"><?php echo esc_html($cache_status); ?></span></td>
2121+
</tr>
2122+
<tr>
2123+
<td class="workos-table-label"><?php esc_html_e('WP Sees Update', 'workos-for-wordpress'); ?></td>
2124+
<td>
2125+
<?php if ($wp_sees_update): ?>
2126+
<span class="workos-badge workos-badge-success"><?php esc_html_e('Yes', 'workos-for-wordpress'); ?></span>
2127+
<?php elseif ($wp_no_update): ?>
2128+
<span class="workos-badge workos-badge-muted"><?php esc_html_e('No (checked, up to date)', 'workos-for-wordpress'); ?></span>
2129+
<?php else: ?>
2130+
<span class="workos-badge workos-badge-warning"><?php esc_html_e('Not in transient', 'workos-for-wordpress'); ?></span>
2131+
<?php endif; ?>
2132+
</td>
2133+
</tr>
2134+
<?php if ($zip_url): ?>
2135+
<tr>
2136+
<td class="workos-table-label"><?php esc_html_e('Download URL', 'workos-for-wordpress'); ?></td>
2137+
<td><span class="workos-diag-value" style="word-break:break-all;"><?php echo esc_html($zip_url); ?></span></td>
2138+
</tr>
2139+
<?php endif; ?>
2140+
<tr>
2141+
<td class="workos-table-label"><?php esc_html_e('GitHub API', 'workos-for-wordpress'); ?></td>
2142+
<td>
2143+
<span class="workos-diag-value"><?php echo esc_html($api_url); ?></span>
2144+
<span class="workos-badge <?php echo $github_ok ? 'workos-badge-success' : 'workos-badge-error'; ?>">
2145+
<?php echo esc_html($github_ok ? 'HTTP 200' : "HTTP {$http_code}"); ?>
2146+
</span>
2147+
</td>
2148+
</tr>
2149+
</tbody>
2150+
</table>
2151+
</div>
19972152
<?php
19982153
}
19992154
}

includes/Updater.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ class Updater {
1010
private string $plugin_slug;
1111
private string $version;
1212
private string $github_repo = 'AlwaysCuriousCo/workos-for-wordpress';
13-
private string $cache_key = 'workos_wp_update_check';
13+
private string $cache_key;
1414
private int $cache_ttl = 43200; // 12 hours
1515

1616
public function __construct(string $plugin_file, string $version) {
1717
$this->plugin_file = $plugin_file;
1818
$this->plugin_slug = plugin_basename($plugin_file);
1919
$this->version = $version;
20+
// Version-scoped cache key so upgrades automatically invalidate stale data.
21+
$this->cache_key = 'workos_wp_update_' . md5($version);
2022
}
2123

2224
public function register_hooks(): void {
25+
// Clean up legacy cache key from older versions.
26+
delete_transient('workos_wp_update_check');
27+
2328
add_filter('pre_set_site_transient_update_plugins', [$this, 'check_for_update']);
2429
add_filter('plugins_api', [$this, 'plugin_info'], 10, 3);
2530
add_filter('plugin_row_meta', [$this, 'plugin_row_meta'], 10, 2);
@@ -36,10 +41,17 @@ public function check_for_update($transient) {
3641
$transient = new \stdClass();
3742
}
3843

39-
if (empty($transient->checked)) {
40-
return $transient;
44+
// Ensure response/no_update arrays exist.
45+
if (!isset($transient->response) || !is_array($transient->response)) {
46+
$transient->response = [];
47+
}
48+
if (!isset($transient->no_update) || !is_array($transient->no_update)) {
49+
$transient->no_update = [];
4150
}
4251

52+
// Don't bail on empty checked — some hosts/caches clear it.
53+
// We still run the check and let version_compare decide.
54+
4355
$release = $this->get_latest_release();
4456
if (!$release) {
4557
return $transient;
@@ -60,8 +72,9 @@ public function check_for_update($transient) {
6072
'requires_php' => '8.1',
6173
'requires' => '6.4',
6274
];
75+
// Remove from no_update if previously marked.
76+
unset($transient->no_update[$this->plugin_slug]);
6377
} else {
64-
// Tell WordPress we checked and there's no update.
6578
$transient->no_update[$this->plugin_slug] = (object) [
6679
'slug' => dirname($this->plugin_slug),
6780
'plugin' => $this->plugin_slug,
@@ -134,13 +147,20 @@ public function plugin_row_meta(array $meta, string $file): array {
134147
* Fetch the latest release from GitHub, with caching.
135148
*/
136149
private function get_latest_release(): ?array {
137-
$cached = get_transient($this->cache_key);
138-
if (is_array($cached) && !empty($cached['tag_name'])) {
139-
return $cached;
140-
}
141-
// If cached as 'none', a previous check found nothing — respect the TTL.
142-
if ($cached === 'none') {
143-
return null;
150+
// Bypass cache when WordPress is doing a forced update check.
151+
$force_check = isset($_GET['force-check']) || (defined('DOING_CRON') && DOING_CRON);
152+
153+
if (!$force_check) {
154+
$cached = get_transient($this->cache_key);
155+
if (is_array($cached) && !empty($cached['tag_name'])) {
156+
return $cached;
157+
}
158+
// If cached as 'none', a previous check found nothing — respect the TTL.
159+
if ($cached === 'none') {
160+
return null;
161+
}
162+
} else {
163+
delete_transient($this->cache_key);
144164
}
145165

146166
$response = wp_remote_get(

workos-for-wordpress.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Plugin Name: WorkOS for WordPress
44
* Plugin URI: https://github.com/AlwaysCuriousCo/workos-for-wordpress
55
* Description: Integrate WorkOS authentication and user management into WordPress.
6-
* Version: 1.1.2
6+
* Version: 1.1.3
77
* Author: Always Curious
88
* Author URI: https://alwayscurious.co
99
* License: GPL-3.0-or-later
@@ -15,7 +15,7 @@
1515

1616
defined('ABSPATH') || exit;
1717

18-
define('WORKOS_WP_VERSION', '1.1.2');
18+
define('WORKOS_WP_VERSION', '1.1.3');
1919
define('WORKOS_WP_PLUGIN_FILE', __FILE__);
2020
define('WORKOS_WP_PLUGIN_DIR', plugin_dir_path(__FILE__));
2121
define('WORKOS_WP_PLUGIN_URL', plugin_dir_url(__FILE__));

0 commit comments

Comments
 (0)