From 642a81a8d47d40d9631647fa36cd9a7f8269f15a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 May 2025 17:52:22 +0200 Subject: [PATCH 1/6] refactor: split off value casting out of config:system:set command Signed-off-by: Robin Appelman --- core/Command/Config/System/CastHelper.php | 76 ++++++++++++++++++ core/Command/Config/System/SetConfig.php | 77 +------------------ lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + .../Command/Config/System/CastHelperTest.php | 69 +++++++++++++++++ .../Command/Config/System/SetConfigTest.php | 3 +- 6 files changed, 151 insertions(+), 76 deletions(-) create mode 100644 core/Command/Config/System/CastHelper.php create mode 100644 tests/Core/Command/Config/System/CastHelperTest.php diff --git a/core/Command/Config/System/CastHelper.php b/core/Command/Config/System/CastHelper.php new file mode 100644 index 0000000000000..f2b838bdf9b95 --- /dev/null +++ b/core/Command/Config/System/CastHelper.php @@ -0,0 +1,76 @@ + (int)$value, + 'readable-value' => 'integer ' . (int)$value, + ]; + + case 'double': + case 'float': + if (!is_numeric($value)) { + throw new \InvalidArgumentException('Non-numeric value specified'); + } + return [ + 'value' => (float)$value, + 'readable-value' => 'double ' . (float)$value, + ]; + + case 'boolean': + case 'bool': + $value = strtolower($value); + return match ($value) { + 'true' => [ + 'value' => true, + 'readable-value' => 'boolean ' . $value, + ], + 'false' => [ + 'value' => false, + 'readable-value' => 'boolean ' . $value, + ], + default => throw new \InvalidArgumentException('Unable to parse value as boolean'), + }; + + case 'null': + return [ + 'value' => null, + 'readable-value' => 'null', + ]; + + case 'string': + $value = (string)$value; + return [ + 'value' => $value, + 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value, + ]; + + case 'json': + $value = json_decode($value, true); + return [ + 'value' => $value, + 'readable-value' => 'json ' . json_encode($value), + ]; + + default: + throw new \InvalidArgumentException('Invalid type'); + } + } +} diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php index 62ab7f7120fe3..1b1bdc66a6e01 100644 --- a/core/Command/Config/System/SetConfig.php +++ b/core/Command/Config/System/SetConfig.php @@ -17,6 +17,7 @@ class SetConfig extends Base { public function __construct( SystemConfig $systemConfig, + private CastHelper $castHelper, ) { parent::__construct($systemConfig); } @@ -57,7 +58,7 @@ protected function configure() { protected function execute(InputInterface $input, OutputInterface $output): int { $configNames = $input->getArgument('name'); $configName = $configNames[0]; - $configValue = $this->castValue($input->getOption('value'), $input->getOption('type')); + $configValue = $this->castHelper->castValue($input->getOption('value'), $input->getOption('type')); $updateOnly = $input->getOption('update-only'); if (count($configNames) > 1) { @@ -80,80 +81,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - /** - * @param string $value - * @param string $type - * @return mixed - * @throws \InvalidArgumentException - */ - protected function castValue($value, $type) { - switch ($type) { - case 'integer': - case 'int': - if (!is_numeric($value)) { - throw new \InvalidArgumentException('Non-numeric value specified'); - } - return [ - 'value' => (int)$value, - 'readable-value' => 'integer ' . (int)$value, - ]; - - case 'double': - case 'float': - if (!is_numeric($value)) { - throw new \InvalidArgumentException('Non-numeric value specified'); - } - return [ - 'value' => (float)$value, - 'readable-value' => 'double ' . (float)$value, - ]; - - case 'boolean': - case 'bool': - $value = strtolower($value); - switch ($value) { - case 'true': - return [ - 'value' => true, - 'readable-value' => 'boolean ' . $value, - ]; - - case 'false': - return [ - 'value' => false, - 'readable-value' => 'boolean ' . $value, - ]; - - default: - throw new \InvalidArgumentException('Unable to parse value as boolean'); - } - - // no break - case 'null': - return [ - 'value' => null, - 'readable-value' => 'null', - ]; - - case 'string': - $value = (string)$value; - return [ - 'value' => $value, - 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value, - ]; - - case 'json': - $value = json_decode($value, true); - return [ - 'value' => $value, - 'readable-value' => 'json ' . json_encode($value), - ]; - - default: - throw new \InvalidArgumentException('Invalid type'); - } - } - /** * @param array $configNames * @param mixed $existingValues diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 2c1872e23d929..91503349e599a 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1225,6 +1225,7 @@ 'OC\\Core\\Command\\Config\\Import' => $baseDir . '/core/Command/Config/Import.php', 'OC\\Core\\Command\\Config\\ListConfigs' => $baseDir . '/core/Command/Config/ListConfigs.php', 'OC\\Core\\Command\\Config\\System\\Base' => $baseDir . '/core/Command/Config/System/Base.php', + 'OC\\Core\\Command\\Config\\System\\CastHelper' => $baseDir . '/core/Command/Config/System/CastHelper.php', 'OC\\Core\\Command\\Config\\System\\DeleteConfig' => $baseDir . '/core/Command/Config/System/DeleteConfig.php', 'OC\\Core\\Command\\Config\\System\\GetConfig' => $baseDir . '/core/Command/Config/System/GetConfig.php', 'OC\\Core\\Command\\Config\\System\\SetConfig' => $baseDir . '/core/Command/Config/System/SetConfig.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 9e843c976d56a..ccc4f6de725f3 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1274,6 +1274,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Config\\Import' => __DIR__ . '/../../..' . '/core/Command/Config/Import.php', 'OC\\Core\\Command\\Config\\ListConfigs' => __DIR__ . '/../../..' . '/core/Command/Config/ListConfigs.php', 'OC\\Core\\Command\\Config\\System\\Base' => __DIR__ . '/../../..' . '/core/Command/Config/System/Base.php', + 'OC\\Core\\Command\\Config\\System\\CastHelper' => __DIR__ . '/../../..' . '/core/Command/Config/System/CastHelper.php', 'OC\\Core\\Command\\Config\\System\\DeleteConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/DeleteConfig.php', 'OC\\Core\\Command\\Config\\System\\GetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/GetConfig.php', 'OC\\Core\\Command\\Config\\System\\SetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/SetConfig.php', diff --git a/tests/Core/Command/Config/System/CastHelperTest.php b/tests/Core/Command/Config/System/CastHelperTest.php new file mode 100644 index 0000000000000..0d3ca032026ac --- /dev/null +++ b/tests/Core/Command/Config/System/CastHelperTest.php @@ -0,0 +1,69 @@ +castHelper = new CastHelper(); + } + + public static function castValueProvider(): array { + return [ + [null, 'string', ['value' => '', 'readable-value' => 'empty string']], + + ['abc', 'string', ['value' => 'abc', 'readable-value' => 'string abc']], + + ['123', 'integer', ['value' => 123, 'readable-value' => 'integer 123']], + ['456', 'int', ['value' => 456, 'readable-value' => 'integer 456']], + + ['2.25', 'double', ['value' => 2.25, 'readable-value' => 'double 2.25']], + ['0.5', 'float', ['value' => 0.5, 'readable-value' => 'double 0.5']], + + ['', 'null', ['value' => null, 'readable-value' => 'null']], + + ['true', 'boolean', ['value' => true, 'readable-value' => 'boolean true']], + ['false', 'bool', ['value' => false, 'readable-value' => 'boolean false']], + ]; + } + + /** + * @dataProvider castValueProvider + */ + public function testCastValue($value, $type, $expectedValue): void { + $this->assertSame( + $expectedValue, + $this->castHelper->castValue($value, $type) + ); + } + + public static function castValueInvalidProvider(): array { + return [ + ['123', 'foobar'], + + [null, 'integer'], + ['abc', 'integer'], + ['76ggg', 'double'], + ['true', 'float'], + ['foobar', 'boolean'], + ]; + } + + /** + * @dataProvider castValueInvalidProvider + */ + public function testCastValueInvalid($value, $type): void { + $this->expectException(\InvalidArgumentException::class); + + $this->castHelper->castValue($value, $type); + } +} diff --git a/tests/Core/Command/Config/System/SetConfigTest.php b/tests/Core/Command/Config/System/SetConfigTest.php index 2905af5c3d73e..cf44058f6703b 100644 --- a/tests/Core/Command/Config/System/SetConfigTest.php +++ b/tests/Core/Command/Config/System/SetConfigTest.php @@ -7,6 +7,7 @@ namespace Tests\Core\Command\Config\System; +use OC\Core\Command\Config\System\CastHelper; use OC\Core\Command\Config\System\SetConfig; use OC\SystemConfig; use Symfony\Component\Console\Input\InputInterface; @@ -35,7 +36,7 @@ protected function setUp(): void { $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock(); /** @var \OC\SystemConfig $systemConfig */ - $this->command = new SetConfig($systemConfig); + $this->command = new SetConfig($systemConfig, new CastHelper()); } From 38faa7af70800002aea9f98bd116be0a6471c7c5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 May 2025 17:52:31 +0200 Subject: [PATCH 2/6] feat: add commands to get and set memcache values Signed-off-by: Robin Appelman --- core/Command/Memcache/DistributedGet.php | 40 +++++++++++++++ core/Command/Memcache/DistributedSet.php | 57 +++++++++++++++++++++ lib/composer/composer/autoload_classmap.php | 2 + lib/composer/composer/autoload_static.php | 2 + 4 files changed, 101 insertions(+) create mode 100644 core/Command/Memcache/DistributedGet.php create mode 100644 core/Command/Memcache/DistributedSet.php diff --git a/core/Command/Memcache/DistributedGet.php b/core/Command/Memcache/DistributedGet.php new file mode 100644 index 0000000000000..bf1b00d312d81 --- /dev/null +++ b/core/Command/Memcache/DistributedGet.php @@ -0,0 +1,40 @@ +setName('memcache:distributed:get') + ->setDescription('Get a value from the distributed memcache') + ->addArgument('key', InputArgument::REQUIRED, 'The key to retrieve'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $cache = $this->cacheFactory->createDistributed(); + $key = $input->getArgument('key'); + + $value = $cache->get($key); + $this->writeMixedInOutputFormat($input, $output, $value); + return 0; + } +} diff --git a/core/Command/Memcache/DistributedSet.php b/core/Command/Memcache/DistributedSet.php new file mode 100644 index 0000000000000..0f31c22f730d1 --- /dev/null +++ b/core/Command/Memcache/DistributedSet.php @@ -0,0 +1,57 @@ +setName('memcache:distributed:set') + ->setDescription('Set a value in the distributed memcache') + ->addArgument('key', InputArgument::REQUIRED, 'The key to set') + ->addArgument('value', InputArgument::REQUIRED, 'The value to set') + ->addOption( + 'type', + null, + InputOption::VALUE_REQUIRED, + 'Value type [string, integer, float, boolean, json, null]', + 'string' + ); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $cache = $this->cacheFactory->createDistributed(); + $key = $input->getArgument('key'); + $value = $input->getArgument('value'); + $type = $input->getOption('type'); + ['value' => $value, 'readable-value' => $readable] = $this->castHelper->castValue($value, $type); + if ($cache->set($key, $value)) { + $output->writeln('Distributed cache key ' . $key . ' set to ' . $readable . ''); + return 0; + } else { + $output->writeln('Failed to set cache key ' . $key . ''); + return 1; + } + } +} diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 91503349e599a..da029b264c75d 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1284,6 +1284,8 @@ 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => $baseDir . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => $baseDir . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => $baseDir . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedGet' => $baseDir . '/core/Command/Memcache/DistributedGet.php', + 'OC\\Core\\Command\\Memcache\\DistributedSet' => $baseDir . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => $baseDir . '/core/Command/Memcache/RedisCommand.php', 'OC\\Core\\Command\\Preview\\Cleanup' => $baseDir . '/core/Command/Preview/Cleanup.php', 'OC\\Core\\Command\\Preview\\Generate' => $baseDir . '/core/Command/Preview/Generate.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ccc4f6de725f3..1a4b9a4564715 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1333,6 +1333,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => __DIR__ . '/../../..' . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedGet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedGet.php', + 'OC\\Core\\Command\\Memcache\\DistributedSet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => __DIR__ . '/../../..' . '/core/Command/Memcache/RedisCommand.php', 'OC\\Core\\Command\\Preview\\Cleanup' => __DIR__ . '/../../..' . '/core/Command/Preview/Cleanup.php', 'OC\\Core\\Command\\Preview\\Generate' => __DIR__ . '/../../..' . '/core/Command/Preview/Generate.php', From a8428cad01f2bf72a5ab7274484bf82cf26f5b0e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 May 2025 16:00:40 +0200 Subject: [PATCH 3/6] feat: add command to delete memcache key Signed-off-by: Robin Appelman --- core/Command/Memcache/DistributedDelete.php | 43 +++++++++++++++++++++ lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + 3 files changed, 45 insertions(+) create mode 100644 core/Command/Memcache/DistributedDelete.php diff --git a/core/Command/Memcache/DistributedDelete.php b/core/Command/Memcache/DistributedDelete.php new file mode 100644 index 0000000000000..ae0855acb03ea --- /dev/null +++ b/core/Command/Memcache/DistributedDelete.php @@ -0,0 +1,43 @@ +setName('memcache:distributed:delete') + ->setDescription('Delete a value in the distributed memcache') + ->addArgument('key', InputArgument::REQUIRED, 'The key to delete'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $cache = $this->cacheFactory->createDistributed(); + $key = $input->getArgument('key'); + if ($cache->remove($key)) { + $output->writeln('Distributed cache key ' . $key . ' deleted'); + return 0; + } else { + $output->writeln('Failed to delete cache key ' . $key . ''); + return 1; + } + } +} diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index da029b264c75d..83225a1bb5061 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1284,6 +1284,7 @@ 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => $baseDir . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => $baseDir . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => $baseDir . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedDelete' => $baseDir . '/core/Command/Memcache/DistributedDelete.php', 'OC\\Core\\Command\\Memcache\\DistributedGet' => $baseDir . '/core/Command/Memcache/DistributedGet.php', 'OC\\Core\\Command\\Memcache\\DistributedSet' => $baseDir . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => $baseDir . '/core/Command/Memcache/RedisCommand.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 1a4b9a4564715..ef98b312d54a7 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1333,6 +1333,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => __DIR__ . '/../../..' . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedDelete' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedDelete.php', 'OC\\Core\\Command\\Memcache\\DistributedGet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedGet.php', 'OC\\Core\\Command\\Memcache\\DistributedSet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => __DIR__ . '/../../..' . '/core/Command/Memcache/RedisCommand.php', From 32e201e54029d5127b66e2fe876e765fceff7fce Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 May 2025 17:35:53 +0200 Subject: [PATCH 4/6] feat: add command to clear memcache Signed-off-by: Robin Appelman [skip ci] --- core/Command/Memcache/DistributedClear.php | 47 +++++++++++++++++++++ lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + 3 files changed, 49 insertions(+) create mode 100644 core/Command/Memcache/DistributedClear.php diff --git a/core/Command/Memcache/DistributedClear.php b/core/Command/Memcache/DistributedClear.php new file mode 100644 index 0000000000000..424f21f1e8124 --- /dev/null +++ b/core/Command/Memcache/DistributedClear.php @@ -0,0 +1,47 @@ +setName('memcache:distributed:clear') + ->setDescription('Clear values from the distributed memcache') + ->addOption('prefix', null, InputOption::VALUE_REQUIRED, 'Only remove keys matching the prefix'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $cache = $this->cacheFactory->createDistributed(); + $prefix = $input->getOption('prefix'); + if ($cache->clear($prefix)) { + if ($prefix) { + $output->writeln('Distributed cache matching prefix ' . $prefix . ' cleared'); + } else { + $output->writeln('Distributed cache cleared'); + } + return 0; + } else { + $output->writeln('Failed to clear cache'); + return 1; + } + } +} diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 83225a1bb5061..1c23c763bc132 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1284,6 +1284,7 @@ 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => $baseDir . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => $baseDir . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => $baseDir . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedClear' => $baseDir . '/core/Command/Memcache/DistributedClear.php', 'OC\\Core\\Command\\Memcache\\DistributedDelete' => $baseDir . '/core/Command/Memcache/DistributedDelete.php', 'OC\\Core\\Command\\Memcache\\DistributedGet' => $baseDir . '/core/Command/Memcache/DistributedGet.php', 'OC\\Core\\Command\\Memcache\\DistributedSet' => $baseDir . '/core/Command/Memcache/DistributedSet.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ef98b312d54a7..c3b87cc93d5cf 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1333,6 +1333,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => __DIR__ . '/../../..' . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedClear' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedClear.php', 'OC\\Core\\Command\\Memcache\\DistributedDelete' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedDelete.php', 'OC\\Core\\Command\\Memcache\\DistributedGet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedGet.php', 'OC\\Core\\Command\\Memcache\\DistributedSet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedSet.php', From 43e38a120fae0bdd99c169c4f780b6eefdfc5aa5 Mon Sep 17 00:00:00 2001 From: yemkareems Date: Tue, 26 Aug 2025 09:48:07 +0530 Subject: [PATCH 5/6] fix: added set/get/delete/clear to register command Signed-off-by: yemkareems --- core/register_command.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/register_command.php b/core/register_command.php index 9412562747b31..1ef6ae795fd55 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -158,6 +158,10 @@ $application->add(Server::get(Command\TaskProcessing\Statistics::class)); $application->add(Server::get(Command\Memcache\RedisCommand::class)); + $application->add(Server::get(Command\Memcache\DistributedClear::class)); + $application->add(Server::get(Command\Memcache\DistributedDelete::class)); + $application->add(Server::get(Command\Memcache\DistributedGet::class)); + $application->add(Server::get(Command\Memcache\DistributedSet::class)); } else { $application->add(Server::get(Command\Maintenance\Install::class)); } From bc64573fb51c81a8ad9bc4992b05452d6d982fba Mon Sep 17 00:00:00 2001 From: yemkareems Date: Tue, 26 Aug 2025 19:40:56 +0530 Subject: [PATCH 6/6] fix: copy SetConfig.php and SetConfigTest.php from master to backport branch Signed-off-by: yemkareems --- core/Command/Config/System/SetConfig.php | 74 +++++++++++++++++++ .../Command/Config/System/SetConfigTest.php | 9 ++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php index 1b1bdc66a6e01..df7343b86ead0 100644 --- a/core/Command/Config/System/SetConfig.php +++ b/core/Command/Config/System/SetConfig.php @@ -81,6 +81,80 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } + /** + * @param string $value + * @param string $type + * @return mixed + * @throws \InvalidArgumentException + */ + protected function castValue($value, $type) { + switch ($type) { + case 'integer': + case 'int': + if (!is_numeric($value)) { + throw new \InvalidArgumentException('Non-numeric value specified'); + } + return [ + 'value' => (int)$value, + 'readable-value' => 'integer ' . (int)$value, + ]; + + case 'double': + case 'float': + if (!is_numeric($value)) { + throw new \InvalidArgumentException('Non-numeric value specified'); + } + return [ + 'value' => (float)$value, + 'readable-value' => 'double ' . (float)$value, + ]; + + case 'boolean': + case 'bool': + $value = strtolower($value); + switch ($value) { + case 'true': + return [ + 'value' => true, + 'readable-value' => 'boolean ' . $value, + ]; + + case 'false': + return [ + 'value' => false, + 'readable-value' => 'boolean ' . $value, + ]; + + default: + throw new \InvalidArgumentException('Unable to parse value as boolean'); + } + + // no break + case 'null': + return [ + 'value' => null, + 'readable-value' => 'null', + ]; + + case 'string': + $value = (string)$value; + return [ + 'value' => $value, + 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value, + ]; + + case 'json': + $value = json_decode($value, true); + return [ + 'value' => $value, + 'readable-value' => 'json ' . json_encode($value), + ]; + + default: + throw new \InvalidArgumentException('Invalid type'); + } + } + /** * @param array $configNames * @param mixed $existingValues diff --git a/tests/Core/Command/Config/System/SetConfigTest.php b/tests/Core/Command/Config/System/SetConfigTest.php index cf44058f6703b..d7ced242eb771 100644 --- a/tests/Core/Command/Config/System/SetConfigTest.php +++ b/tests/Core/Command/Config/System/SetConfigTest.php @@ -1,4 +1,5 @@ systemConfig->expects($this->once()) ->method('setValue') ->with($configNames[0], $expectedValue); @@ -89,7 +90,7 @@ public function setUpdateOnlyProvider() { /** * @dataProvider setUpdateOnlyProvider */ - public function testSetUpdateOnly($configNames, $existingData): void { + public function testSetUpdateOnly($configNames, $existingData) { $this->expectException(\UnexpectedValueException::class); $this->systemConfig->expects($this->never()) @@ -136,7 +137,7 @@ public function castValueProvider() { /** * @dataProvider castValueProvider */ - public function testCastValue($value, $type, $expectedValue): void { + public function testCastValue($value, $type, $expectedValue) { $this->assertSame($expectedValue, $this->invokePrivate($this->command, 'castValue', [$value, $type]) ); @@ -157,7 +158,7 @@ public function castValueInvalidProvider() { /** * @dataProvider castValueInvalidProvider */ - public function testCastValueInvalid($value, $type): void { + public function testCastValueInvalid($value, $type) { $this->expectException(\InvalidArgumentException::class); $this->invokePrivate($this->command, 'castValue', [$value, $type]);