*/ private array $options = []; protected function setUp(): void { parent::setUp(); $this->options = []; Functions\when('add_option')->alias(function (string $name, mixed $value = '', string $unused = '', mixed $autoload = null): bool { self::assertFalse($autoload, 'locks are never autoloaded'); if (array_key_exists($name, $this->options)) { return false; } $this->options[$name] = $value; return true; }); Functions\when('get_option')->alias(fn (string $name, mixed $default = false): mixed => $this->options[$name] ?? $default); Functions\when('delete_option')->alias(function (string $name): bool { unset($this->options[$name]); return true; }); } public function testAcquireIsExclusiveUntilReleased(): void { $lock = new DesignLock(); self::assertTrue($lock->acquire('presets')); self::assertIsInt($this->options['lit_mcp_lock_presets']); self::assertFalse($lock->acquire('presets')); self::assertTrue($lock->acquire('colors'), 'areas lock independently'); $lock->release('presets'); self::assertTrue($lock->acquire('presets')); } public function testAStaleLockIsTakenOver(): void { $this->options['lit_mcp_lock_presets'] = time() - DesignLock::STALE_AFTER - 1; self::assertTrue((new DesignLock())->acquire('presets')); self::assertGreaterThan(time() - 5, $this->options['lit_mcp_lock_presets']); } public function testAFreshLockIsNotTakenOver(): void { $this->options['lit_mcp_lock_presets'] = time() - 10; self::assertFalse((new DesignLock())->acquire('presets')); } public function testOptionNamesAndUnknownAreas(): void { self::assertSame('lit_mcp_lock_theme_options', DesignLock::option('theme_options')); $this->expectException(InvalidArgumentException::class); DesignLock::option('pages'); } }