From 577ad146a4623afe8cdf435bfde125f378bae4a7 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya <alejandro@alejandrocelaya.com> Date: Sat, 30 Apr 2016 18:14:43 +0200 Subject: [PATCH] Implemented shortcode generation --- .../autoload/middleware-pipeline.global.php | 2 + config/autoload/services.global.php | 1 + src/Middleware/CliParamsMiddleware.php | 66 ++++++++++++++ .../GenerateShortcodeMiddleware.php | 91 +++++++++++++++++++ .../Factory/CliParamsMiddlewareFactory.php | 29 ++++++ 5 files changed, 189 insertions(+) create mode 100644 src/Middleware/CliParamsMiddleware.php create mode 100644 src/Middleware/CliRoutable/GenerateShortcodeMiddleware.php create mode 100644 src/Middleware/Factory/CliParamsMiddlewareFactory.php diff --git a/config/autoload/middleware-pipeline.global.php b/config/autoload/middleware-pipeline.global.php index 8a393ce1..d033f9b2 100644 --- a/config/autoload/middleware-pipeline.global.php +++ b/config/autoload/middleware-pipeline.global.php @@ -1,4 +1,5 @@ <?php +use Acelaya\UrlShortener\Middleware\CliParamsMiddleware; use Zend\Expressive\Container\ApplicationFactory; use Zend\Expressive\Helper; @@ -15,6 +16,7 @@ return [ 'routing' => [ 'middleware' => [ ApplicationFactory::ROUTING_MIDDLEWARE, + CliParamsMiddleware::class, Helper\UrlHelperMiddleware::class, ApplicationFactory::DISPATCH_MIDDLEWARE, ], diff --git a/config/autoload/services.global.php b/config/autoload/services.global.php index 5d47160a..421c8a00 100644 --- a/config/autoload/services.global.php +++ b/config/autoload/services.global.php @@ -39,6 +39,7 @@ return [ // Middleware Middleware\CliRoutable\GenerateShortcodeMiddleware::class => AnnotatedFactory::class, + Middleware\CliParamsMiddleware::class => Middleware\Factory\CliParamsMiddlewareFactory::class, ], 'aliases' => [ 'em' => EntityManager::class, diff --git a/src/Middleware/CliParamsMiddleware.php b/src/Middleware/CliParamsMiddleware.php new file mode 100644 index 00000000..c750ff9b --- /dev/null +++ b/src/Middleware/CliParamsMiddleware.php @@ -0,0 +1,66 @@ +<?php +namespace Acelaya\UrlShortener\Middleware; + +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; +use Zend\Expressive\Router\RouteResult; +use Zend\Stratigility\MiddlewareInterface; + +class CliParamsMiddleware implements MiddlewareInterface +{ + /** + * @var array + */ + private $argv; + + public function __construct(array $argv) + { + $this->argv = $argv; + } + + /** + * Process an incoming request and/or response. + * + * Accepts a server-side request and a response instance, and does + * something with them. + * + * If the response is not complete and/or further processing would not + * interfere with the work done in the middleware, or if the middleware + * wants to delegate to another process, it can use the `$out` callable + * if present. + * + * If the middleware does not return a value, execution of the current + * request is considered complete, and the response instance provided will + * be considered the response to return. + * + * Alternately, the middleware may return a response instance. + * + * Often, middleware will `return $out();`, with the assumption that a + * later middleware will return a response. + * + * @param Request $request + * @param Response $response + * @param null|callable $out + * @return null|Response + */ + public function __invoke(Request $request, Response $response, callable $out = null) + { + // When not in CLI, just call next middleware + if (! php_sapi_name() === 'cli') { + return $out($request, $response); + } + + /** @var RouteResult $routeResult */ + $routeResult = $request->getAttribute(RouteResult::class); + if (! $routeResult->isSuccess()) { + return $out($request, $response); + } + + // Inject ARGV params as request attributes + if ($routeResult->getMatchedRouteName() === 'cli-generate-shortcode') { + $request = $request->withAttribute('longUrl', isset($this->argv[2]) ? $this->argv[2] : null); + } + + return $out($request, $response); + } +} diff --git a/src/Middleware/CliRoutable/GenerateShortcodeMiddleware.php b/src/Middleware/CliRoutable/GenerateShortcodeMiddleware.php new file mode 100644 index 00000000..44fa3bf8 --- /dev/null +++ b/src/Middleware/CliRoutable/GenerateShortcodeMiddleware.php @@ -0,0 +1,91 @@ +<?php +namespace Acelaya\UrlShortener\Middleware\CliRoutable; + +use Acelaya\UrlShortener\Exception\InvalidUrlException; +use Acelaya\UrlShortener\Service\UrlShortener; +use Acelaya\UrlShortener\Service\UrlShortenerInterface; +use Acelaya\ZsmAnnotatedServices\Annotation\Inject; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; +use Zend\Diactoros\Uri; +use Zend\Stratigility\MiddlewareInterface; + +class GenerateShortcodeMiddleware implements MiddlewareInterface +{ + /** + * @var UrlShortenerInterface + */ + private $urlShortener; + /** + * @var array + */ + private $config; + + /** + * GenerateShortcodeMiddleware constructor. + * + * @param UrlShortenerInterface|UrlShortener $urlShortener + * @param array $config + * + * @Inject({UrlShortener::class, "config.url-shortener"}) + */ + public function __construct(UrlShortenerInterface $urlShortener, array $config) + { + $this->urlShortener = $urlShortener; + $this->config = $config; + } + + /** + * Process an incoming request and/or response. + * + * Accepts a server-side request and a response instance, and does + * something with them. + * + * If the response is not complete and/or further processing would not + * interfere with the work done in the middleware, or if the middleware + * wants to delegate to another process, it can use the `$out` callable + * if present. + * + * If the middleware does not return a value, execution of the current + * request is considered complete, and the response instance provided will + * be considered the response to return. + * + * Alternately, the middleware may return a response instance. + * + * Often, middleware will `return $out();`, with the assumption that a + * later middleware will return a response. + * + * @param Request $request + * @param Response $response + * @param null|callable $out + * @return null|Response + */ + public function __invoke(Request $request, Response $response, callable $out = null) + { + $longUrl = $request->getAttribute('longUrl'); + + try { + if (! isset($longUrl)) { + $response->getBody()->write('A URL was not provided!' . PHP_EOL); + return; + } + + $shortcode = $this->urlShortener->urlToShortCode(new Uri($longUrl)); + $shortUrl = (new Uri())->withPath($shortcode) + ->withScheme($this->config['schema']) + ->withHost($this->config['hostname']); + + $response->getBody()->write( + sprintf('Processed URL "%s".%sGenerated short URL "%s"', $longUrl, PHP_EOL, $shortUrl) . PHP_EOL + ); + } catch (InvalidUrlException $e) { + $response->getBody()->write( + sprintf('Provided URL "%s" is invalid. Try with a different one.', $longUrl) . PHP_EOL + ); + } catch (\Exception $e) { + $response->getBody()->write($e); + } finally { + return is_callable($out) ? $out($request, $response) : $response; + } + } +} diff --git a/src/Middleware/Factory/CliParamsMiddlewareFactory.php b/src/Middleware/Factory/CliParamsMiddlewareFactory.php new file mode 100644 index 00000000..73e365ac --- /dev/null +++ b/src/Middleware/Factory/CliParamsMiddlewareFactory.php @@ -0,0 +1,29 @@ +<?php +namespace Acelaya\UrlShortener\Middleware\Factory; + +use Acelaya\UrlShortener\Middleware\CliParamsMiddleware; +use Interop\Container\ContainerInterface; +use Interop\Container\Exception\ContainerException; +use Zend\ServiceManager\Exception\ServiceNotCreatedException; +use Zend\ServiceManager\Exception\ServiceNotFoundException; +use Zend\ServiceManager\Factory\FactoryInterface; + +class CliParamsMiddlewareFactory 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) + { + return new CliParamsMiddleware($_SERVER['argv']); + } +}