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:
co-authored by
Claude Opus 5
parent
cef52734ee
commit
200f791f40
@@ -292,6 +292,19 @@ wc_edm_is(
|
||||
'woocommerce-email-discount-manager',
|
||||
is_array( $offered ) ? $offered['slug'] : null
|
||||
);
|
||||
// Dashboard → Updates falls back to a generic grey plug when this is missing,
|
||||
// and a 404 here is invisible until someone looks at that screen.
|
||||
wc_edm_ok(
|
||||
'the offer carries an icon',
|
||||
is_array( $offered ) && ! empty( $offered['icons']['svg'] ),
|
||||
'without it wp-admin shows the generic plugin placeholder'
|
||||
);
|
||||
wc_edm_ok(
|
||||
'and the icon is a file that is actually in the release',
|
||||
file_exists( WC_EDM_PLUGIN_DIR . 'assets/icon.svg' ),
|
||||
'the offer would point wp-admin at a 404'
|
||||
);
|
||||
|
||||
wc_edm_ok(
|
||||
'the offer names a downloadable package',
|
||||
is_array( $offered ) && ! empty( $offered['package'] ),
|
||||
@@ -314,6 +327,81 @@ set_transient(
|
||||
$offered = wc_edm()->updater->offer_update( false, get_plugin_data( WC_EDM_PLUGIN_FILE, false, false ) );
|
||||
wc_edm_is( 'the current version is answered too, not passed over', WC_EDM_VERSION, is_array( $offered ) ? $offered['version'] : null );
|
||||
|
||||
/*
|
||||
* The "Enable auto-updates" link on the Plugins screen.
|
||||
*
|
||||
* It is not automatic for a plugin that does not come from wordpress.org.
|
||||
* WP_Plugins_List_Table sets 'update-supported' => true only for plugins it
|
||||
* finds in the update transient's `response` list (an update is waiting) or
|
||||
* its `no_update` list (we asked, there is none). A plugin in neither gets
|
||||
* "Auto-updates are not available for this plugin." and no toggle.
|
||||
*
|
||||
* That is the whole reason offer_update() answers even when the installed
|
||||
* version is already current. Staying silent there is how a plugin ends up
|
||||
* unable to auto-update while looking perfectly configured — so this asserts
|
||||
* the outcome, not the intention.
|
||||
*
|
||||
* The feed stays stubbed through the transient above: this is about what
|
||||
* WordPress does with our answer, and a test that needs the internet fails for
|
||||
* reasons that have nothing to do with it.
|
||||
*/
|
||||
// "Check again" must discard the six-hour cache, or the button lies: someone
|
||||
// who has just published a release clicks it, sees nothing, and concludes the
|
||||
// whole mechanism is broken.
|
||||
set_transient( WC_EDM_Updater::TRANSIENT, array( 'version' => '1.0.0', 'package' => 'x', 'url' => 'x', 'tested' => '' ), 600 );
|
||||
wp_set_current_user( 1 );
|
||||
$_GET['force-check'] = '1';
|
||||
wc_edm()->updater->forget_on_force_check();
|
||||
unset( $_GET['force-check'] );
|
||||
wc_edm_ok( 'Check again discards the cached feed', false === get_transient( WC_EDM_Updater::TRANSIENT ) );
|
||||
|
||||
// And a visitor with no business updating plugins does not get to clear it.
|
||||
set_transient( WC_EDM_Updater::TRANSIENT, array( 'version' => '1.0.0', 'package' => 'x', 'url' => 'x', 'tested' => '' ), 600 );
|
||||
wp_set_current_user( 0 );
|
||||
$_GET['force-check'] = '1';
|
||||
wc_edm()->updater->forget_on_force_check();
|
||||
unset( $_GET['force-check'] );
|
||||
wc_edm_ok( 'but a caller who cannot update plugins does not clear it', is_array( get_transient( WC_EDM_Updater::TRANSIENT ) ) );
|
||||
delete_transient( WC_EDM_Updater::TRANSIENT );
|
||||
|
||||
// Rendering the list table in a CLI context makes core itself emit a
|
||||
// strlen(null) deprecation from class-wp-plugins-list-table.php. It is
|
||||
// WordPress's, not ours, which is why the deprecation check filters on this
|
||||
// plugin's directory rather than failing on everything it sees.
|
||||
delete_site_transient( 'update_plugins' );
|
||||
wp_update_plugins();
|
||||
$transient = get_site_transient( 'update_plugins' );
|
||||
$basename = plugin_basename( WC_EDM_PLUGIN_FILE );
|
||||
|
||||
wc_edm_ok(
|
||||
'WordPress files the plugin under response or no_update',
|
||||
isset( $transient->response[ $basename ] ) || isset( $transient->no_update[ $basename ] ),
|
||||
'in neither, so wp-admin would say "Auto-updates are not available for this plugin"'
|
||||
);
|
||||
|
||||
// And the list table itself, which is what the shop owner actually looks at.
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-plugins-list-table.php';
|
||||
wp_set_current_user( 1 );
|
||||
set_current_screen( 'plugins' );
|
||||
|
||||
$table = new WP_Plugins_List_Table( array( 'screen' => get_current_screen() ) );
|
||||
$table->prepare_items();
|
||||
|
||||
$row = null;
|
||||
foreach ( $table->items as $file => $data ) {
|
||||
if ( $file === $basename ) {
|
||||
$row = $data;
|
||||
}
|
||||
}
|
||||
|
||||
wc_edm_ok( 'the plugin is on the Plugins screen at all', null !== $row );
|
||||
wc_edm_ok(
|
||||
'and WordPress marks it as supporting updates',
|
||||
$row && ! empty( $row['update-supported'] ),
|
||||
'without this the auto-update column reads "Auto-updates are not available for this plugin."'
|
||||
);
|
||||
|
||||
delete_transient( WC_EDM_Updater::TRANSIENT );
|
||||
|
||||
/* --------------------------------------------------------------- verdict -- */
|
||||
|
||||
Reference in New Issue
Block a user