Console commands are now lazy loaded

This commit is contained in:
Alejandro Celaya 2017-12-27 15:37:26 +01:00
parent a9094dc0f6
commit af0ff0f65b
19 changed files with 78 additions and 45 deletions

View File

@ -1,5 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
declare(strict_types=1);
use Interop\Container\ContainerInterface; use Interop\Container\ContainerInterface;
use Symfony\Component\Console\Application as CliApp; use Symfony\Component\Console\Application as CliApp;

View File

@ -1,14 +1,14 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
use Shlinkio\Shlink\Common; use function Shlinkio\Shlink\Common\env;
return [ return [
'app_options' => [ 'app_options' => [
'name' => 'Shlink', 'name' => 'Shlink',
'version' => '1.2.0', 'version' => '1.7.0',
'secret_key' => Common\env('SECRET_KEY'), 'secret_key' => env('SECRET_KEY'),
], ],
]; ];

View File

@ -9,21 +9,25 @@ return [
'cli' => [ 'cli' => [
'locale' => Common\env('CLI_LOCALE', 'en'), 'locale' => Common\env('CLI_LOCALE', 'en'),
'commands' => [ 'commands' => [
Command\Shortcode\GenerateShortcodeCommand::class, Command\Shortcode\GenerateShortcodeCommand::NAME => Command\Shortcode\GenerateShortcodeCommand::class,
Command\Shortcode\ResolveUrlCommand::class, Command\Shortcode\ResolveUrlCommand::NAME => Command\Shortcode\ResolveUrlCommand::class,
Command\Shortcode\ListShortcodesCommand::class, Command\Shortcode\ListShortcodesCommand::NAME => Command\Shortcode\ListShortcodesCommand::class,
Command\Shortcode\GetVisitsCommand::class, Command\Shortcode\GetVisitsCommand::NAME => Command\Shortcode\GetVisitsCommand::class,
Command\Shortcode\GeneratePreviewCommand::class, Command\Shortcode\GeneratePreviewCommand::NAME => Command\Shortcode\GeneratePreviewCommand::class,
Command\Visit\ProcessVisitsCommand::class,
Command\Config\GenerateCharsetCommand::class, Command\Visit\ProcessVisitsCommand::NAME => Command\Visit\ProcessVisitsCommand::class,
Command\Config\GenerateSecretCommand::class,
Command\Api\GenerateKeyCommand::class, Command\Config\GenerateCharsetCommand::NAME => Command\Config\GenerateCharsetCommand::class,
Command\Api\DisableKeyCommand::class, Command\Config\GenerateSecretCommand::NAME => Command\Config\GenerateSecretCommand::class,
Command\Api\ListKeysCommand::class,
Command\Tag\ListTagsCommand::class, Command\Api\GenerateKeyCommand::NAME => Command\Api\GenerateKeyCommand::class,
Command\Tag\CreateTagCommand::class, Command\Api\DisableKeyCommand::NAME => Command\Api\DisableKeyCommand::class,
Command\Tag\RenameTagCommand::class, Command\Api\ListKeysCommand::NAME => Command\Api\ListKeysCommand::class,
Command\Tag\DeleteTagsCommand::class,
Command\Tag\ListTagsCommand::NAME => Command\Tag\ListTagsCommand::class,
Command\Tag\CreateTagCommand::NAME => Command\Tag\CreateTagCommand::class,
Command\Tag\RenameTagCommand::NAME => Command\Tag\RenameTagCommand::class,
Command\Tag\DeleteTagsCommand::NAME => Command\Tag\DeleteTagsCommand::class,
], ],
], ],

View File

@ -12,6 +12,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class DisableKeyCommand extends Command class DisableKeyCommand extends Command
{ {
const NAME = 'api-key:disable';
/** /**
* @var ApiKeyServiceInterface * @var ApiKeyServiceInterface
*/ */
@ -30,7 +32,7 @@ class DisableKeyCommand extends Command
public function configure() public function configure()
{ {
$this->setName('api-key:disable') $this->setName(self::NAME)
->setDescription($this->translator->translate('Disables an API key.')) ->setDescription($this->translator->translate('Disables an API key.'))
->addArgument('apiKey', InputArgument::REQUIRED, $this->translator->translate('The API key to disable')); ->addArgument('apiKey', InputArgument::REQUIRED, $this->translator->translate('The API key to disable'));
} }

View File

@ -12,6 +12,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class GenerateKeyCommand extends Command class GenerateKeyCommand extends Command
{ {
const NAME = 'api-key:generate';
/** /**
* @var ApiKeyServiceInterface * @var ApiKeyServiceInterface
*/ */
@ -30,7 +32,7 @@ class GenerateKeyCommand extends Command
public function configure() public function configure()
{ {
$this->setName('api-key:generate') $this->setName(self::NAME)
->setDescription($this->translator->translate('Generates a new valid API key.')) ->setDescription($this->translator->translate('Generates a new valid API key.'))
->addOption( ->addOption(
'expirationDate', 'expirationDate',

View File

@ -14,6 +14,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class ListKeysCommand extends Command class ListKeysCommand extends Command
{ {
const NAME = 'api-key:list';
/** /**
* @var ApiKeyServiceInterface * @var ApiKeyServiceInterface
*/ */
@ -32,7 +34,7 @@ class ListKeysCommand extends Command
public function configure() public function configure()
{ {
$this->setName('api-key:list') $this->setName(self::NAME)
->setDescription($this->translator->translate('Lists all the available API keys.')) ->setDescription($this->translator->translate('Lists all the available API keys.'))
->addOption( ->addOption(
'enabledOnly', 'enabledOnly',

View File

@ -11,6 +11,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class GenerateCharsetCommand extends Command class GenerateCharsetCommand extends Command
{ {
const NAME = 'config:generate-charset';
/** /**
* @var TranslatorInterface * @var TranslatorInterface
*/ */
@ -24,7 +26,7 @@ class GenerateCharsetCommand extends Command
public function configure() public function configure()
{ {
$this->setName('config:generate-charset') $this->setName(self::NAME)
->setDescription(sprintf($this->translator->translate( ->setDescription(sprintf($this->translator->translate(
'Generates a character set sample just by shuffling the default one, "%s". ' 'Generates a character set sample just by shuffling the default one, "%s". '
. 'Then it can be set in the SHORTCODE_CHARS environment variable' . 'Then it can be set in the SHORTCODE_CHARS environment variable'

View File

@ -13,6 +13,8 @@ class GenerateSecretCommand extends Command
{ {
use StringUtilsTrait; use StringUtilsTrait;
const NAME = 'config:generate-secret';
/** /**
* @var TranslatorInterface * @var TranslatorInterface
*/ */
@ -26,7 +28,7 @@ class GenerateSecretCommand extends Command
public function configure() public function configure()
{ {
$this->setName('config:generate-secret') $this->setName(self::NAME)
->setDescription($this->translator->translate( ->setDescription($this->translator->translate(
'Generates a random secret string that can be used for JWT token encryption' 'Generates a random secret string that can be used for JWT token encryption'
)); ));

View File

@ -13,6 +13,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class GeneratePreviewCommand extends Command class GeneratePreviewCommand extends Command
{ {
const NAME = 'shortcode:process-previews';
/** /**
* @var PreviewGeneratorInterface * @var PreviewGeneratorInterface
*/ */
@ -39,7 +41,7 @@ class GeneratePreviewCommand extends Command
public function configure() public function configure()
{ {
$this->setName('shortcode:process-previews') $this->setName(self::NAME)
->setDescription( ->setDescription(
$this->translator->translate( $this->translator->translate(
'Processes and generates the previews for every URL, improving performance for later web requests.' 'Processes and generates the previews for every URL, improving performance for later web requests.'

View File

@ -18,6 +18,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class GenerateShortcodeCommand extends Command class GenerateShortcodeCommand extends Command
{ {
const NAME = 'shortcode:generate';
/** /**
* @var UrlShortenerInterface * @var UrlShortenerInterface
*/ */
@ -44,7 +46,7 @@ class GenerateShortcodeCommand extends Command
public function configure() public function configure()
{ {
$this->setName('shortcode:generate') $this->setName(self::NAME)
->setDescription( ->setDescription(
$this->translator->translate('Generates a short code for provided URL and returns the short URL') $this->translator->translate('Generates a short code for provided URL and returns the short URL')
) )

View File

@ -17,6 +17,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class GetVisitsCommand extends Command class GetVisitsCommand extends Command
{ {
const NAME = 'shortcode:visits';
/** /**
* @var VisitsTrackerInterface * @var VisitsTrackerInterface
*/ */
@ -35,7 +37,7 @@ class GetVisitsCommand extends Command
public function configure() public function configure()
{ {
$this->setName('shortcode:visits') $this->setName(self::NAME)
->setDescription( ->setDescription(
$this->translator->translate('Returns the detailed visits information for provided short code') $this->translator->translate('Returns the detailed visits information for provided short code')
) )

View File

@ -19,6 +19,8 @@ class ListShortcodesCommand extends Command
{ {
use PaginatorUtilsTrait; use PaginatorUtilsTrait;
const NAME = 'shortcode:list';
/** /**
* @var ShortUrlServiceInterface * @var ShortUrlServiceInterface
*/ */
@ -37,7 +39,7 @@ class ListShortcodesCommand extends Command
public function configure() public function configure()
{ {
$this->setName('shortcode:list') $this->setName(self::NAME)
->setDescription($this->translator->translate('List all short URLs')) ->setDescription($this->translator->translate('List all short URLs'))
->addOption( ->addOption(
'page', 'page',

View File

@ -16,6 +16,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class ResolveUrlCommand extends Command class ResolveUrlCommand extends Command
{ {
const NAME = 'shortcode:parse';
/** /**
* @var UrlShortenerInterface * @var UrlShortenerInterface
*/ */
@ -34,7 +36,7 @@ class ResolveUrlCommand extends Command
public function configure() public function configure()
{ {
$this->setName('shortcode:parse') $this->setName(self::NAME)
->setDescription($this->translator->translate('Returns the long URL behind a short code')) ->setDescription($this->translator->translate('Returns the long URL behind a short code'))
->addArgument( ->addArgument(
'shortCode', 'shortCode',

View File

@ -12,6 +12,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class CreateTagCommand extends Command class CreateTagCommand extends Command
{ {
const NAME = 'tag:create';
/** /**
* @var TagServiceInterface * @var TagServiceInterface
*/ */
@ -31,7 +33,7 @@ class CreateTagCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('tag:create') ->setName(self::NAME)
->setDescription($this->translator->translate('Creates one or more tags.')) ->setDescription($this->translator->translate('Creates one or more tags.'))
->addOption( ->addOption(
'name', 'name',

View File

@ -12,6 +12,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class DeleteTagsCommand extends Command class DeleteTagsCommand extends Command
{ {
const NAME = 'tag:delete';
/** /**
* @var TagServiceInterface * @var TagServiceInterface
*/ */
@ -31,7 +33,7 @@ class DeleteTagsCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('tag:delete') ->setName(self::NAME)
->setDescription($this->translator->translate('Deletes one or more tags.')) ->setDescription($this->translator->translate('Deletes one or more tags.'))
->addOption( ->addOption(
'name', 'name',

View File

@ -13,6 +13,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class ListTagsCommand extends Command class ListTagsCommand extends Command
{ {
const NAME = 'tag:list';
/** /**
* @var TagServiceInterface * @var TagServiceInterface
*/ */
@ -32,7 +34,7 @@ class ListTagsCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('tag:list') ->setName(self::NAME)
->setDescription($this->translator->translate('Lists existing tags.')); ->setDescription($this->translator->translate('Lists existing tags.'));
} }

View File

@ -13,6 +13,8 @@ use Zend\I18n\Translator\TranslatorInterface;
class RenameTagCommand extends Command class RenameTagCommand extends Command
{ {
const NAME = 'tag:rename';
/** /**
* @var TagServiceInterface * @var TagServiceInterface
*/ */
@ -32,7 +34,7 @@ class RenameTagCommand extends Command
protected function configure() protected function configure()
{ {
$this $this
->setName('tag:rename') ->setName(self::NAME)
->setDescription($this->translator->translate('Renames one existing tag.')) ->setDescription($this->translator->translate('Renames one existing tag.'))
->addArgument('oldName', InputArgument::REQUIRED, $this->translator->translate('Current name of the tag.')) ->addArgument('oldName', InputArgument::REQUIRED, $this->translator->translate('Current name of the tag.'))
->addArgument('newName', InputArgument::REQUIRED, $this->translator->translate('New name of the tag.')); ->addArgument('newName', InputArgument::REQUIRED, $this->translator->translate('New name of the tag.'));

View File

@ -15,6 +15,7 @@ use Zend\I18n\Translator\TranslatorInterface;
class ProcessVisitsCommand extends Command class ProcessVisitsCommand extends Command
{ {
const LOCALHOST = '127.0.0.1'; const LOCALHOST = '127.0.0.1';
const NAME = 'visit:process';
/** /**
* @var VisitServiceInterface * @var VisitServiceInterface
@ -42,7 +43,7 @@ class ProcessVisitsCommand extends Command
public function configure() public function configure()
{ {
$this->setName('visit:process') $this->setName(self::NAME)
->setDescription( ->setDescription(
$this->translator->translate('Processes visits where location is not set yet') $this->translator->translate('Processes visits where location is not set yet')
); );

View File

@ -5,8 +5,11 @@ namespace Shlinkio\Shlink\CLI\Factory;
use Interop\Container\ContainerInterface; use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException; use Interop\Container\Exception\ContainerException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Core\Options\AppOptions;
use Symfony\Component\Console\Application as CliApp; use Symfony\Component\Console\Application as CliApp;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Zend\I18n\Translator\Translator; use Zend\I18n\Translator\Translator;
use Zend\ServiceManager\Exception\ServiceNotCreatedException; use Zend\ServiceManager\Exception\ServiceNotCreatedException;
use Zend\ServiceManager\Exception\ServiceNotFoundException; use Zend\ServiceManager\Exception\ServiceNotFoundException;
@ -20,28 +23,23 @@ class ApplicationFactory implements FactoryInterface
* @param ContainerInterface $container * @param ContainerInterface $container
* @param string $requestedName * @param string $requestedName
* @param null|array $options * @param null|array $options
* @return object * @return CliApp
* @throws NotFoundExceptionInterface
* @throws ContainerExceptionInterface
* @throws ServiceNotFoundException if unable to resolve the service. * @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when * @throws ServiceNotCreatedException if an exception is raised when creating a service.
* creating a service.
* @throws ContainerException if any other error occurs * @throws ContainerException if any other error occurs
*/ */
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) public function __invoke(ContainerInterface $container, $requestedName, array $options = null): CliApp
{ {
$config = $container->get('config')['cli']; $config = $container->get('config')['cli'];
$appOptions = $container->get(AppOptions::class); $appOptions = $container->get(AppOptions::class);
$translator = $container->get(Translator::class); $translator = $container->get(Translator::class);
$translator->setLocale($config['locale']); $translator->setLocale($config['locale']);
$commands = isset($config['commands']) ? $config['commands'] : []; $commands = $config['commands'] ?? [];
$app = new CliApp($appOptions->getName(), $appOptions->getVersion()); $app = new CliApp($appOptions->getName(), $appOptions->getVersion());
foreach ($commands as $command) { $app->setCommandLoader(new ContainerCommandLoader($container, $commands));
if (! $container->has($command)) {
continue;
}
$app->add($container->get($command));
}
return $app; return $app;
} }