implement console
This commit is contained in:
112
bin/console
112
bin/console
@@ -2,16 +2,116 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console entry point - Symfony console has been removed.
|
* Console Entry Point
|
||||||
* Add your own CLI commands here or integrate an alternative CLI library.
|
*
|
||||||
|
* Bootstraps the application container and registers console commands
|
||||||
|
* from core and modules using lazy loading via Symfony Console.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use KTXC\Application;
|
||||||
|
use KTXC\Kernel;
|
||||||
|
use KTXC\Module\ModuleManager;
|
||||||
|
use KTXF\Module\ModuleConsoleInterface;
|
||||||
|
use Symfony\Component\Console\Application as ConsoleApplication;
|
||||||
|
use Symfony\Component\Console\Command\LazyCommand;
|
||||||
|
|
||||||
|
// Check dependencies
|
||||||
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
||||||
throw new LogicException('Dependencies are missing. Try running "composer install".');
|
fwrite(STDERR, "Dependencies are missing. Run 'composer install' first.\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once dirname(__DIR__).'/vendor/autoload.php';
|
require_once dirname(__DIR__).'/vendor/autoload.php';
|
||||||
|
|
||||||
echo "Console commands not available. Symfony console has been removed.\n";
|
try {
|
||||||
echo "To add CLI functionality, integrate an alternative CLI library.\n";
|
// Bootstrap the application
|
||||||
exit(0);
|
$projectRoot = dirname(__DIR__);
|
||||||
|
$app = new Application($projectRoot);
|
||||||
|
|
||||||
|
// Boot kernel to initialize container and modules
|
||||||
|
$app->kernel()->boot();
|
||||||
|
|
||||||
|
// Get the container
|
||||||
|
$container = $app->container();
|
||||||
|
|
||||||
|
// Create Symfony Console Application
|
||||||
|
$console = new ConsoleApplication('Ktrix Console', Kernel::VERSION);
|
||||||
|
|
||||||
|
// Collect all command classes
|
||||||
|
$commandClasses = [];
|
||||||
|
|
||||||
|
// Collect commands from modules
|
||||||
|
/** @var ModuleManager $moduleManager */
|
||||||
|
$moduleManager = $container->get(ModuleManager::class);
|
||||||
|
|
||||||
|
foreach ($moduleManager->list() as $module) {
|
||||||
|
$moduleInstance = $module->instance();
|
||||||
|
|
||||||
|
// Skip if module instance is not available
|
||||||
|
if ($moduleInstance === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if module implements console command provider
|
||||||
|
if ($moduleInstance instanceof ModuleConsoleInterface) {
|
||||||
|
try {
|
||||||
|
$commands = $moduleInstance->registerCI();
|
||||||
|
|
||||||
|
foreach ($commands as $commandClass) {
|
||||||
|
if (!class_exists($commandClass)) {
|
||||||
|
fwrite(STDERR, "Warning: Command class not found: {$commandClass}\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$commandClasses[] = $commandClass;
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
fwrite(STDERR, "Warning: Failed to load commands from module {$module->handle()}: {$e->getMessage()}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register commands using lazy loading
|
||||||
|
foreach ($commandClasses as $commandClass) {
|
||||||
|
try {
|
||||||
|
// Use reflection to read #[AsCommand] attribute without instantiation
|
||||||
|
$reflection = new \ReflectionClass($commandClass);
|
||||||
|
$attributes = $reflection->getAttributes(\Symfony\Component\Console\Attribute\AsCommand::class);
|
||||||
|
|
||||||
|
if (empty($attributes)) {
|
||||||
|
fwrite(STDERR, "Warning: Command {$commandClass} missing #[AsCommand] attribute\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get attribute instance
|
||||||
|
/** @var \Symfony\Component\Console\Attribute\AsCommand $commandAttr */
|
||||||
|
$commandAttr = $attributes[0]->newInstance();
|
||||||
|
|
||||||
|
// Create lazy command wrapper that defers instantiation
|
||||||
|
$lazyCommand = new LazyCommand(
|
||||||
|
$commandAttr->name,
|
||||||
|
[],
|
||||||
|
$commandAttr->description ?? '',
|
||||||
|
$commandAttr->hidden ?? false,
|
||||||
|
fn() => $container->get($commandClass) // Only instantiate when executed
|
||||||
|
);
|
||||||
|
|
||||||
|
$console->add($lazyCommand);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
fwrite(STDERR, "Warning: Failed to register command {$commandClass}: {$e->getMessage()}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the console application
|
||||||
|
$exitCode = $console->run();
|
||||||
|
exit($exitCode);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
fwrite(STDERR, "Fatal error: " . $e->getMessage() . "\n");
|
||||||
|
if (isset($app) && $app->debug()) {
|
||||||
|
fwrite(STDERR, $e->getTraceAsString() . "\n");
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"mongodb/mongodb": "^2.1",
|
"mongodb/mongodb": "^2.1",
|
||||||
"php-di/php-di": "*",
|
"php-di/php-di": "*",
|
||||||
"phpseclib/phpseclib": "^3.0"
|
"phpseclib/phpseclib": "^3.0",
|
||||||
|
"symfony/console": "^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^11.0"
|
"phpunit/phpunit": "^11.0"
|
||||||
|
|||||||
680
composer.lock
generated
680
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9b9f3e5ee2fe48f2f736eb5d0a74be7c",
|
"content-hash": "2798ba3263d47fe84e91ee7dfd47e310",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "laravel/serializable-closure",
|
"name": "laravel/serializable-closure",
|
||||||
@@ -604,6 +604,506 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-09-11T13:17:53+00:00"
|
"time": "2024-09-11T13:17:53+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/console",
|
||||||
|
"version": "v7.4.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/console.git",
|
||||||
|
"reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
|
||||||
|
"reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
|
"symfony/string": "^7.2|^8.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/dependency-injection": "<6.4",
|
||||||
|
"symfony/dotenv": "<6.4",
|
||||||
|
"symfony/event-dispatcher": "<6.4",
|
||||||
|
"symfony/lock": "<6.4",
|
||||||
|
"symfony/process": "<6.4"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/log-implementation": "1.0|2.0|3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/config": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/event-dispatcher": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/http-foundation": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/http-kernel": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/lock": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/messenger": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/process": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/stopwatch": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/var-dumper": "^6.4|^7.0|^8.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Console\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"cli",
|
||||||
|
"command-line",
|
||||||
|
"console",
|
||||||
|
"terminal"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/console/tree/v7.4.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-12-23T14:50:43+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/deprecation-contracts",
|
||||||
|
"version": "v3.6.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||||
|
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||||
|
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/contracts",
|
||||||
|
"name": "symfony/contracts"
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.6-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"function.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A generic function and convention to trigger deprecation notices",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-09-25T14:21:43+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-ctype",
|
||||||
|
"version": "v1.33.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
|
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
|
||||||
|
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"ext-ctype": "*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-ctype": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/polyfill",
|
||||||
|
"name": "symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Ctype\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Gert de Pagter",
|
||||||
|
"email": "BackEndTea@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for ctype functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"ctype",
|
||||||
|
"polyfill",
|
||||||
|
"portable"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-09-09T11:45:10+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-intl-grapheme",
|
||||||
|
"version": "v1.33.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||||
|
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
|
||||||
|
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-intl": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/polyfill",
|
||||||
|
"name": "symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for intl's grapheme_* functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"grapheme",
|
||||||
|
"intl",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-06-27T09:58:17+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-intl-normalizer",
|
||||||
|
"version": "v1.33.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||||
|
"reference": "3833d7255cc303546435cb650316bff708a1c75c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
|
||||||
|
"reference": "3833d7255cc303546435cb650316bff708a1c75c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-intl": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/polyfill",
|
||||||
|
"name": "symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"Resources/stubs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for intl's Normalizer class and related functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"intl",
|
||||||
|
"normalizer",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-09-09T11:45:10+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
"version": "v1.33.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
|
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||||
|
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"php": ">=7.2"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"ext-mbstring": "*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/polyfill",
|
||||||
|
"name": "symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for the Mbstring extension",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"mbstring",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-12-23T08:48:59+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php85",
|
"name": "symfony/polyfill-php85",
|
||||||
"version": "v1.33.0",
|
"version": "v1.33.0",
|
||||||
@@ -683,6 +1183,184 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-06-23T16:12:55+00:00"
|
"time": "2025-06-23T16:12:55+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/service-contracts",
|
||||||
|
"version": "v3.6.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/service-contracts.git",
|
||||||
|
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||||
|
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"psr/container": "^1.1|^2.0",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"ext-psr": "<1.1|>=2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"thanks": {
|
||||||
|
"url": "https://github.com/symfony/contracts",
|
||||||
|
"name": "symfony/contracts"
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.6-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Contracts\\Service\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Test/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Generic abstractions related to writing services",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"abstractions",
|
||||||
|
"contracts",
|
||||||
|
"decoupling",
|
||||||
|
"interfaces",
|
||||||
|
"interoperability",
|
||||||
|
"standards"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-07-15T11:30:57+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/string",
|
||||||
|
"version": "v7.4.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/string.git",
|
||||||
|
"reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003",
|
||||||
|
"reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3.0",
|
||||||
|
"symfony/polyfill-ctype": "~1.8",
|
||||||
|
"symfony/polyfill-intl-grapheme": "~1.33",
|
||||||
|
"symfony/polyfill-intl-normalizer": "~1.0",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/translation-contracts": "<2.5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/emoji": "^7.1|^8.0",
|
||||||
|
"symfony/http-client": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/intl": "^6.4|^7.0|^8.0",
|
||||||
|
"symfony/translation-contracts": "^2.5|^3.0",
|
||||||
|
"symfony/var-exporter": "^6.4|^7.0|^8.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"Resources/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\String\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"grapheme",
|
||||||
|
"i18n",
|
||||||
|
"string",
|
||||||
|
"unicode",
|
||||||
|
"utf-8",
|
||||||
|
"utf8"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/string/tree/v7.4.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/nicolas-grekas",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-11-27T13:27:24+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
|||||||
92
core/lib/Console/ModuleDisableCommand.php
Normal file
92
core/lib/Console/ModuleDisableCommand.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KTXC\Console;
|
||||||
|
|
||||||
|
use KTXC\Module\ModuleManager;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module Disable Command
|
||||||
|
*
|
||||||
|
* Disables an enabled module.
|
||||||
|
*/
|
||||||
|
#[AsCommand(
|
||||||
|
name: 'module:disable',
|
||||||
|
description: 'Disable a module',
|
||||||
|
)]
|
||||||
|
class ModuleDisableCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ModuleManager $moduleManager,
|
||||||
|
private readonly LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->addArgument('handle', InputArgument::REQUIRED, 'Module handle to disable')
|
||||||
|
->setHelp('This command disables an enabled module without uninstalling it.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$handle = $input->getArgument('handle');
|
||||||
|
|
||||||
|
$io->title('Disable Module');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Prevent disabling core module
|
||||||
|
if ($handle === 'core') {
|
||||||
|
$io->error('Cannot disable the core module.');
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the module
|
||||||
|
$modules = $this->moduleManager->list(installedOnly: true, enabledOnly: false);
|
||||||
|
$module = $modules[$handle] ?? null;
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$io->error("Module '{$handle}' not found or not installed.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$module->enabled()) {
|
||||||
|
$io->warning("Module '{$handle}' is already disabled.");
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the module
|
||||||
|
$io->text("Disabling module '{$handle}'...");
|
||||||
|
$this->moduleManager->disable($handle);
|
||||||
|
|
||||||
|
$this->logger->info('Module disabled via console', [
|
||||||
|
'handle' => $handle,
|
||||||
|
'command' => $this->getName(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$io->success("Module '{$handle}' disabled successfully!");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$io->error('Failed to disable module: ' . $e->getMessage());
|
||||||
|
$this->logger->error('Module disable failed', [
|
||||||
|
'handle' => $handle,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
core/lib/Console/ModuleEnableCommand.php
Normal file
86
core/lib/Console/ModuleEnableCommand.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KTXC\Console;
|
||||||
|
|
||||||
|
use KTXC\Module\ModuleManager;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module Enable Command
|
||||||
|
*
|
||||||
|
* Enables a disabled module.
|
||||||
|
*/
|
||||||
|
#[AsCommand(
|
||||||
|
name: 'module:enable',
|
||||||
|
description: 'Enable a module',
|
||||||
|
)]
|
||||||
|
class ModuleEnableCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ModuleManager $moduleManager,
|
||||||
|
private readonly LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->addArgument('handle', InputArgument::REQUIRED, 'Module handle to enable')
|
||||||
|
->setHelp('This command enables a previously disabled module.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$handle = $input->getArgument('handle');
|
||||||
|
|
||||||
|
$io->title('Enable Module');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Find the module
|
||||||
|
$modules = $this->moduleManager->list(installedOnly: true, enabledOnly: false);
|
||||||
|
$module = $modules[$handle] ?? null;
|
||||||
|
|
||||||
|
if (!$module) {
|
||||||
|
$io->error("Module '{$handle}' not found or not installed.");
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($module->enabled()) {
|
||||||
|
$io->warning("Module '{$handle}' is already enabled.");
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the module
|
||||||
|
$io->text("Enabling module '{$handle}'...");
|
||||||
|
$this->moduleManager->enable($handle);
|
||||||
|
|
||||||
|
$this->logger->info('Module enabled via console', [
|
||||||
|
'handle' => $handle,
|
||||||
|
'command' => $this->getName(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$io->success("Module '{$handle}' enabled successfully!");
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$io->error('Failed to enable module: ' . $e->getMessage());
|
||||||
|
$this->logger->error('Module enable failed', [
|
||||||
|
'handle' => $handle,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
core/lib/Console/ModuleListCommand.php
Normal file
86
core/lib/Console/ModuleListCommand.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KTXC\Console;
|
||||||
|
|
||||||
|
use KTXC\Module\ModuleManager;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module List Command
|
||||||
|
*
|
||||||
|
* Lists all modules with their status and version information.
|
||||||
|
*/
|
||||||
|
#[AsCommand(
|
||||||
|
name: 'module:list',
|
||||||
|
description: 'List all modules with their status and versions',
|
||||||
|
)]
|
||||||
|
class ModuleListCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ModuleManager $moduleManager
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->addOption('all', 'a', InputOption::VALUE_NONE, 'Show all modules including disabled ones')
|
||||||
|
->setHelp('This command lists all installed modules with their status and version information.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$showAll = $input->getOption('all');
|
||||||
|
|
||||||
|
$io->title('Installed Modules');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$modules = $this->moduleManager->list(
|
||||||
|
installedOnly: true,
|
||||||
|
enabledOnly: !$showAll
|
||||||
|
);
|
||||||
|
|
||||||
|
if (count($modules) === 0) {
|
||||||
|
$io->warning('No modules found.');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
$status = $module->enabled() ? '<fg=green>Enabled</>' : '<fg=yellow>Disabled</>';
|
||||||
|
$upgrade = $module->needsUpgrade() ? '<fg=red>Yes</>' : '';
|
||||||
|
|
||||||
|
$rows[] = [
|
||||||
|
$module->handle(),
|
||||||
|
$module->version(),
|
||||||
|
$status,
|
||||||
|
$upgrade,
|
||||||
|
$module->namespace() ?? 'N/A',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->table(
|
||||||
|
['Handle', 'Version', 'Status', 'Needs Upgrade', 'Namespace'],
|
||||||
|
$rows
|
||||||
|
);
|
||||||
|
|
||||||
|
$io->success(sprintf('Found %d module(s).', count($modules)));
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$io->error('Failed to list modules: ' . $e->getMessage());
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
shared/lib/Module/ModuleConsoleInterface.php
Normal file
13
shared/lib/Module/ModuleConsoleInterface.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KTXF\Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module Console Interface
|
||||||
|
*/
|
||||||
|
interface ModuleConsoleInterface
|
||||||
|
{
|
||||||
|
public function registerCI(): array;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user