Deleted everything related with previews generation

This commit is contained in:
Alejandro Celaya 2019-12-31 13:40:38 +01:00
parent 9d36534230
commit 78b484e657
30 changed files with 22 additions and 818 deletions

2
.gitattributes vendored
View file

@ -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

View file

@ -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.

View file

@ -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": {

View file

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
/* @deprecated */
return [
'preview_generation' => [
'files_location' => 'data/cache',
],
];

View file

@ -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')

View file

@ -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"
}
}
}
}
}
}
}

View file

@ -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"

View file

@ -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,

View file

@ -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 => [

View file

@ -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);
}
}
}
}

View file

@ -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;
}
}

View file

@ -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],
],

View file

@ -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],
],
],
];

View file

@ -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);
}
}
}

View file

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

View file

@ -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',
],
],
];

View file

@ -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');
}
}

View file

@ -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));
}
}

View file

@ -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;
}

View file

@ -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,
]]);
}
}

View file

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\PreviewGenerator\Image;
use Zend\ServiceManager\ServiceLocatorInterface;
/** @deprecated */
interface ImageBuilderInterface extends ServiceLocatorInterface
{
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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);
}
}

View file

@ -15,9 +15,6 @@
<testsuite name="CLI">
<directory>./module/CLI/test</directory>
</testsuite>
<testsuite name="PreviewGenerator">
<directory>./module/PreviewGenerator/test</directory>
</testsuite>
</testsuites>
<filter>