diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..c08baeb75 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +## CHANGELOG + +### 0.2.0 + +**Enhancements:** + +* [9: Use symfony/console to dispatch console requests, instead of trying to integrate the process with expressive](https://github.com/acelaya/url-shortener/issues/9) +* [8: Create a REST API](https://github.com/acelaya/url-shortener/issues/8) +* [10: Add more CLI functionality](https://github.com/acelaya/url-shortener/issues/10) + +**Tasks** + +* [5: Create CHANGELOG file](https://github.com/acelaya/url-shortener/issues/5) diff --git a/bin/cli b/bin/cli index 1816b80fa..e400bef8c 100755 --- a/bin/cli +++ b/bin/cli @@ -1,14 +1,10 @@ #!/usr/bin/env php addCommands([ - $container->get(GenerateShortcodeCommand::class), -]); +$app = $container->get(CliApp::class); $app->run(); diff --git a/config/autoload/cli.global.php b/config/autoload/cli.global.php new file mode 100644 index 000000000..1276cc9e4 --- /dev/null +++ b/config/autoload/cli.global.php @@ -0,0 +1,15 @@ + [ + 'commands' => [ + Command\GenerateShortcodeCommand::class, + Command\ResolveUrlCommand::class, + Command\ListShortcodesCommand::class, + Command\GetVisitsCommand::class, + ] + ], + +]; diff --git a/config/autoload/services.global.php b/config/autoload/services.global.php index b08229e75..4d6cc40e3 100644 --- a/config/autoload/services.global.php +++ b/config/autoload/services.global.php @@ -1,5 +1,5 @@ [ 'factories' => [ - Application::class => Container\ApplicationFactory::class, + Expressive\Application::class => Container\ApplicationFactory::class, + Console\Application::class => CLI\Factory\ApplicationFactory::class, // Url helpers Helper\UrlHelper::class => Helper\UrlHelperFactory::class, @@ -42,7 +44,10 @@ Cache::class => CacheFactory::class, // Cli commands - CliCommands\GenerateShortcodeCommand::class => AnnotatedFactory::class, + CLI\Command\GenerateShortcodeCommand::class => AnnotatedFactory::class, + CLI\Command\ResolveUrlCommand::class => AnnotatedFactory::class, + CLI\Command\ListShortcodesCommand::class => AnnotatedFactory::class, + CLI\Command\GetVisitsCommand::class => AnnotatedFactory::class, // Middleware Middleware\Routable\RedirectMiddleware::class => AnnotatedFactory::class, diff --git a/src/CliCommands/GenerateShortcodeCommand.php b/src/CLI/Command/GenerateShortcodeCommand.php similarity index 94% rename from src/CliCommands/GenerateShortcodeCommand.php rename to src/CLI/Command/GenerateShortcodeCommand.php index 9f545dcee..ffc355db2 100644 --- a/src/CliCommands/GenerateShortcodeCommand.php +++ b/src/CLI/Command/GenerateShortcodeCommand.php @@ -1,5 +1,5 @@ setName('generate-shortcode') + $this->setName('shortcode:generate') ->setDescription('Generates a shortcode for provided URL and returns the short URL') ->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse'); } @@ -88,8 +88,6 @@ public function execute(InputInterface $input, OutputInterface $output) $output->writeln( sprintf('Provided URL "%s" is invalid. Try with a different one.', $longUrl) ); - } catch (\Exception $e) { - $output->writeln('' . $e . ''); } } } diff --git a/src/CLI/Command/GetVisitsCommand.php b/src/CLI/Command/GetVisitsCommand.php new file mode 100644 index 000000000..3c4e796da --- /dev/null +++ b/src/CLI/Command/GetVisitsCommand.php @@ -0,0 +1,77 @@ +visitsTracker = $visitsTracker; + } + + public function configure() + { + $this->setName('shortcode:visits') + ->setDescription('Returns the detailed visits information for provided short code') + ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get'); + } + + public function interact(InputInterface $input, OutputInterface $output) + { + $shortCode = $input->getArgument('shortCode'); + if (! empty($shortCode)) { + return; + } + + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + $question = new Question( + 'A short code was not provided. Which short code do you want to use?: ' + ); + + $shortCode = $helper->ask($input, $output, $question); + if (! empty($shortCode)) { + $input->setArgument('shortCode', $shortCode); + } + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $shortCode = $input->getArgument('shortCode'); + $visits = $this->visitsTracker->info($shortCode); + $table = new Table($output); + $table->setHeaders([ + 'Referer', + 'Date', + 'Temote Address', + 'User agent', + ]); + + foreach ($visits as $row) { + $table->addRow(array_values($row->jsonSerialize())); + } + $table->render(); + } +} diff --git a/src/CLI/Command/ListShortcodesCommand.php b/src/CLI/Command/ListShortcodesCommand.php new file mode 100644 index 000000000..ac85d50f0 --- /dev/null +++ b/src/CLI/Command/ListShortcodesCommand.php @@ -0,0 +1,84 @@ +shortUrlService = $shortUrlService; + } + + public function configure() + { + $this->setName('shortcode:list') + ->setDescription('List all short URLs') + ->addOption( + 'page', + 'p', + InputOption::VALUE_OPTIONAL, + sprintf('The first page to list (%s items per page)', PaginableRepositoryAdapter::ITEMS_PER_PAGE), + 1 + ); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $page = intval($input->getOption('page')); + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + do { + $result = $this->shortUrlService->listShortUrls($page); + $page++; + $table = new Table($output); + $table->setHeaders([ + 'Short code', + 'Original URL', + 'Date created', + 'Visits count', + ]); + + foreach ($result as $row) { + $table->addRow(array_values($row->jsonSerialize())); + } + $table->render(); + + if ($this->isLastPage($result)) { + $continue = false; + $output->writeln('You have reached last page'); + } else { + $continue = $helper->ask($input, $output, new ConfirmationQuestion( + sprintf('Continue with page %s? (y/N) ', $page), + false + )); + } + } while ($continue); + } +} diff --git a/src/CLI/Command/ResolveUrlCommand.php b/src/CLI/Command/ResolveUrlCommand.php new file mode 100644 index 000000000..4eb5ff412 --- /dev/null +++ b/src/CLI/Command/ResolveUrlCommand.php @@ -0,0 +1,78 @@ +urlShortener = $urlShortener; + } + + public function configure() + { + $this->setName('shortcode:parse') + ->setDescription('Returns the long URL behind a short code') + ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code to parse'); + } + + public function interact(InputInterface $input, OutputInterface $output) + { + $shortCode = $input->getArgument('shortCode'); + if (! empty($shortCode)) { + return; + } + + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + $question = new Question( + 'A short code was not provided. Which short code do you want to parse?: ' + ); + + $shortCode = $helper->ask($input, $output, $question); + if (! empty($shortCode)) { + $input->setArgument('shortCode', $shortCode); + } + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $shortCode = $input->getArgument('shortCode'); + + try { + $longUrl = $this->urlShortener->shortCodeToUrl($shortCode); + if (! isset($longUrl)) { + $output->writeln(sprintf('No URL found for short code "%s"', $shortCode)); + return; + } + + $output->writeln(sprintf('Long URL %s', $longUrl)); + } catch (InvalidShortCodeException $e) { + $output->writeln( + sprintf('Provided short code "%s" has an invalid format.', $shortCode) + ); + } + } +} diff --git a/src/CLI/Factory/ApplicationFactory.php b/src/CLI/Factory/ApplicationFactory.php new file mode 100644 index 000000000..d44150d1c --- /dev/null +++ b/src/CLI/Factory/ApplicationFactory.php @@ -0,0 +1,41 @@ +get('config')['cli']; + $app = new CliApp(); + + $commands = isset($config['commands']) ? $config['commands'] : []; + foreach ($commands as $command) { + if (! $container->has($command)) { + continue; + } + + $app->add($container->get($command)); + } + + return $app; + } +} diff --git a/src/Middleware/Rest/ListShortcodesMiddleware.php b/src/Middleware/Rest/ListShortcodesMiddleware.php index 6b74241ce..99d82454b 100644 --- a/src/Middleware/Rest/ListShortcodesMiddleware.php +++ b/src/Middleware/Rest/ListShortcodesMiddleware.php @@ -1,7 +1,7 @@ getCurrentPageNumber() >= $paginator->count(); + } }