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();
+ }
}