-
-
Notifications
You must be signed in to change notification settings - Fork 259
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from acelaya/feature/10
feature/10
- Loading branch information
Showing
11 changed files
with
334 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,10 @@ | ||
#!/usr/bin/env php | ||
<?php | ||
use Acelaya\UrlShortener\CliCommands\GenerateShortcodeCommand; | ||
use Interop\Container\ContainerInterface; | ||
use Symfony\Component\Console\Application as CliApp; | ||
|
||
/** @var ContainerInterface $container */ | ||
$container = include __DIR__ . '/../config/container.php'; | ||
|
||
$app = new CliApp(); | ||
$app->addCommands([ | ||
$container->get(GenerateShortcodeCommand::class), | ||
]); | ||
$app = $container->get(CliApp::class); | ||
$app->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
use Acelaya\UrlShortener\CLI\Command; | ||
|
||
return [ | ||
|
||
'cli' => [ | ||
'commands' => [ | ||
Command\GenerateShortcodeCommand::class, | ||
Command\ResolveUrlCommand::class, | ||
Command\ListShortcodesCommand::class, | ||
Command\GetVisitsCommand::class, | ||
] | ||
], | ||
|
||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
namespace Acelaya\UrlShortener\CLI\Command; | ||
|
||
use Acelaya\UrlShortener\Service\VisitsTracker; | ||
use Acelaya\UrlShortener\Service\VisitsTrackerInterface; | ||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Helper\QuestionHelper; | ||
use Symfony\Component\Console\Helper\Table; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Question\Question; | ||
|
||
class GetVisitsCommand extends Command | ||
{ | ||
/** | ||
* @var VisitsTrackerInterface | ||
*/ | ||
private $visitsTracker; | ||
|
||
/** | ||
* GetVisitsCommand constructor. | ||
* @param VisitsTrackerInterface|VisitsTracker $visitsTracker | ||
* | ||
* @Inject({VisitsTracker::class}) | ||
*/ | ||
public function __construct(VisitsTrackerInterface $visitsTracker) | ||
{ | ||
parent::__construct(null); | ||
$this->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( | ||
'<question>A short code was not provided. Which short code do you want to use?:</question> ' | ||
); | ||
|
||
$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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
namespace Acelaya\UrlShortener\CLI\Command; | ||
|
||
use Acelaya\UrlShortener\Paginator\Adapter\PaginableRepositoryAdapter; | ||
use Acelaya\UrlShortener\Paginator\Util\PaginatorUtilsTrait; | ||
use Acelaya\UrlShortener\Service\ShortUrlService; | ||
use Acelaya\UrlShortener\Service\ShortUrlServiceInterface; | ||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Helper\QuestionHelper; | ||
use Symfony\Component\Console\Helper\Table; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Question\ConfirmationQuestion; | ||
|
||
class ListShortcodesCommand extends Command | ||
{ | ||
use PaginatorUtilsTrait; | ||
|
||
/** | ||
* @var ShortUrlServiceInterface | ||
*/ | ||
private $shortUrlService; | ||
|
||
/** | ||
* ListShortcodesCommand constructor. | ||
* @param ShortUrlServiceInterface|ShortUrlService $shortUrlService | ||
* | ||
* @Inject({ShortUrlService::class}) | ||
*/ | ||
public function __construct(ShortUrlServiceInterface $shortUrlService) | ||
{ | ||
parent::__construct(null); | ||
$this->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('<info>You have reached last page</info>'); | ||
} else { | ||
$continue = $helper->ask($input, $output, new ConfirmationQuestion( | ||
sprintf('<question>Continue with page <bg=cyan;options=bold>%s</>? (y/N)</question> ', $page), | ||
false | ||
)); | ||
} | ||
} while ($continue); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php | ||
namespace Acelaya\UrlShortener\CLI\Command; | ||
|
||
use Acelaya\UrlShortener\Exception\InvalidShortCodeException; | ||
use Acelaya\UrlShortener\Service\UrlShortener; | ||
use Acelaya\UrlShortener\Service\UrlShortenerInterface; | ||
use Acelaya\ZsmAnnotatedServices\Annotation\Inject; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Helper\QuestionHelper; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Question\Question; | ||
|
||
class ResolveUrlCommand extends Command | ||
{ | ||
/** | ||
* @var UrlShortenerInterface | ||
*/ | ||
private $urlShortener; | ||
|
||
/** | ||
* ResolveUrlCommand constructor. | ||
* @param UrlShortenerInterface|UrlShortener $urlShortener | ||
* | ||
* @Inject({UrlShortener::class}) | ||
*/ | ||
public function __construct(UrlShortenerInterface $urlShortener) | ||
{ | ||
parent::__construct(null); | ||
$this->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( | ||
'<question>A short code was not provided. Which short code do you want to parse?:</question> ' | ||
); | ||
|
||
$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('<error>No URL found for short code "%s"</error>', $shortCode)); | ||
return; | ||
} | ||
|
||
$output->writeln(sprintf('Long URL <info>%s</info>', $longUrl)); | ||
} catch (InvalidShortCodeException $e) { | ||
$output->writeln( | ||
sprintf('<error>Provided short code "%s" has an invalid format.</error>', $shortCode) | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
namespace Acelaya\UrlShortener\CLI\Factory; | ||
|
||
use Interop\Container\ContainerInterface; | ||
use Interop\Container\Exception\ContainerException; | ||
use Symfony\Component\Console\Application as CliApp; | ||
use Zend\ServiceManager\Exception\ServiceNotCreatedException; | ||
use Zend\ServiceManager\Exception\ServiceNotFoundException; | ||
use Zend\ServiceManager\Factory\FactoryInterface; | ||
|
||
class ApplicationFactory implements FactoryInterface | ||
{ | ||
/** | ||
* Create an object | ||
* | ||
* @param ContainerInterface $container | ||
* @param string $requestedName | ||
* @param null|array $options | ||
* @return object | ||
* @throws ServiceNotFoundException if unable to resolve the service. | ||
* @throws ServiceNotCreatedException if an exception is raised when | ||
* creating a service. | ||
* @throws ContainerException if any other error occurs | ||
*/ | ||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) | ||
{ | ||
$config = $container->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; | ||
} | ||
} |
Oops, something went wrong.