mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-25 22:29:51 +03:00
Deleted everything related with previews generation
This commit is contained in:
parent
9d36534230
commit
78b484e657
30 changed files with 22 additions and 818 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -5,8 +5,6 @@
|
|||
/module/CLI/test-resources export-ignore
|
||||
/module/Core/test export-ignore
|
||||
/module/Core/test-db export-ignore
|
||||
/module/PreviewGenerator/test export-ignore
|
||||
/module/PreviewGenerator/test-db export-ignore
|
||||
/module/Rest/test export-ignore
|
||||
/module/Rest/test-api export-ignore
|
||||
.gitattributes export-ignore
|
||||
|
|
47
README.md
47
README.md
|
@ -215,12 +215,6 @@ Those tasks can be performed using shlink's CLI tool, so it should be easy to sc
|
|||
|
||||
> You don't need this if you use Shlink v1.17.0 or newer, since now it downloads/updates the geolocation database automatically just before trying to use it.
|
||||
|
||||
* Generate website previews: `/path/to/shlink/bin/cli short-url:process-previews`
|
||||
|
||||
Running this will improve the performance of the `doma.in/abc123/preview` URLs, which return a preview of the site.
|
||||
|
||||
> **Important!** Generating previews is considered deprecated and the feature will be removed in Shlink v2.
|
||||
|
||||
*Any of these commands accept the `-q` flag, which makes it not display any output. This is recommended when configuring the commands as cron jobs.*
|
||||
|
||||
## Update to new version
|
||||
|
@ -274,33 +268,32 @@ Options:
|
|||
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
|
||||
|
||||
Available commands:
|
||||
help Displays help for a command
|
||||
list Lists commands
|
||||
help Displays help for a command
|
||||
list Lists commands
|
||||
api-key
|
||||
api-key:disable Disables an API key.
|
||||
api-key:generate Generates a new valid API key.
|
||||
api-key:list Lists all the available API keys.
|
||||
api-key:disable Disables an API key.
|
||||
api-key:generate Generates a new valid API key.
|
||||
api-key:list Lists all the available API keys.
|
||||
config
|
||||
config:generate-charset [DEPRECATED] Generates a character set sample just by shuffling the default one, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". Then it can be set in the SHORTCODE_CHARS environment variable
|
||||
config:generate-secret [DEPRECATED] Generates a random secret string that can be used for JWT token encryption
|
||||
config:generate-charset [DEPRECATED] Generates a character set sample just by shuffling the default one, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". Then it can be set in the SHORTCODE_CHARS environment variable
|
||||
config:generate-secret [DEPRECATED] Generates a random secret string that can be used for JWT token encryption
|
||||
db
|
||||
db:create Creates the database needed for shlink to work. It will do nothing if the database already exists
|
||||
db:migrate Runs database migrations, which will ensure the shlink database is up to date.
|
||||
db:create Creates the database needed for shlink to work. It will do nothing if the database already exists
|
||||
db:migrate Runs database migrations, which will ensure the shlink database is up to date.
|
||||
short-url
|
||||
short-url:delete [short-code:delete] Deletes a short URL
|
||||
short-url:generate [shortcode:generate|short-code:generate] Generates a short URL for provided long URL and returns it
|
||||
short-url:list [shortcode:list|short-code:list] List all short URLs
|
||||
short-url:parse [shortcode:parse|short-code:parse] Returns the long URL behind a short code
|
||||
short-url:process-previews [shortcode:process-previews|short-code:process-previews] [DEPRECATED] Processes and generates the previews for every URL, improving performance for later web requests.
|
||||
short-url:visits [shortcode:visits|short-code:visits] Returns the detailed visits information for provided short code
|
||||
short-url:delete [short-code:delete] Deletes a short URL
|
||||
short-url:generate [shortcode:generate|short-code:generate] Generates a short URL for provided long URL and returns it
|
||||
short-url:list [shortcode:list|short-code:list] List all short URLs
|
||||
short-url:parse [shortcode:parse|short-code:parse] Returns the long URL behind a short code
|
||||
short-url:visits [shortcode:visits|short-code:visits] Returns the detailed visits information for provided short code
|
||||
tag
|
||||
tag:create Creates one or more tags.
|
||||
tag:delete Deletes one or more tags.
|
||||
tag:list Lists existing tags.
|
||||
tag:rename Renames one existing tag.
|
||||
tag:create Creates one or more tags.
|
||||
tag:delete Deletes one or more tags.
|
||||
tag:list Lists existing tags.
|
||||
tag:rename Renames one existing tag.
|
||||
visit
|
||||
visit:locate [visit:process] Resolves visits origin locations.
|
||||
visit:update-db [DEPRECATED] Updates the GeoLite2 database file used to geolocate IP addresses
|
||||
visit:locate [visit:process] Resolves visits origin locations.
|
||||
visit:update-db [DEPRECATED] Updates the GeoLite2 database file used to geolocate IP addresses
|
||||
```
|
||||
|
||||
> This product includes GeoLite2 data created by MaxMind, available from [https://www.maxmind.com](https://www.maxmind.com)
|
||||
|
|
Binary file not shown.
|
@ -71,8 +71,7 @@
|
|||
"psr-4": {
|
||||
"Shlinkio\\Shlink\\CLI\\": "module/CLI/src",
|
||||
"Shlinkio\\Shlink\\Rest\\": "module/Rest/src",
|
||||
"Shlinkio\\Shlink\\Core\\": "module/Core/src",
|
||||
"Shlinkio\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/src/"
|
||||
"Shlinkio\\Shlink\\Core\\": "module/Core/src"
|
||||
},
|
||||
"files": [
|
||||
"module/Core/functions/functions.php"
|
||||
|
@ -86,8 +85,7 @@
|
|||
"ShlinkioTest\\Shlink\\Core\\": [
|
||||
"module/Core/test",
|
||||
"module/Core/test-db"
|
||||
],
|
||||
"ShlinkioTest\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/test"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/* @deprecated */
|
||||
return [
|
||||
|
||||
'preview_generation' => [
|
||||
'files_location' => 'data/cache',
|
||||
],
|
||||
|
||||
];
|
|
@ -23,7 +23,6 @@ return (new ConfigAggregator\ConfigAggregator([
|
|||
CLI\ConfigProvider::class,
|
||||
Rest\ConfigProvider::class,
|
||||
EventDispatcher\ConfigProvider::class,
|
||||
PreviewGenerator\ConfigProvider::class,
|
||||
new ConfigAggregator\PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
|
||||
env('APP_ENV') === 'test'
|
||||
? new ConfigAggregator\PhpFileProvider('config/test/*.global.php')
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"operationId": "shortUrlPreview",
|
||||
"tags": [
|
||||
"URL Shortener"
|
||||
],
|
||||
"summary": "Short URL preview image",
|
||||
"description": "Returns the preview of the page behind a short URL",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "shortCode",
|
||||
"in": "path",
|
||||
"description": "The short code to resolve.",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Image in PNG format",
|
||||
"content": {
|
||||
"image/png": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,9 +105,6 @@
|
|||
"/{shortCode}/qr-code": {
|
||||
"$ref": "paths/{shortCode}_qr-code.json"
|
||||
},
|
||||
"/{shortCode}/preview": {
|
||||
"$ref": "paths/{shortCode}_preview.json"
|
||||
},
|
||||
|
||||
"/rest/v1/authenticate": {
|
||||
"$ref": "paths/v1_authenticate.json"
|
||||
|
|
|
@ -12,7 +12,6 @@ return [
|
|||
Command\ShortUrl\ResolveUrlCommand::NAME => Command\ShortUrl\ResolveUrlCommand::class,
|
||||
Command\ShortUrl\ListShortUrlsCommand::NAME => Command\ShortUrl\ListShortUrlsCommand::class,
|
||||
Command\ShortUrl\GetVisitsCommand::NAME => Command\ShortUrl\GetVisitsCommand::class,
|
||||
Command\ShortUrl\GeneratePreviewCommand::NAME => Command\ShortUrl\GeneratePreviewCommand::class,
|
||||
Command\ShortUrl\DeleteShortUrlCommand::NAME => Command\ShortUrl\DeleteShortUrlCommand::class,
|
||||
|
||||
Command\Visit\LocateVisitsCommand::NAME => Command\Visit\LocateVisitsCommand::class,
|
||||
|
|
|
@ -12,7 +12,6 @@ use Shlinkio\Shlink\Core\Service;
|
|||
use Shlinkio\Shlink\Installer\Factory\ProcessHelperFactory;
|
||||
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdater;
|
||||
use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
|
||||
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
|
||||
use Symfony\Component\Console as SymfonyCli;
|
||||
use Symfony\Component\Lock\LockFactory;
|
||||
|
@ -34,7 +33,6 @@ return [
|
|||
Command\ShortUrl\ResolveUrlCommand::class => ConfigAbstractFactory::class,
|
||||
Command\ShortUrl\ListShortUrlsCommand::class => ConfigAbstractFactory::class,
|
||||
Command\ShortUrl\GetVisitsCommand::class => ConfigAbstractFactory::class,
|
||||
Command\ShortUrl\GeneratePreviewCommand::class => ConfigAbstractFactory::class,
|
||||
Command\ShortUrl\DeleteShortUrlCommand::class => ConfigAbstractFactory::class,
|
||||
|
||||
Command\Visit\LocateVisitsCommand::class => ConfigAbstractFactory::class,
|
||||
|
@ -64,7 +62,6 @@ return [
|
|||
Command\ShortUrl\ResolveUrlCommand::class => [Service\UrlShortener::class],
|
||||
Command\ShortUrl\ListShortUrlsCommand::class => [Service\ShortUrlService::class, 'config.url_shortener.domain'],
|
||||
Command\ShortUrl\GetVisitsCommand::class => [Service\VisitsTracker::class],
|
||||
Command\ShortUrl\GeneratePreviewCommand::class => [Service\ShortUrlService::class, PreviewGenerator::class],
|
||||
Command\ShortUrl\DeleteShortUrlCommand::class => [Service\ShortUrl\DeleteShortUrlService::class],
|
||||
|
||||
Command\Visit\LocateVisitsCommand::class => [
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\CLI\Command\ShortUrl;
|
||||
|
||||
use Shlinkio\Shlink\CLI\Util\ExitCodes;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrlServiceInterface;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGeneratorInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/** @deprecated */
|
||||
class GeneratePreviewCommand extends Command
|
||||
{
|
||||
public const NAME = 'short-url:process-previews';
|
||||
private const ALIASES = ['shortcode:process-previews', 'short-code:process-previews'];
|
||||
|
||||
/** @var PreviewGeneratorInterface */
|
||||
private $previewGenerator;
|
||||
/** @var ShortUrlServiceInterface */
|
||||
private $shortUrlService;
|
||||
|
||||
public function __construct(ShortUrlServiceInterface $shortUrlService, PreviewGeneratorInterface $previewGenerator)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->shortUrlService = $shortUrlService;
|
||||
$this->previewGenerator = $previewGenerator;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName(self::NAME)
|
||||
->setAliases(self::ALIASES)
|
||||
->setDescription(
|
||||
'[DEPRECATED] Processes and generates the previews for every URL, improving performance for later web '
|
||||
. 'requests.'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): ?int
|
||||
{
|
||||
$page = 1;
|
||||
do {
|
||||
$shortUrls = $this->shortUrlService->listShortUrls($page);
|
||||
$page += 1;
|
||||
|
||||
foreach ($shortUrls as $shortUrl) {
|
||||
$this->processUrl($shortUrl->getLongUrl(), $output);
|
||||
}
|
||||
} while ($page <= $shortUrls->count());
|
||||
|
||||
(new SymfonyStyle($input, $output))->success('Finished processing all URLs');
|
||||
return ExitCodes::EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
private function processUrl($url, OutputInterface $output): void
|
||||
{
|
||||
try {
|
||||
$output->write(sprintf('Processing URL %s...', $url));
|
||||
$this->previewGenerator->generatePreview($url);
|
||||
$output->writeln(' <info>Success!</info>');
|
||||
} catch (PreviewGenerationException $e) {
|
||||
$output->writeln(' <error>Error</error>');
|
||||
if ($output->isVerbose()) {
|
||||
$this->getApplication()->renderThrowable($e, $output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\CLI\Command\ShortUrl;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\CLI\Command\ShortUrl\GeneratePreviewCommand;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Service\ShortUrlService;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
use Zend\Paginator\Adapter\ArrayAdapter;
|
||||
use Zend\Paginator\Paginator;
|
||||
|
||||
use function count;
|
||||
use function substr_count;
|
||||
|
||||
class GeneratePreviewCommandTest extends TestCase
|
||||
{
|
||||
private CommandTester $commandTester;
|
||||
private ObjectProphecy $previewGenerator;
|
||||
private ObjectProphecy $shortUrlService;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->previewGenerator = $this->prophesize(PreviewGenerator::class);
|
||||
$this->shortUrlService = $this->prophesize(ShortUrlService::class);
|
||||
|
||||
$command = new GeneratePreviewCommand($this->shortUrlService->reveal(), $this->previewGenerator->reveal());
|
||||
$app = new Application();
|
||||
$app->add($command);
|
||||
|
||||
$this->commandTester = new CommandTester($command);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function previewsForEveryUrlAreGenerated()
|
||||
{
|
||||
$paginator = $this->createPaginator([
|
||||
new ShortUrl('http://foo.com'),
|
||||
new ShortUrl('https://bar.com'),
|
||||
new ShortUrl('http://baz.com/something'),
|
||||
]);
|
||||
$this->shortUrlService->listShortUrls(1)->willReturn($paginator)->shouldBeCalledOnce();
|
||||
|
||||
$generatePreview1 = $this->previewGenerator->generatePreview('http://foo.com')->willReturn('');
|
||||
$generatePreview2 = $this->previewGenerator->generatePreview('https://bar.com')->willReturn('');
|
||||
$generatePreview3 = $this->previewGenerator->generatePreview('http://baz.com/something')->willReturn('');
|
||||
|
||||
$this->commandTester->execute([]);
|
||||
$output = $this->commandTester->getDisplay();
|
||||
|
||||
$this->assertStringContainsString('Processing URL http://foo.com', $output);
|
||||
$this->assertStringContainsString('Processing URL https://bar.com', $output);
|
||||
$this->assertStringContainsString('Processing URL http://baz.com/something', $output);
|
||||
$this->assertStringContainsString('Finished processing all URLs', $output);
|
||||
$generatePreview1->shouldHaveBeenCalledOnce();
|
||||
$generatePreview2->shouldHaveBeenCalledOnce();
|
||||
$generatePreview3->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function exceptionWillOutputError()
|
||||
{
|
||||
$items = [
|
||||
new ShortUrl('http://foo.com'),
|
||||
new ShortUrl('https://bar.com'),
|
||||
new ShortUrl('http://baz.com/something'),
|
||||
];
|
||||
$paginator = $this->createPaginator($items);
|
||||
$this->shortUrlService->listShortUrls(1)->willReturn($paginator)->shouldBeCalledOnce();
|
||||
$this->previewGenerator->generatePreview(Argument::any())->willThrow(PreviewGenerationException::class)
|
||||
->shouldBeCalledTimes(count($items));
|
||||
|
||||
$this->commandTester->execute([]);
|
||||
$output = $this->commandTester->getDisplay();
|
||||
$this->assertEquals(count($items), substr_count($output, 'Error'));
|
||||
}
|
||||
|
||||
protected function createPaginator(array $items)
|
||||
{
|
||||
$paginator = new Paginator(new ArrayAdapter($items));
|
||||
$paginator->setItemCountPerPage(count($items));
|
||||
|
||||
return $paginator;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ use Doctrine\Common\Cache\Cache;
|
|||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Shlinkio\Shlink\Core\ErrorHandler;
|
||||
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
|
||||
use Zend\Expressive\Router\RouterInterface;
|
||||
use Zend\Expressive\Template\TemplateRendererInterface;
|
||||
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
||||
|
@ -37,7 +36,6 @@ return [
|
|||
Action\RedirectAction::class => ConfigAbstractFactory::class,
|
||||
Action\PixelAction::class => ConfigAbstractFactory::class,
|
||||
Action\QrCodeAction::class => ConfigAbstractFactory::class,
|
||||
Action\PreviewAction::class => ConfigAbstractFactory::class,
|
||||
|
||||
Middleware\QrCodeCacheMiddleware::class => ConfigAbstractFactory::class,
|
||||
],
|
||||
|
@ -74,7 +72,6 @@ return [
|
|||
'Logger_Shlink',
|
||||
],
|
||||
Action\QrCodeAction::class => [RouterInterface::class, Service\UrlShortener::class, 'Logger_Shlink'],
|
||||
Action\PreviewAction::class => [PreviewGenerator::class, Service\UrlShortener::class, 'Logger_Shlink'],
|
||||
|
||||
Middleware\QrCodeCacheMiddleware::class => [Cache::class],
|
||||
],
|
||||
|
|
|
@ -37,23 +37,6 @@ return [
|
|||
],
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
|
||||
// Deprecated routes
|
||||
[
|
||||
'name' => 'short-url-preview',
|
||||
'path' => '/{shortCode}/preview',
|
||||
'middleware' => Action\PreviewAction::class,
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
[
|
||||
'name' => 'short-url-qr-code-old',
|
||||
'path' => '/qr/{shortCode}[/{size:[0-9]+}]',
|
||||
'middleware' => [
|
||||
Middleware\QrCodeCacheMiddleware::class,
|
||||
Action\QrCodeAction::class,
|
||||
],
|
||||
'allowed_methods' => [RequestMethod::METHOD_GET],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Action;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Shlinkio\Shlink\Common\Response\ResponseUtilsTrait;
|
||||
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGeneratorInterface;
|
||||
|
||||
/** @deprecated */
|
||||
class PreviewAction implements MiddlewareInterface
|
||||
{
|
||||
use ResponseUtilsTrait;
|
||||
|
||||
/** @var PreviewGeneratorInterface */
|
||||
private $previewGenerator;
|
||||
/** @var UrlShortenerInterface */
|
||||
private $urlShortener;
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
public function __construct(
|
||||
PreviewGeneratorInterface $previewGenerator,
|
||||
UrlShortenerInterface $urlShortener,
|
||||
?LoggerInterface $logger = null
|
||||
) {
|
||||
$this->previewGenerator = $previewGenerator;
|
||||
$this->urlShortener = $urlShortener;
|
||||
$this->logger = $logger ?: new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request and return a response, optionally delegating
|
||||
* to the next middleware component to create the response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function process(Request $request, RequestHandlerInterface $handler): Response
|
||||
{
|
||||
$shortCode = $request->getAttribute('shortCode');
|
||||
|
||||
try {
|
||||
$url = $this->urlShortener->shortCodeToUrl($shortCode);
|
||||
$imagePath = $this->previewGenerator->generatePreview($url->getLongUrl());
|
||||
return $this->generateImageResponse($imagePath);
|
||||
} catch (ShortUrlNotFoundException | PreviewGenerationException $e) {
|
||||
$this->logger->warning('An error occurred while generating preview image. {e}', ['e' => $e]);
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Core\Action;
|
||||
|
||||
use finfo;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Shlinkio\Shlink\Core\Action\PreviewAction;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
|
||||
use Shlinkio\Shlink\Core\Service\UrlShortener;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
|
||||
use Zend\Diactoros\Response;
|
||||
use Zend\Diactoros\ServerRequest;
|
||||
|
||||
use function filesize;
|
||||
|
||||
use const FILEINFO_MIME;
|
||||
|
||||
/** @deprecated */
|
||||
class PreviewActionTest extends TestCase
|
||||
{
|
||||
/** @var PreviewAction */
|
||||
private $action;
|
||||
/** @var ObjectProphecy */
|
||||
private $previewGenerator;
|
||||
/** @var ObjectProphecy */
|
||||
private $urlShortener;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->previewGenerator = $this->prophesize(PreviewGenerator::class);
|
||||
$this->urlShortener = $this->prophesize(UrlShortener::class);
|
||||
$this->action = new PreviewAction($this->previewGenerator->reveal(), $this->urlShortener->reveal());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function correctShortCodeReturnsImageResponse(): void
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$url = 'foobar.com';
|
||||
$shortUrl = new ShortUrl($url);
|
||||
$path = __FILE__;
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)->shouldBeCalledOnce();
|
||||
$this->previewGenerator->generatePreview($url)->willReturn($path)->shouldBeCalledOnce();
|
||||
|
||||
$resp = $this->action->process(
|
||||
(new ServerRequest())->withAttribute('shortCode', $shortCode),
|
||||
$this->prophesize(RequestHandlerInterface::class)->reveal()
|
||||
);
|
||||
|
||||
$this->assertEquals(filesize($path), $resp->getHeaderLine('Content-length'));
|
||||
$this->assertEquals((new finfo(FILEINFO_MIME))->file($path), $resp->getHeaderLine('Content-type'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function invalidShortCodeExceptionFallsBackToNextMiddleware(): void
|
||||
{
|
||||
$shortCode = 'abc123';
|
||||
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(ShortUrlNotFoundException::class)
|
||||
->shouldBeCalledOnce();
|
||||
$delegate = $this->prophesize(RequestHandlerInterface::class);
|
||||
$process = $delegate->handle(Argument::any())->willReturn(new Response());
|
||||
|
||||
$this->action->process(
|
||||
(new ServerRequest())->withAttribute('shortCode', $shortCode),
|
||||
$delegate->reveal()
|
||||
);
|
||||
|
||||
$process->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
|
||||
|
||||
return [
|
||||
|
||||
'dependencies' => [
|
||||
'factories' => [
|
||||
Image\ImageBuilder::class => Image\ImageBuilderFactory::class,
|
||||
Service\PreviewGenerator::class => ConfigAbstractFactory::class,
|
||||
],
|
||||
],
|
||||
|
||||
ConfigAbstractFactory::class => [
|
||||
Service\PreviewGenerator::class => [
|
||||
Image\ImageBuilder::class,
|
||||
Filesystem::class,
|
||||
'config.preview_generation.files_location',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
|
@ -1,16 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator;
|
||||
|
||||
use function Shlinkio\Shlink\Common\loadConfigFromGlob;
|
||||
|
||||
/** @deprecated */
|
||||
class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
return loadConfigFromGlob(__DIR__ . '/../config/{,*.}config.php');
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/** @deprecated */
|
||||
class PreviewGenerationException extends RuntimeException
|
||||
{
|
||||
public static function fromImageError(string $error): self
|
||||
{
|
||||
return new self(sprintf('Error generating a preview image with error: %s', $error));
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use Zend\ServiceManager\AbstractPluginManager;
|
||||
|
||||
/** @deprecated */
|
||||
class ImageBuilder extends AbstractPluginManager implements ImageBuilderInterface
|
||||
{
|
||||
protected $instanceOf = Image::class;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/** @deprecated */
|
||||
class ImageBuilderFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
return new ImageBuilder($container, ['factories' => [
|
||||
Image::class => ImageFactory::class,
|
||||
]]);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use Zend\ServiceManager\ServiceLocatorInterface;
|
||||
|
||||
/** @deprecated */
|
||||
interface ImageBuilderInterface extends ServiceLocatorInterface
|
||||
{
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/** @deprecated */
|
||||
class ImageFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container, string $requestedName, ?array $options = null)
|
||||
{
|
||||
$config = $container->get('config')['wkhtmltopdf'];
|
||||
$image = new Image($config['images'] ?? null);
|
||||
|
||||
if ($options['url'] ?? null) {
|
||||
$image->setPage($options['url']);
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Service;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Image\ImageBuilderInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
use function sprintf;
|
||||
use function urlencode;
|
||||
|
||||
/** @deprecated */
|
||||
class PreviewGenerator implements PreviewGeneratorInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $location;
|
||||
/** @var ImageBuilderInterface */
|
||||
private $imageBuilder;
|
||||
/** @var Filesystem */
|
||||
private $filesystem;
|
||||
|
||||
public function __construct(ImageBuilderInterface $imageBuilder, Filesystem $filesystem, string $location)
|
||||
{
|
||||
$this->location = $location;
|
||||
$this->imageBuilder = $imageBuilder;
|
||||
$this->filesystem = $filesystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and stores preview for provided website and returns the path to the image file
|
||||
*
|
||||
* @throws PreviewGenerationException
|
||||
*/
|
||||
public function generatePreview(string $url): string
|
||||
{
|
||||
$image = $this->imageBuilder->build(Image::class, ['url' => $url]);
|
||||
|
||||
// If the file already exists, return its path
|
||||
$cacheId = sprintf('preview_%s.%s', urlencode($url), $image->type);
|
||||
$path = $this->location . '/' . $cacheId;
|
||||
if ($this->filesystem->exists($path)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
// Save and check if an error occurred
|
||||
$image->saveAs($path);
|
||||
$error = $image->getError();
|
||||
if (! empty($error)) {
|
||||
throw PreviewGenerationException::fromImageError($error);
|
||||
}
|
||||
|
||||
// Cache the path and return it
|
||||
return $path;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\PreviewGenerator\Service;
|
||||
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
|
||||
/** @deprecated */
|
||||
interface PreviewGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Generates and stores preview for provided website and returns the path to the image file
|
||||
*
|
||||
* @throws PreviewGenerationException
|
||||
*/
|
||||
public function generatePreview(string $url): string;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\PreviewGenerator;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\PreviewGenerator\ConfigProvider;
|
||||
|
||||
class ConfigProviderTest extends TestCase
|
||||
{
|
||||
/** @var ConfigProvider */
|
||||
private $configProvider;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->configProvider = new ConfigProvider();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function configIsReturned(): void
|
||||
{
|
||||
$config = ($this->configProvider)();
|
||||
|
||||
$this->assertArrayHasKey('dependencies', $config);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Image\ImageBuilder;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Image\ImageBuilderFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
class ImageBuilderFactoryTest extends TestCase
|
||||
{
|
||||
/** @var ImageBuilderFactory */
|
||||
private $factory;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->factory = new ImageBuilderFactory();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function serviceIsCreated()
|
||||
{
|
||||
$instance = $this->factory->__invoke(new ServiceManager(), '');
|
||||
$this->assertInstanceOf(ImageBuilder::class, $instance);
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\PreviewGenerator\Image;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionObject;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Image\ImageFactory;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
class ImageFactoryTest extends TestCase
|
||||
{
|
||||
/** @var ImageFactory */
|
||||
private $factory;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->factory = new ImageFactory();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function noPageIsSetWhenOptionsAreNotProvided()
|
||||
{
|
||||
/** @var Image $image */
|
||||
$image = $this->factory->__invoke(new ServiceManager(['services' => [
|
||||
'config' => ['wkhtmltopdf' => []],
|
||||
]]), '');
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
|
||||
$ref = new ReflectionObject($image);
|
||||
$page = $ref->getProperty('_page');
|
||||
$page->setAccessible(true);
|
||||
$this->assertNull($page->getValue($image));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function aPageIsSetWhenOptionsIncludeTheUrl()
|
||||
{
|
||||
$expectedPage = 'foo/bar.html';
|
||||
|
||||
/** @var Image $image */
|
||||
$image = $this->factory->__invoke(new ServiceManager(['services' => [
|
||||
'config' => ['wkhtmltopdf' => []],
|
||||
]]), '', ['url' => $expectedPage]);
|
||||
$this->assertInstanceOf(Image::class, $image);
|
||||
|
||||
$ref = new ReflectionObject($image);
|
||||
$page = $ref->getProperty('_page');
|
||||
$page->setAccessible(true);
|
||||
$this->assertEquals($expectedPage, $page->getValue($image));
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\PreviewGenerator\Service;
|
||||
|
||||
use mikehaertl\wkhtmlto\Image;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Exception\PreviewGenerationException;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Image\ImageBuilder;
|
||||
use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
|
||||
use function sprintf;
|
||||
use function urlencode;
|
||||
|
||||
class PreviewGeneratorTest extends TestCase
|
||||
{
|
||||
/** @var PreviewGenerator */
|
||||
private $generator;
|
||||
/** @var ObjectProphecy */
|
||||
private $image;
|
||||
/** @var ObjectProphecy */
|
||||
private $filesystem;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->image = $this->prophesize(Image::class);
|
||||
$this->filesystem = $this->prophesize(Filesystem::class);
|
||||
|
||||
$this->generator = new PreviewGenerator(new ImageBuilder(new ServiceManager(), [
|
||||
'factories' => [
|
||||
Image::class => function () {
|
||||
return $this->image->reveal();
|
||||
},
|
||||
],
|
||||
]), $this->filesystem->reveal(), 'dir');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function alreadyProcessedElementsAreNotProcessed()
|
||||
{
|
||||
$url = 'http://foo.com';
|
||||
$this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(true)
|
||||
->shouldBeCalledOnce();
|
||||
$this->image->saveAs(Argument::cetera())->shouldBeCalledTimes(0);
|
||||
$this->assertEquals(sprintf('dir/preview_%s.png', urlencode($url)), $this->generator->generatePreview($url));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function nonProcessedElementsAreProcessed()
|
||||
{
|
||||
$url = 'http://foo.com';
|
||||
$cacheId = sprintf('preview_%s.png', urlencode($url));
|
||||
$expectedPath = 'dir/' . $cacheId;
|
||||
|
||||
$this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(false)
|
||||
->shouldBeCalledOnce();
|
||||
|
||||
$this->image->saveAs($expectedPath)->shouldBeCalledOnce();
|
||||
$this->image->getError()->willReturn('')->shouldBeCalledOnce();
|
||||
$this->assertEquals($expectedPath, $this->generator->generatePreview($url));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function errorWhileGeneratingPreviewThrowsException()
|
||||
{
|
||||
$url = 'http://foo.com';
|
||||
$cacheId = sprintf('preview_%s.png', urlencode($url));
|
||||
$expectedPath = 'dir/' . $cacheId;
|
||||
|
||||
$this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(false)
|
||||
->shouldBeCalledOnce();
|
||||
|
||||
$this->image->saveAs($expectedPath)->shouldBeCalledOnce();
|
||||
$this->image->getError()->willReturn('Error!!')->shouldBeCalledOnce();
|
||||
|
||||
$this->expectException(PreviewGenerationException::class);
|
||||
|
||||
$this->generator->generatePreview($url);
|
||||
}
|
||||
}
|
|
@ -15,9 +15,6 @@
|
|||
<testsuite name="CLI">
|
||||
<directory>./module/CLI/test</directory>
|
||||
</testsuite>
|
||||
<testsuite name="PreviewGenerator">
|
||||
<directory>./module/PreviewGenerator/test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
|
|
Loading…
Reference in a new issue