An icon, a Check again that checks, and the auto-update rule written down

Three gaps found by being asked plain questions about it.

**The auto-update toggle was a promise nobody had checked.** offer_update()
answers even when the installed version is current, on the reasoning that the
answer has to land in WordPress's no_update list for the "Enable auto-updates"
link to exist at all. That was a comment and an intention; it is now an
assertion against the real WP_Plugins_List_Table, which is where the flag is
actually read:

    $plugin_data = array_merge( (array) $plugin_info->no_update[ $plugin_file ],
                               array( 'update-supported' => true ), $plugin_data );

A plugin in neither response nor no_update gets "Auto-updates are not available
for this plugin" while looking entirely healthy.

**An icon.** Without one, Dashboard → Updates shows a generic grey plug.
assets/icon.svg, handed over in the offer's icons key, served from the shop's
own copy rather than the release host — one fewer thing that must be reachable
for wp-admin to render, and it cannot go mixed content on an HTTPS shop. Drawn
as paths rather than <text>: an SVG that leans on a font renders differently on
every machine, and this one is shown at about 40px, which is the size where
that is the difference between a mark and a smudge.

**"Check again" now checks again.** The six-hour cache is right for the check
WordPress runs twice a day and wrong for a link whose whole promise is that it
looks now. Publishing a release and then clicking it showed nothing for up to
six hours, which reads exactly like a broken updater.

And docs/REUSE.md was missing all of this: it covered Update URI, where to
instantiate the updater and making the repo public, but not the one rule that
is genuinely easy to get wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kristianwind
2026-09-16 12:23:05 +02:00
co-authored by Claude Opus 5
parent cef52734ee
commit 200f791f40
5 changed files with 219 additions and 3 deletions
+36
View File
@@ -55,6 +55,9 @@ class WC_EDM_Updater {
// update, and the plugins screen keeps offering a version already
// installed.
add_action( 'upgrader_process_complete', array( $this, 'forget' ), 10, 0 );
// And "Check again" has to actually check again.
add_action( 'admin_init', array( $this, 'forget_on_force_check' ) );
}
/**
@@ -123,6 +126,18 @@ class WC_EDM_Updater {
'tested' => $release['tested'],
'requires' => isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : '',
'requires_php' => isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : '',
// 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',
),
);
}
@@ -133,6 +148,27 @@ class WC_EDM_Updater {
delete_transient( self::TRANSIENT );
}
/**
* Honour the "Check again" link on Dashboard → Updates.
*
* The six-hour cache is right for the check WordPress runs twice a day on
* its own, and wrong for a button whose entire promise is that it looks
* right now. Without this, someone who has just published a release clicks
* it, sees nothing, and concludes the update mechanism is broken.
*
* No nonce to verify: this reads a link WordPress itself renders, and the
* only effect is discarding a cache — the worst a forged request achieves
* is one extra HTTP GET.
*/
public function forget_on_force_check() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( empty( $_GET['force-check'] ) || ! current_user_can( 'update_plugins' ) ) {
return;
}
$this->forget();
}
/**
* Read the newest release from the repository.
*