feat(updater): Update-Prüfung nach Installation oder Versionswechsel neu auslösen, Version 1.0.5
Eine Installation löscht das gespeicherte Update-Ergebnis; eine Prüfung, die läuft, solange das Plugin nicht geladen ist, speichert eines ohne das Plugin, und der Schalter für automatische Updates fehlt bis zu eine Stunde. RecheckOnInstall vergisst das Ergebnis beim ersten admin_init mit der neuen Version (Priorität 5, vor _maybe_update_plugins des Core), der es dann mit registriertem GiteaUpdater neu aufbaut. Die Option lit_mcp_installed_version räumt der Uninstaller auf. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
62292a4846
commit
9f7c2d9aba
+4
-1
@@ -4,7 +4,7 @@ Tags: mcp, ai, divi, pods, oauth
|
|||||||
Requires at least: 6.9
|
Requires at least: 6.9
|
||||||
Tested up to: 7.1
|
Tested up to: 7.1
|
||||||
Requires PHP: 8.1
|
Requires PHP: 8.1
|
||||||
Stable tag: 1.0.4
|
Stable tag: 1.0.5
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
@@ -209,6 +209,9 @@ LIT MCP schreibt nur mit Divi-Versionen, die für diese Plugin-Version geprüft
|
|||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.0.5 =
|
||||||
|
* Nach einer Installation oder einem Versionswechsel prüft WordPress sofort neu auf Updates, damit der Schalter für automatische Updates gleich erscheint.
|
||||||
|
|
||||||
= 1.0.4 =
|
= 1.0.4 =
|
||||||
* Kürzere Beschreibung in der Plugin-Liste.
|
* Kürzere Beschreibung in der Plugin-Liste.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -38,6 +38,7 @@ use LIT\MCP\Server\RequestContext;
|
|||||||
use LIT\MCP\Server\ServerRegistrar;
|
use LIT\MCP\Server\ServerRegistrar;
|
||||||
use LIT\MCP\Server\VisibilityFilter;
|
use LIT\MCP\Server\VisibilityFilter;
|
||||||
use LIT\MCP\Updater\GiteaUpdater;
|
use LIT\MCP\Updater\GiteaUpdater;
|
||||||
|
use LIT\MCP\Updater\RecheckOnInstall;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ defined('ABSPATH') || exit;
|
|||||||
*/
|
*/
|
||||||
final class Plugin
|
final class Plugin
|
||||||
{
|
{
|
||||||
public const VERSION = '1.0.4';
|
public const VERSION = '1.0.5';
|
||||||
|
|
||||||
private static string $pluginFile = '';
|
private static string $pluginFile = '';
|
||||||
private static ?SettingsPage $settingsPage = null;
|
private static ?SettingsPage $settingsPage = null;
|
||||||
@@ -57,6 +58,7 @@ final class Plugin
|
|||||||
|
|
||||||
// Before the dependency check: a plugin that is inactive for a missing dependency must still be updatable.
|
// Before the dependency check: a plugin that is inactive for a missing dependency must still be updatable.
|
||||||
(new GiteaUpdater(plugin_basename($pluginFile), dirname($pluginFile)))->register();
|
(new GiteaUpdater(plugin_basename($pluginFile), dirname($pluginFile)))->register();
|
||||||
|
(new RecheckOnInstall(self::VERSION))->register();
|
||||||
|
|
||||||
$missing = (new Dependencies())->missing();
|
$missing = (new Dependencies())->missing();
|
||||||
if ($missing !== []) {
|
if ($missing !== []) {
|
||||||
|
|||||||
+3
-2
@@ -20,8 +20,8 @@ defined('ABSPATH') || exit;
|
|||||||
* ReleaseStore::OPTION, Integrations\Divi\Release\CheckReportStore::OPTION, Integrations\
|
* ReleaseStore::OPTION, Integrations\Divi\Release\CheckReportStore::OPTION, Integrations\
|
||||||
* Divi\Release\DiviCheckRoute::LOCK, Integrations\Divi\Design\DesignLock::option(),
|
* Divi\Release\DiviCheckRoute::LOCK, Integrations\Divi\Design\DesignLock::option(),
|
||||||
* Admin\ConnectionStatus::ENDPOINT_TRANSIENT, Integrations\Divi\Release\ReleaseResolver::CACHE,
|
* Admin\ConnectionStatus::ENDPOINT_TRANSIENT, Integrations\Divi\Release\ReleaseResolver::CACHE,
|
||||||
* ChangeLog\ChangeLogCleanup::HOOK, ChangeLog\ChangeLog::TABLE and Admin\LogTab::PER_PAGE_OPTION
|
* ChangeLog\ChangeLogCleanup::HOOK, ChangeLog\ChangeLog::TABLE, Admin\LogTab::PER_PAGE_OPTION and
|
||||||
* on purpose;
|
* Updater\RecheckOnInstall::OPTION on purpose;
|
||||||
* tests/Unit/UninstallerTest.php and tests/Unit/UninstallTest.php keep them in sync with
|
* tests/Unit/UninstallerTest.php and tests/Unit/UninstallTest.php keep them in sync with
|
||||||
* those constants.
|
* those constants.
|
||||||
*
|
*
|
||||||
@@ -40,6 +40,7 @@ final class Uninstaller
|
|||||||
'lit_mcp_lock_divi_options', 'lit_mcp_lock_variables', 'lit_mcp_lock_presets',
|
'lit_mcp_lock_divi_options', 'lit_mcp_lock_variables', 'lit_mcp_lock_presets',
|
||||||
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
||||||
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
||||||
|
'lit_mcp_installed_version',
|
||||||
];
|
];
|
||||||
private const TRANSIENTS = ['lit_mcp_endpoint_check', 'lit_mcp_divi_state'];
|
private const TRANSIENTS = ['lit_mcp_endpoint_check', 'lit_mcp_divi_state'];
|
||||||
private const CRON_HOOK = 'lit_mcp_log_cleanup';
|
private const CRON_HOOK = 'lit_mcp_log_cleanup';
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Updater;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes WordPress check for updates again right after this plugin was installed or replaced. An install deletes
|
||||||
|
* the stored update result, and a check that runs while the plugin is not loaded stores one without it: the plugin
|
||||||
|
* list then hides the auto-update switch for up to an hour. The first admin request with the new code forgets the
|
||||||
|
* result at admin_init, before core's own _maybe_update_plugins (priority 10) rebuilds it, this time with
|
||||||
|
* GiteaUpdater registered.
|
||||||
|
*/
|
||||||
|
final class RecheckOnInstall
|
||||||
|
{
|
||||||
|
public const OPTION = 'lit_mcp_installed_version';
|
||||||
|
|
||||||
|
public function __construct(private string $version)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(): void
|
||||||
|
{
|
||||||
|
add_action('admin_init', [$this, 'recheckIfNew'], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recheckIfNew(): void
|
||||||
|
{
|
||||||
|
if (get_option(self::OPTION) === $this->version) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_site_transient('update_plugins');
|
||||||
|
update_option(self::OPTION, $this->version, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
|||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||||
use LIT\MCP\Limits;
|
use LIT\MCP\Limits;
|
||||||
|
use LIT\MCP\Updater\RecheckOnInstall;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
|
|
||||||
final class UninstallTest extends TestCase
|
final class UninstallTest extends TestCase
|
||||||
@@ -61,6 +62,7 @@ final class UninstallTest extends TestCase
|
|||||||
DesignLock::option('colors'), DesignLock::option('variables'), DesignLock::option('presets'),
|
DesignLock::option('colors'), DesignLock::option('variables'), DesignLock::option('presets'),
|
||||||
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
||||||
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
||||||
|
RecheckOnInstall::OPTION,
|
||||||
];
|
];
|
||||||
self::assertSame(array_merge($own, $own), $deleted);
|
self::assertSame(array_merge($own, $own), $deleted);
|
||||||
self::assertNotContains('mcp_jwt_secret', $deleted);
|
self::assertNotContains('mcp_jwt_secret', $deleted);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
|||||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||||
use LIT\MCP\Limits;
|
use LIT\MCP\Limits;
|
||||||
use LIT\MCP\Uninstaller;
|
use LIT\MCP\Uninstaller;
|
||||||
|
use LIT\MCP\Updater\RecheckOnInstall;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,6 +68,7 @@ final class UninstallerTest extends TestCase
|
|||||||
DesignLock::option('colors'), DesignLock::option('variables'), DesignLock::option('presets'),
|
DesignLock::option('colors'), DesignLock::option('variables'), DesignLock::option('presets'),
|
||||||
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
// Locks of versions before the shared one (audit L5) may still sit in the table.
|
||||||
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
'lit_mcp_lock_colors', 'lit_mcp_lock_theme_options',
|
||||||
|
RecheckOnInstall::OPTION,
|
||||||
],
|
],
|
||||||
$deleted
|
$deleted
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Tests\Unit\Updater;
|
||||||
|
|
||||||
|
use Brain\Monkey\Actions;
|
||||||
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
use LIT\MCP\Updater\RecheckOnInstall;
|
||||||
|
|
||||||
|
final class RecheckOnInstallTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testRunsAtAdminInitBeforeCoreRebuildsTheUpdateResult(): void
|
||||||
|
{
|
||||||
|
$recheck = new RecheckOnInstall('1.0.5');
|
||||||
|
// Core's _maybe_update_plugins sits on admin_init at the default priority 10.
|
||||||
|
Actions\expectAdded('admin_init')->once()->with([$recheck, 'recheckIfNew'], 5);
|
||||||
|
|
||||||
|
$recheck->register();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @dataProvider installedBefore */
|
||||||
|
public function testForgetsTheUpdateResultWhenTheVersionIsNewToThisSite(string|false $stored): void
|
||||||
|
{
|
||||||
|
Functions\when('get_option')->justReturn($stored);
|
||||||
|
Functions\expect('delete_site_transient')->once()->with('update_plugins');
|
||||||
|
Functions\expect('update_option')->once()->with(RecheckOnInstall::OPTION, '1.0.5', false);
|
||||||
|
|
||||||
|
(new RecheckOnInstall('1.0.5'))->recheckIfNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return array<string, array{string|false}> */
|
||||||
|
public static function installedBefore(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'fresh install, nothing stored' => [false],
|
||||||
|
'replaced by a newer version' => ['1.0.4'],
|
||||||
|
'replaced by an older version' => ['1.0.9'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDoesNothingForTheVersionAlreadySeen(): void
|
||||||
|
{
|
||||||
|
Functions\when('get_option')->justReturn('1.0.5');
|
||||||
|
Functions\expect('delete_site_transient')->never();
|
||||||
|
Functions\expect('update_option')->never();
|
||||||
|
|
||||||
|
(new RecheckOnInstall('1.0.5'))->recheckIfNew();
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
* Plugin Name: WP-LIT-MCP
|
* Plugin Name: WP-LIT-MCP
|
||||||
* Plugin URI: https://git.loosen-it.de/janniclas.loosen/WP-LIT-MCP
|
* Plugin URI: https://git.loosen-it.de/janniclas.loosen/WP-LIT-MCP
|
||||||
* Description: MCP-Server für WordPress, Divi 5 und Pods. Pflegt Inhalte, Medien und Divi-Seiten mit OAuth für KI-Assistenten.
|
* Description: MCP-Server für WordPress, Divi 5 und Pods. Pflegt Inhalte, Medien und Divi-Seiten mit OAuth für KI-Assistenten.
|
||||||
* Version: 1.0.4
|
* Version: 1.0.5
|
||||||
* Update URI: https://git.loosen-it.de/janniclas.loosen/WP-LIT-MCP
|
* Update URI: https://git.loosen-it.de/janniclas.loosen/WP-LIT-MCP
|
||||||
* Requires at least: 6.9
|
* Requires at least: 6.9
|
||||||
* Requires PHP: 8.1
|
* Requires PHP: 8.1
|
||||||
|
|||||||
Reference in New Issue
Block a user