diff --git a/administrator/components/com_installer/src/Model/DiscoverModel.php b/administrator/components/com_installer/src/Model/DiscoverModel.php index e33a3937e95aa..349592d64b4a0 100644 --- a/administrator/components/com_installer/src/Model/DiscoverModel.php +++ b/administrator/components/com_installer/src/Model/DiscoverModel.php @@ -87,7 +87,7 @@ protected function populateState($ordering = 'name', $direction = 'asc') /** * Method to get the database query. * - * @return DatabaseQuery the database query + * @return DatabaseQuery The database query * * @since 3.1 */ @@ -147,7 +147,7 @@ protected function getListQuery() * * Finds uninstalled extensions * - * @return void + * @return int The count of discovered extensions * * @since 1.6 */ @@ -173,6 +173,8 @@ public function discover() $extensions[$key] = $install; } + $count = 0; + foreach ($results as $result) { // Check if we have a match on the element @@ -183,8 +185,11 @@ public function discover() // Put it into the table $result->check(); $result->store(); + $count++; } } + + return $count; } /** diff --git a/libraries/src/Console/ExtensionDiscoverCommand.php b/libraries/src/Console/ExtensionDiscoverCommand.php new file mode 100644 index 0000000000000..e6c5955bcfdfa --- /dev/null +++ b/libraries/src/Console/ExtensionDiscoverCommand.php @@ -0,0 +1,166 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +\defined('JPATH_PLATFORM') or die; + +use Joomla\CMS\Installer\Installer; +use Joomla\Component\Installer\Administrator\Model\DiscoverModel; +use Joomla\Console\Command\AbstractCommand; +use Joomla\Database\DatabaseInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Console command for discovering extensions + * + * @since __DEPLOY_VERSION__ + */ +class ExtensionDiscoverCommand extends AbstractCommand +{ + /** + * The default command name + * + * @var string + * + * @since __DEPLOY_VERSION__ + */ + protected static $defaultName = 'extension:discover'; + + /** + * Stores the Input Object + * + * @var InputInterface + * + * @since __DEPLOY_VERSION__ + */ + private $cliInput; + + /** + * SymfonyStyle Object + * + * @var SymfonyStyle + * + * @since __DEPLOY_VERSION__ + */ + private $ioStyle; + + /** + * Instantiate the command. + * + * @since __DEPLOY_VERSION__ + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Configures the IO + * + * @param InputInterface $input Console Input + * @param OutputInterface $output Console Output + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + */ + private function configureIO(InputInterface $input, OutputInterface $output): void + { + $this->cliInput = $input; + $this->ioStyle = new SymfonyStyle($input, $output); + } + + /** + * Initialise the command. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function configure(): void + { + $help = "%command.name% is used to discover extensions + \nUsage: + \n php %command.full_name%"; + + $this->setDescription('Discover extensions'); + $this->setHelp($help); + } + + /** + * Used for discovering extensions + * + * @return integer The count of discovered extensions + * + * @throws \Exception + * + * @since __DEPLOY_VERSION__ + */ + public function processDiscover(): int + { + $app = $this->getApplication(); + + $mvcFactory = $app->bootComponent('com_installer')->getMVCFactory(); + + $model = $mvcFactory->createModel('Discover', 'Administrator'); + + return $model->discover(); + } + + /** + * Used for finding the text for the note + * + * @param int $count The count of installed Extensions + * + * @return string The text for the note + * + * @since __DEPLOY_VERSION__ + */ + public function getNote(int $count): string + { + if ($count < 1) + { + return 'No extensions were discovered.'; + } + elseif ($count === 1) + { + return $count . ' extension has been discovered.'; + } + else + { + return $count . ' extensions have been discovered.'; + } + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since __DEPLOY_VERSION__ + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + + $count = $this->processDiscover(); + + $this->ioStyle->note($this->getNote($count)); + + return Command::SUCCESS; + } +} diff --git a/libraries/src/Console/ExtensionDiscoverInstallCommand.php b/libraries/src/Console/ExtensionDiscoverInstallCommand.php index 85bd804ae3cdb..dcfdb6d795b76 100644 --- a/libraries/src/Console/ExtensionDiscoverInstallCommand.php +++ b/libraries/src/Console/ExtensionDiscoverInstallCommand.php @@ -13,6 +13,7 @@ use Joomla\CMS\Installer\Installer; use Joomla\Console\Command\AbstractCommand; use Joomla\Database\DatabaseInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -31,7 +32,7 @@ class ExtensionDiscoverInstallCommand extends AbstractCommand * @var string * @since __DEPLOY_VERSION__ */ - protected static $defaultName = 'extension:discoverinstall'; + protected static $defaultName = 'extension:discover:install'; /** * Stores the Input Object @@ -53,23 +54,10 @@ class ExtensionDiscoverInstallCommand extends AbstractCommand * Database connector * * @var DatabaseInterface - * @since 4.0.0 - */ - private $db; - - /** - * Exit Code For Discover Failure - * - * @since __DEPLOY_VERSION__ - */ - public const DISCOVER_FAILED = 1; - - /** - * Exit Code For Discover Success * * @since __DEPLOY_VERSION__ */ - public const DISCOVER_SUCCESSFUL = 0; + private $db; /** * Instantiate the command. @@ -115,10 +103,11 @@ protected function configure(): void $help = "%command.name% is used to discover extensions \nYou can provide the following option to the command: \n --eid: The ID of the extension + \n If you do not provide a ID all discovered extensions are installed. \nUsage: \n php %command.full_name% --eid="; - $this->setDescription('Discover and install all extensions or a specified extension'); + $this->setDescription('Install discovered extensions'); $this->setHelp($help); } @@ -127,19 +116,19 @@ protected function configure(): void * * @param string $eid Id of the extension * - * @return boolean + * @return integer The count of installed extensions * * @throws \Exception * @since __DEPLOY_VERSION__ */ - public function processDiscover($eid): bool + public function processDiscover($eid): int { $jInstaller = new Installer; - $result = true; + $count = 0; if ($eid === -1) { - $db = $this->db; + $db = $this->db; $query = $db->getQuery(true) ->select($db->quoteName(['extension_id'])) ->from($db->quoteName('#__extensions')) @@ -151,21 +140,71 @@ public function processDiscover($eid): bool { if (!$jInstaller->discover_install($eidToDiscover->extension_id)) { - $this->ioStyle->warning('There was a problem installing the extension with ID ' . $eidToDiscover->extension_id . '.'); - $result = false; + return -1; } + + $count++; } if (empty($eidsToDiscover)) { - $this->ioStyle->warning('There is no extension to discover and install.'); + return 0; + } + } + else + { + if ($jInstaller->discover_install($eid)) + { + return 1; + } + else + { + return -1; } + } + + return $count; + } - return $result; + /** + * Used for finding the text for the note + * + * @param int $count Number of extensions to install + * @param int $eid ID of the extension or -1 if no special + * + * @return string The text for the note + * + * @since __DEPLOY_VERSION__ + */ + public function getNote(int $count, int $eid): string + { + if ($count < 0 && $eid >= 0) + { + return 'Unable to install the extension with ID ' . $eid; + } + elseif ($count < 0 && $eid < 0) + { + return 'Unable to install discovered extensions.'; + } + elseif ($count === 0) + { + return 'There are no pending discovered extensions for install. Perhaps you need to run extension:discover first?'; + } + elseif ($count === 1 && $eid > 0) + { + return 'Extension with ID ' . $eid . ' installed successfully.'; + } + elseif ($count === 1 && $eid < 0) + { + return $count . ' discovered extension has been installed.'; + } + elseif ($count > 1 && $eid < 0) + { + return $count . ' discovered extensions have been installed.'; } else { - return $jInstaller->discover_install($eid); + return 'The return value is not possible and has to be checked.'; } } @@ -177,7 +216,6 @@ public function processDiscover($eid): bool * * @return integer The command exit code * - * @throws \Exception * @since __DEPLOY_VERSION__ */ protected function doExecute(InputInterface $input, OutputInterface $output): int @@ -188,31 +226,42 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in { $result = $this->processDiscover($eid); - if (!$result) + if ($result === -1) { - $this->ioStyle->error('Unable to discover and install the extension with ID ' . $eid); + $this->ioStyle->error($this->getNote($result, $eid)); - return self::DISCOVER_FAILED; + return Command::FAILURE; } + else + { + $this->ioStyle->success($this->getNote($result, $eid)); - $this->ioStyle->success('Extension with ID ' . $eid . ' discovered and installed successfully.'); - - return self::DISCOVER_SUCCESSFUL; + return Command::SUCCESS; + } } else { $result = $this->processDiscover(-1); - if (!$result) + if ($result < 0) + { + $this->ioStyle->error($this->getNote($result, -1)); + + return Command::FAILURE; + } + elseif ($result === 0) { - $this->ioStyle->error('Unable to discover and install all extensions'); + $this->ioStyle->note($this->getNote($result, -1)); - return self::DISCOVER_FAILED; + return Command::SUCCESS; } - $this->ioStyle->success('All extensions discovered and installed successfully.'); + else + { + $this->ioStyle->note($this->getNote($result, -1)); - return self::DISCOVER_SUCCESSFUL; + return Command::SUCCESS; + } } } } diff --git a/libraries/src/Console/ExtensionDiscoverListCommand.php b/libraries/src/Console/ExtensionDiscoverListCommand.php new file mode 100644 index 0000000000000..2ccea39f6c47c --- /dev/null +++ b/libraries/src/Console/ExtensionDiscoverListCommand.php @@ -0,0 +1,109 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +\defined('JPATH_PLATFORM') or die; + +use Joomla\Console\Command\AbstractCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Console command for list discovered extensions + * + * @since __DEPLOY_VERSION__ + */ +class ExtensionDiscoverListCommand extends ExtensionsListCommand +{ + /** + * The default command name + * + * @var string + * + * @since __DEPLOY_VERSION__ + */ + protected static $defaultName = 'extension:discover:list'; + + /** + * Initialise the command. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function configure(): void + { + $help = "%command.name% is used to list all extensions that could be installed via discoverinstall + \nUsage: + \n php %command.full_name%"; + + $this->setDescription('List discovered extensions'); + $this->setHelp($help); + } + + /** + * Filters the extension state + * + * @param array $extensions The Extensions + * @param string $state The Extension state + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function filterExtensionsBasedOnState($extensions, $state): array + { + $filteredExtensions = []; + + foreach ($extensions as $key => $extension) + { + if ($extension['state'] === $state) + { + $filteredExtensions[] = $extension; + } + } + + return $filteredExtensions; + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since __DEPLOY_VERSION__ + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + + $extensions = $this->getExtensions(); + $state = -1; + + $discovered_extensions = $this->filterExtensionsBasedOnState($extensions, $state); + + if (empty($discovered_extensions)) + { + $this->ioStyle->note("There are no pending discovered extensions to install. Perhaps you need to run extension:discover first?"); + + return Command::SUCCESS; + } + + $discovered_extensions = $this->getExtensionsNameAndId($discovered_extensions); + + $this->ioStyle->title('Discovered extensions.'); + $this->ioStyle->table(['Name', 'Extension ID', 'Version', 'Type', 'Active'], $discovered_extensions); + + return Command::SUCCESS; + } +} diff --git a/libraries/src/Console/ExtensionsListCommand.php b/libraries/src/Console/ExtensionsListCommand.php index bd1ddd7af3502..2142facdfc2ca 100644 --- a/libraries/src/Console/ExtensionsListCommand.php +++ b/libraries/src/Console/ExtensionsListCommand.php @@ -38,21 +38,21 @@ class ExtensionsListCommand extends AbstractCommand * @var array * @since 4.0 */ - private $extensions; + protected $extensions; /** * Stores the Input Object * @var InputInterface * @since 4.0 */ - private $cliInput; + protected $cliInput; /** * SymfonyStyle Object * @var SymfonyStyle * @since 4.0 */ - private $ioStyle; + protected $ioStyle; /** * Database connector @@ -86,7 +86,7 @@ public function __construct(DatabaseInterface $db) * @since 4.0 * */ - private function configureIO(InputInterface $input, OutputInterface $output): void + protected function configureIO(InputInterface $input, OutputInterface $output): void { $this->cliInput = $input; $this->ioStyle = new SymfonyStyle($input, $output); @@ -179,7 +179,7 @@ private function getAllExtensionsFromDB(): array * * @since 4.0 */ - private function getExtensionsNameAndId($extensions): array + protected function getExtensionsNameAndId($extensions): array { $extInfo = []; diff --git a/libraries/src/Service/Provider/Application.php b/libraries/src/Service/Provider/Application.php index 66514d6d2b59f..2fa5c893185bc 100644 --- a/libraries/src/Service/Provider/Application.php +++ b/libraries/src/Service/Provider/Application.php @@ -17,7 +17,9 @@ use Joomla\CMS\Application\SiteApplication; use Joomla\CMS\Console\CheckJoomlaUpdatesCommand; use Joomla\CMS\Console\ExtensionInstallCommand; +use Joomla\CMS\Console\ExtensionDiscoverCommand; use Joomla\CMS\Console\ExtensionDiscoverInstallCommand; +use Joomla\CMS\Console\ExtensionDiscoverListCommand; use Joomla\CMS\Console\ExtensionRemoveCommand; use Joomla\CMS\Console\ExtensionsListCommand; use Joomla\CMS\Console\FinderIndexCommand; @@ -158,7 +160,9 @@ function (Container $container) CheckJoomlaUpdatesCommand::getDefaultName() => CheckJoomlaUpdatesCommand::class, ExtensionRemoveCommand::getDefaultName() => ExtensionRemoveCommand::class, ExtensionInstallCommand::getDefaultName() => ExtensionInstallCommand::class, + ExtensionDiscoverCommand::getDefaultName() => ExtensionDiscoverCommand::class, ExtensionDiscoverInstallCommand::getDefaultName() => ExtensionDiscoverInstallCommand::class, + ExtensionDiscoverListCommand::getDefaultName() => ExtensionDiscoverListCommand::class, UpdateCoreCommand::getDefaultName() => UpdateCoreCommand::class, FinderIndexCommand::getDefaultName() => FinderIndexCommand::class, ]; diff --git a/libraries/src/Service/Provider/Console.php b/libraries/src/Service/Provider/Console.php index 9aee01df2ea9f..acf6a6aea6cc3 100644 --- a/libraries/src/Service/Provider/Console.php +++ b/libraries/src/Service/Provider/Console.php @@ -13,7 +13,9 @@ use Joomla\CMS\Console\CheckJoomlaUpdatesCommand; use Joomla\CMS\Console\ExtensionInstallCommand; +use Joomla\CMS\Console\ExtensionDiscoverCommand; use Joomla\CMS\Console\ExtensionDiscoverInstallCommand; +use Joomla\CMS\Console\ExtensionDiscoverListCommand; use Joomla\CMS\Console\ExtensionRemoveCommand; use Joomla\CMS\Console\ExtensionsListCommand; use Joomla\CMS\Console\FinderIndexCommand; @@ -163,6 +165,15 @@ function (Container $container) true ); + $container->share( + ExtensionDiscoverCommand::class, + function (Container $container) + { + return new ExtensionDiscoverCommand; + }, + true + ); + $container->share( ExtensionDiscoverInstallCommand::class, function (Container $container) @@ -172,6 +183,15 @@ function (Container $container) true ); + $container->share( + ExtensionDiscoverListCommand::class, + function (Container $container) + { + return new ExtensionDiscoverListCommand($container->get('db')); + }, + true + ); + $container->share( UpdateCoreCommand::class, function (Container $container) diff --git a/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverCommandTest.php b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverCommandTest.php new file mode 100644 index 0000000000000..59bacd5753b95 --- /dev/null +++ b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverCommandTest.php @@ -0,0 +1,83 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +namespace Joomla\Tests\Unit\Libraries\Cms\Console; + +use Joomla\CMS\Console\ExtensionDiscoverCommand; + +/** + * Test class for Joomla\CMS\Console\ExtensionDiscoverCommand. + * + * @since __DEPLOY_VERSION__ + */ +class ExtensionDiscoverCommandTest extends \PHPUnit\Framework\TestCase +{ + /** + * Tests the constructor + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testIsConstructable() + { + $this->assertInstanceOf(ExtensionDiscoverCommand::class, $this->createExtensionDiscoverCommand()); + } + + /** + * Tests the processDiscover method + * Ensure that the return value is an integer. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testProcessDiscoverReturnIsInt() + { + $command = $this->createMock(ExtensionDiscoverCommand::class); + + $countOfDiscoveredExtensions = $command->processDiscover(); + + $this->assertIsInt($countOfDiscoveredExtensions); + } + + /** + * Tests the getNote method + * Ensure that the note is correct. + * + * @param int $count Number of extensions to discover + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testGetNote() + { + $command = $this->createExtensionDiscoverCommand(); + + $note0 = $command->getNote(0); + $note1 = $command->getNote(1); + $note2 = $command->getNote(2); + + $this->assertSame($note0, 'No extensions were discovered.'); + $this->assertSame($note1, '1 extension has been discovered.'); + $this->assertSame($note2, '2 extensions have been discovered.'); + } + + /** + * Helper function to create a ExtensionDiscoverCommand + * + * @return ExtensionDiscoverCommand + * + * @since __DEPLOY_VERSION__ + */ + protected function createExtensionDiscoverCommand(): ExtensionDiscoverCommand + { + return new ExtensionDiscoverCommand; + } +} diff --git a/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverInstallCommandTest.php b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverInstallCommandTest.php new file mode 100644 index 0000000000000..eb5790c12f86e --- /dev/null +++ b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverInstallCommandTest.php @@ -0,0 +1,96 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +namespace Joomla\Tests\Unit\Libraries\Cms\Console; + +use Joomla\CMS\Console\ExtensionDiscoverInstallCommand; +use Joomla\Database\DatabaseInterface; + +/** + * Test class for Joomla\CMS\Console\ExtensionDiscoverInstallCommand. + * + * @since __DEPLOY_VERSION__ + */ +class ExtensionDiscoverInstallCommandTest extends \PHPUnit\Framework\TestCase +{ + /** + * Tests the constructor + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testIsConstructable() + { + $this->assertInstanceOf(ExtensionDiscoverInstallCommand::class, $this->createExtensionDiscoverInstallCommand()); + } + + /** + * Tests the processDiscover method + * Ensure that the return value is an integer. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testProcessDiscoverReturnIsInt() + { + $command = $this->createMock(ExtensionDiscoverInstallCommand::class); + + $countOfDiscoveredExtensions1 = $command->processDiscover(-1); + $countOfDiscoveredExtensions0 = $command->processDiscover(0); + $countOfDiscoveredExtensions245 = $command->processDiscover(245); + + $this->assertIsInt($countOfDiscoveredExtensions1); + $this->assertIsInt($countOfDiscoveredExtensions0); + $this->assertIsInt($countOfDiscoveredExtensions245); + } + + /** + * Tests the getNote method + * Ensure that the note is correct. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testGetNote() + { + $command = $this->createExtensionDiscoverInstallCommand(); + + $note0 = $command->getNote(-1, 1); + $note1 = $command->getNote(-1, -1); + $note2 = $command->getNote(0, 1); + $note3 = $command->getNote(1, 1); + $note4 = $command->getNote(1, -1); + $note5 = $command->getNote(2, -1); + $note6 = $command->getNote(2, 1); + + $this->assertSame($note0, 'Unable to install the extension with ID 1'); + $this->assertSame($note1, 'Unable to install discovered extensions.'); + $this->assertSame($note2, 'There are no pending discovered extensions for install. Perhaps you need to run extension:discover first?'); + $this->assertSame($note3, 'Extension with ID 1 installed successfully.'); + $this->assertSame($note4, '1 discovered extension has been installed.'); + $this->assertSame($note5, '2 discovered extensions have been installed.'); + $this->assertSame($note6, 'The return value is not possible and has to be checked.'); + } + + /** + * Helper function to create a ExtensionDiscoverInstallCommand + * + * @return ExtensionDiscoverInstallCommand + * + * @since __DEPLOY_VERSION__ + */ + protected function createExtensionDiscoverInstallCommand(): ExtensionDiscoverInstallCommand + { + $db = $this->createMock(DatabaseInterface::class); + + return new ExtensionDiscoverInstallCommand($db); + } +} diff --git a/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverListCommandTest.php b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverListCommandTest.php new file mode 100644 index 0000000000000..06433527b6fc7 --- /dev/null +++ b/tests/Unit/Libraries/Cms/Console/ExtensionDiscoverListCommandTest.php @@ -0,0 +1,88 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +namespace Joomla\Tests\Unit\Libraries\Cms\Console; + +use Joomla\CMS\Console\ExtensionDiscoverListCommand; +use Joomla\Database\DatabaseInterface; + +/** + * Test class for Joomla\CMS\Console\ExtensionDiscoverCommand. + * + * @since __DEPLOY_VERSION__ + */ +class ExtensionDiscoverListCommandTest extends \PHPUnit\Framework\TestCase +{ + /** + * Tests the constructor + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testIsConstructable() + { + $this->assertInstanceOf(ExtensionDiscoverListCommand::class, $this->createExtensionDiscoverListCommand()); + } + + /** + * Tests the filterExtensionsBasedOnState method + * Ensure that the return value is an array and the filter works correcly. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function testFilterExtensions() + { + $command = $this->createExtensionDiscoverListCommand(); + + $state = -1; + + $extensions0 = array(); + $extensions0[0] = array('state' => 0); + $extensions0[1] = array('state' => 0); + + $extensions1 = array(); + $extensions1[0] = array('state' => 0); + $extensions1[1] = array('state' => -1); + + $extensions2 = array(); + $extensions2[0] = array('state' => -1); + $extensions2[1] = array('state' => -1); + + $filteredextensionsArray0 = $command->filterExtensionsBasedOnState($extensions0, $state); + $filteredextensionsArray1 = $command->filterExtensionsBasedOnState($extensions1, $state); + $filteredextensionsArray2 = $command->filterExtensionsBasedOnState($extensions2, $state); + + $size0 = sizeof($filteredextensionsArray0); + $size1 = sizeof($filteredextensionsArray1); + $size2 = sizeof($filteredextensionsArray2); + + $this->assertSame($size0, 0); + $this->assertSame($size1, 1); + $this->assertSame($size2, 2); + + $this->assertIsArray($filteredextensionsArray0); + $this->assertIsArray($filteredextensionsArray1); + $this->assertIsArray($filteredextensionsArray2); + } + + /** + * Helper function to create a ExtensionDiscoverCommand + * + * @return ExtensionDiscoverCommand + * + * @since __DEPLOY_VERSION__ + */ + protected function createExtensionDiscoverListCommand(): ExtensionDiscoverListCommand + { + $db = $this->createMock(DatabaseInterface::class); + return new ExtensionDiscoverListCommand($db); + } +}