Merge pull request #26 from kristianwind/updater-no-release-fallback
CI / Static checks (push) Successful in 36s
CI / WordPress latest + WooCommerce latest on PHP 8.3 (push) Successful in 1m2s

Answer the update filter even when the release feed cannot be reached
This commit is contained in:
Kristian Wind
2026-09-17 13:27:34 +02:00
committed by GitHub
2 changed files with 54 additions and 10 deletions
+34 -10
View File
@@ -146,10 +146,42 @@ class WC_EDM_Updater {
return $update;
}
// Shared by both branches on purpose. When these were two separate
// literals the no-release branch was simply missing them, and the
// symptom is the grey default plug on Dashboard -> Updates for as long
// as the feed stays down.
//
// Served from the shop's own copy of the plugin rather than from the
// release host: one fewer thing that has to be up and reachable for
// wp-admin to render correctly, it cannot go mixed content on an HTTPS
// shop, and the icon is in the zip anyway.
$icons = array(
'svg' => WC_EDM_PLUGIN_URL . 'assets/icon.svg',
'default' => WC_EDM_PLUGIN_URL . 'assets/icon.svg',
);
$release = $this->latest_release();
// 🔴 Answer with the INSTALLED version rather than returning $update
// untouched. A plugin that answers neither way is in neither the
// `response` nor the `no_update` list, and WP_Plugins_List_Table builds
// the per-plugin "Enable auto-updates" link from that transient — so
// the row reads "Auto-updates are not available for this plugin",
// which reads as a setting rather than as a failed HTTP request. The
// shop then quietly stops being offered fixes, and nothing says so.
//
// The version is true and comparable, so WordPress files it under
// no_update and the row behaves normally until the feed answers again.
if ( ! $release ) {
return $update;
return array(
'slug' => dirname( plugin_basename( WC_EDM_PLUGIN_FILE ) ),
'version' => isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : WC_EDM_VERSION,
'package' => '',
'url' => self::update_uri(),
'requires' => isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : '',
'requires_php' => isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : '',
'icons' => $icons,
);
}
return array(
@@ -163,15 +195,7 @@ class WC_EDM_Updater {
// Without this, Dashboard → Updates shows the generic grey plug
// next to the plugin. WordPress takes the first of svg, 2x, 1x,
// default that is set.
//
// Served from the shop's own copy of the plugin rather than from
// the release host: it is one fewer thing that has to be up and
// reachable for wp-admin to render correctly, it cannot go mixed
// content on an HTTPS shop, and the icon is in the zip anyway.
'icons' => array(
'svg' => WC_EDM_PLUGIN_URL . 'assets/icon.svg',
'default' => WC_EDM_PLUGIN_URL . 'assets/icon.svg',
),
'icons' => $icons,
);
}
+20
View File
@@ -359,6 +359,26 @@ set_transient(
$offered = wc_edm()->updater->offer_update( false, get_plugin_data( WC_EDM_PLUGIN_FILE, false, false ), plugin_basename( WC_EDM_PLUGIN_FILE ) );
wc_edm_is( 'the current version is answered too, not passed over', WC_EDM_VERSION, is_array( $offered ) ? $offered['version'] : null );
// And the case neither assertion above covers: the feed could not be reached.
// Returning $update untouched there drops the plugin out of BOTH the response
// and no_update lists, and WP_Plugins_List_Table builds the per-plugin "Enable
// auto-updates" link from that transient — so the row reads "Auto-updates are
// not available for this plugin", which looks like a setting rather than a
// failed HTTP request. The shop then silently stops being offered fixes.
set_transient( WC_EDM_Updater::TRANSIENT, 'none', 60 );
$offered = wc_edm()->updater->offer_update( false, get_plugin_data( WC_EDM_PLUGIN_FILE, false, false ), plugin_basename( WC_EDM_PLUGIN_FILE ) );
wc_edm_is(
'an unreachable feed still answers with the installed version',
WC_EDM_VERSION,
is_array( $offered ) ? $offered['version'] : null
);
wc_edm_ok(
'and that answer still carries the icon',
is_array( $offered ) && ! empty( $offered['icons'] ),
'without icons in this branch Dashboard -> Updates shows the grey default plug until the feed answers again'
);
delete_transient( WC_EDM_Updater::TRANSIENT );
// 🔴 The filter name is built from the HOSTNAME, not the repository. Every
// plugin updating from gitea.nolimit.dk shares the hook
// update_plugins_gitea.nolimit.dk, and WordPress runs every callback on it for