diff --git a/.gitignore b/.gitignore
index a0f6acf5..00b9cd31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,7 @@
npm-debug.log
yarn-error.log
###< symfony/webpack-encore-bundle ###
+
+###> liip/imagine-bundle ###
+/public/media/cache/
+###< liip/imagine-bundle ###
diff --git a/composer.json b/composer.json
index 93f57c79..a016a2eb 100644
--- a/composer.json
+++ b/composer.json
@@ -3,13 +3,17 @@
"license": "GPL-2.0-or-later",
"require": {
"php": "^7.1.3",
+ "ext-bcmath": "*",
"ext-ctype": "*",
"ext-iconv": "*",
"ext-intl": "*",
+ "ext-json": "*",
"ext-mbstring": "*",
+ "ext-gd": "*",
"doctrine/annotations": "^1.6",
"florianv/swap": "^4.0",
"friendsofsymfony/ckeditor-bundle": "^2.0",
+ "liip/imagine-bundle": "^2.2",
"nyholm/psr7": "^1.1",
"ocramius/proxy-manager": "2.1.*",
"omines/datatables-bundle": "^0.3.1",
@@ -42,9 +46,7 @@
"twig/extensions": "^1.5",
"twig/extra-bundle": "3.x-dev",
"twig/intl-extra": "3.x-dev",
- "webmozart/assert": "^1.4",
- "ext-bcmath": "*",
- "ext-json": "*"
+ "webmozart/assert": "^1.4"
},
"require-dev": {
"roave/security-advisories": "dev-master",
diff --git a/composer.lock b/composer.lock
index 807dc782..378cda36 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "b991c6efd2c3ad84f8c1f76ae8efac2c",
+ "content-hash": "634b7b41a97404c6278ed91d1926f853",
"packages": [
{
"name": "clue/stream-filter",
@@ -1756,6 +1756,64 @@
],
"time": "2019-07-01T23:21:34+00:00"
},
+ {
+ "name": "imagine/imagine",
+ "version": "1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/avalanche123/Imagine.git",
+ "reference": "eec39b2092bc8008a92b8d63824476413dbe7511"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/avalanche123/Imagine/zipball/eec39b2092bc8008a92b8d63824476413dbe7511",
+ "reference": "eec39b2092bc8008a92b8d63824476413dbe7511",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "2.2.*",
+ "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.4"
+ },
+ "suggest": {
+ "ext-gd": "to use the GD implementation",
+ "ext-gmagick": "to use the Gmagick implementation",
+ "ext-imagick": "to use the Imagick implementation"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-develop": "0.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Imagine\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bulat Shakirzyanov",
+ "email": "mallluhuct@gmail.com",
+ "homepage": "http://avalanche123.com"
+ }
+ ],
+ "description": "Image processing for PHP 5.3",
+ "homepage": "http://imagine.readthedocs.org/",
+ "keywords": [
+ "drawing",
+ "graphics",
+ "image manipulation",
+ "image processing"
+ ],
+ "time": "2019-07-09T06:55:48+00:00"
+ },
{
"name": "jdorn/sql-formatter",
"version": "v1.2.17",
@@ -1806,6 +1864,107 @@
],
"time": "2014-01-12T16:20:24+00:00"
},
+ {
+ "name": "liip/imagine-bundle",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/liip/LiipImagineBundle.git",
+ "reference": "2cf633e0f335a9f1f0bb9d55726a73aca9259ea4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/2cf633e0f335a9f1f0bb9d55726a73aca9259ea4",
+ "reference": "2cf633e0f335a9f1f0bb9d55726a73aca9259ea4",
+ "shasum": ""
+ },
+ "require": {
+ "imagine/imagine": "^0.7.1|^1.1",
+ "php": "^7.1",
+ "symfony/asset": "^3.4|^4.2",
+ "symfony/filesystem": "^3.4|^4.2",
+ "symfony/finder": "^3.4|^4.2",
+ "symfony/framework-bundle": "^3.4|^4.2",
+ "symfony/options-resolver": "^3.4|^4.2",
+ "symfony/process": "^3.4|^4.2",
+ "symfony/templating": "^3.4|^4.2",
+ "symfony/translation": "^3.4|^4.2"
+ },
+ "require-dev": {
+ "amazonwebservices/aws-sdk-for-php": "^1.0",
+ "aws/aws-sdk-php": "^2.4",
+ "doctrine/cache": "^1.1",
+ "doctrine/orm": "^2.3",
+ "enqueue/enqueue-bundle": "^0.9",
+ "ext-gd": "*",
+ "friendsofphp/php-cs-fixer": "^2.10",
+ "league/flysystem": "^1.0",
+ "psr/log": "^1.0",
+ "symfony/browser-kit": "^3.4|^4.2",
+ "symfony/console": "^3.4|^4.2",
+ "symfony/dependency-injection": "^3.4|^4.2",
+ "symfony/form": "^3.4|^4.2",
+ "symfony/phpunit-bridge": "^4.3",
+ "symfony/validator": "^3.4|^4.2",
+ "symfony/yaml": "^3.4|^4.2",
+ "twig/twig": "^1.34|^2.4"
+ },
+ "suggest": {
+ "alcaeus/mongo-php-adapter": "required on PHP >= 7.0 to use mongo components with mongodb extension",
+ "amazonwebservices/aws-sdk-for-php": "required to use AWS version 1 cache resolver",
+ "aws/aws-sdk-php": "required to use AWS version 2/3 cache resolver",
+ "doctrine/mongodb-odm": "required to use mongodb-backed doctrine components",
+ "enqueue/enqueue-bundle": "^0.9 add if you like to process images in background",
+ "ext-exif": "required to read EXIF metadata from images",
+ "ext-gd": "required to use gd driver",
+ "ext-gmagick": "required to use gmagick driver",
+ "ext-imagick": "required to use imagick driver",
+ "ext-mongo": "required for mongodb components on PHP <7.0",
+ "ext-mongodb": "required for mongodb components on PHP >=7.0",
+ "league/flysystem": "required to use FlySystem data loader or cache resolver",
+ "monolog/monolog": "A psr/log compatible logger is required to enable logging",
+ "twig/twig": "required to use the provided Twig extension. Version 1.12 or greater needed"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-1.0": "1.7-dev",
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Liip\\ImagineBundle\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Liip and other contributors",
+ "homepage": "https://github.com/liip/LiipImagineBundle/contributors"
+ }
+ ],
+ "description": "This bundle provides an image manipulation abstraction toolkit for Symfony-based projects.",
+ "homepage": "http://liip.ch",
+ "keywords": [
+ "bundle",
+ "image",
+ "imagine",
+ "liip",
+ "manipulation",
+ "photos",
+ "pictures",
+ "symfony",
+ "transformation"
+ ],
+ "time": "2019-10-04T05:45:14+00:00"
+ },
{
"name": "monolog/monolog",
"version": "1.25.1",
@@ -6389,6 +6548,62 @@
"homepage": "http://symfony.com",
"time": "2019-06-18T15:27:04+00:00"
},
+ {
+ "name": "symfony/templating",
+ "version": "v4.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/templating.git",
+ "reference": "15407776e1fe250ed3fa1c1a679482c60c2affe3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/templating/zipball/15407776e1fe250ed3fa1c1a679482c60c2affe3",
+ "reference": "15407776e1fe250ed3fa1c1a679482c60c2affe3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1.3",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "require-dev": {
+ "psr/log": "~1.0"
+ },
+ "suggest": {
+ "psr/log-implementation": "For using debug logging in loaders"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Templating\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Templating Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-26T08:26:39+00:00"
+ },
{
"name": "symfony/translation",
"version": "v4.3.4",
@@ -9023,12 +9238,12 @@
"prefer-lowest": false,
"platform": {
"php": "^7.1.3",
+ "ext-bcmath": "*",
"ext-ctype": "*",
"ext-iconv": "*",
"ext-intl": "*",
- "ext-mbstring": "*",
- "ext-bcmath": "*",
- "ext-json": "*"
+ "ext-json": "*",
+ "ext-mbstring": "*"
},
"platform-dev": [],
"platform-overrides": {
diff --git a/config/bundles.php b/config/bundles.php
index a653a57a..18638810 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -19,4 +19,5 @@ return [
Shivas\VersioningBundle\ShivasVersioningBundle::class => ['all' => true],
FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
+ Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
];
diff --git a/config/packages/liip_imagine.yaml b/config/packages/liip_imagine.yaml
new file mode 100644
index 00000000..5a7319d0
--- /dev/null
+++ b/config/packages/liip_imagine.yaml
@@ -0,0 +1,20 @@
+# See dos how to configure the bundle: https://symfony.com/doc/current/bundles/LiipImagineBundle/basic-usage.html
+liip_imagine:
+ # valid drivers options include "gd" or "gmagick" or "imagick"
+ driver: "gd"
+
+ filter_sets:
+ thumbnail_sm:
+ quality: 70
+ filters:
+ thumbnail:
+ size: [150, 150]
+ mode: inset
+
+ thumbnail_md:
+ quality: 75
+ filters:
+ filters:
+ thumbnail:
+ size: [300, 300]
+ mode: inset
diff --git a/config/routes/liip_imagine.yaml b/config/routes/liip_imagine.yaml
new file mode 100644
index 00000000..201cbd5d
--- /dev/null
+++ b/config/routes/liip_imagine.yaml
@@ -0,0 +1,2 @@
+_liip_imagine:
+ resource: "@LiipImagineBundle/Resources/config/routing.yaml"
diff --git a/config/services.yaml b/config/services.yaml
index 589d7aaa..643ffecd 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -11,7 +11,7 @@ parameters:
banner: '' # The info text shown in the homepage
use_gravatar: true # Set to false, if no Gravatar images should be used for user profiles.
default_currency: 'EUR' # The currency that should be used
- media_directory: 'data/media/'
+ media_directory: 'public/media/'
db_version_fallback: '5.6' # Be sure to override this, in your .env with your real DB version
services:
@@ -32,6 +32,9 @@ services:
resource: '../src/Controller'
tags: ['controller.service_arguments']
+ Liip\ImagineBundle\Service\FilterService:
+ alias: 'liip_imagine.service.filter'
+
app.doctrine.elementListener:
class: App\Security\EntityListeners\ElementPermissionListener
public: false
diff --git a/data/media/.gitignore b/data/media/.gitignore
deleted file mode 100644
index 2e0e43de..00000000
--- a/data/media/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# Ignore everything
-*
\ No newline at end of file
diff --git a/public/media/.gitignore b/public/media/.gitignore
new file mode 100644
index 00000000..420385b9
--- /dev/null
+++ b/public/media/.gitignore
@@ -0,0 +1,3 @@
+# Ignore everything except this .gitignore
+d274.gif
+!.gitignore
\ No newline at end of file
diff --git a/public/media/currency/2/test-5d95f7efefc33.webp b/public/media/currency/2/test-5d95f7efefc33.webp
new file mode 100644
index 00000000..122741b6
Binary files /dev/null and b/public/media/currency/2/test-5d95f7efefc33.webp differ
diff --git a/public/media/part/1108/test-5d9616224f44a.webp b/public/media/part/1108/test-5d9616224f44a.webp
new file mode 100644
index 00000000..122741b6
Binary files /dev/null and b/public/media/part/1108/test-5d9616224f44a.webp differ
diff --git a/public/media/part/2/repositoryopengraphtemplate.png b/public/media/part/2/repositoryopengraphtemplate.png
new file mode 100644
index 00000000..d03dffd8
Binary files /dev/null and b/public/media/part/2/repositoryopengraphtemplate.png differ
diff --git a/src/DataTables/AttachmentDataTable.php b/src/DataTables/AttachmentDataTable.php
index d7424fee..93bbd06a 100644
--- a/src/DataTables/AttachmentDataTable.php
+++ b/src/DataTables/AttachmentDataTable.php
@@ -37,6 +37,7 @@ use App\Entity\Attachments\Attachment;
use App\Entity\Attachments\FootprintAttachment;
use App\Entity\Parts\Part;
use App\Services\AttachmentHelper;
+use App\Services\Attachments\AttachmentURLGenerator;
use App\Services\ElementTypeNameGenerator;
use App\Services\EntityURLGenerator;
use Doctrine\ORM\QueryBuilder;
@@ -54,14 +55,17 @@ class AttachmentDataTable implements DataTableTypeInterface
protected $entityURLGenerator;
protected $attachmentHelper;
protected $elementTypeNameGenerator;
+ protected $attachmentURLGenerator;
public function __construct(TranslatorInterface $translator, EntityURLGenerator $entityURLGenerator,
- AttachmentHelper $attachmentHelper, ElementTypeNameGenerator $elementTypeNameGenerator)
+ AttachmentHelper $attachmentHelper, AttachmentURLGenerator $attachmentURLGenerator,
+ ElementTypeNameGenerator $elementTypeNameGenerator)
{
$this->translator = $translator;
$this->entityURLGenerator = $entityURLGenerator;
$this->attachmentHelper = $attachmentHelper;
$this->elementTypeNameGenerator = $elementTypeNameGenerator;
+ $this->attachmentURLGenerator = $attachmentURLGenerator;
}
protected function getQuery(QueryBuilder $builder)
@@ -89,7 +93,7 @@ class AttachmentDataTable implements DataTableTypeInterface
return sprintf(
'
',
'Part image',
- $this->entityURLGenerator->viewURL($context),
+ $this->attachmentURLGenerator->getThumbnailURL($context),
'img-fluid hoverpic'
);
}
diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php
index e3d87bbd..85e59ceb 100644
--- a/src/DataTables/PartsDataTable.php
+++ b/src/DataTables/PartsDataTable.php
@@ -39,6 +39,7 @@ use App\Entity\Parts\PartLot;
use App\Entity\Parts\Storelocation;
use App\Entity\Parts\Supplier;
use App\Services\AmountFormatter;
+use App\Services\Attachments\AttachmentURLGenerator;
use App\Services\Attachments\PartPreviewGenerator;
use App\Services\EntityURLGenerator;
use App\Services\ToolsTreeBuilder;
@@ -65,15 +66,18 @@ class PartsDataTable implements DataTableTypeInterface
protected $treeBuilder;
protected $amountFormatter;
protected $previewGenerator;
+ protected $attachmentURLGenerator;
public function __construct(EntityURLGenerator $urlGenerator, TranslatorInterface $translator,
- TreeBuilder $treeBuilder, AmountFormatter $amountFormatter, PartPreviewGenerator $previewGenerator)
+ TreeBuilder $treeBuilder, AmountFormatter $amountFormatter,
+ PartPreviewGenerator $previewGenerator, AttachmentURLGenerator $attachmentURLGenerator)
{
$this->urlGenerator = $urlGenerator;
$this->translator = $translator;
$this->treeBuilder = $treeBuilder;
$this->amountFormatter = $amountFormatter;
$this->previewGenerator = $previewGenerator;
+ $this->attachmentURLGenerator = $attachmentURLGenerator;
}
protected function getQuery(QueryBuilder $builder)
@@ -164,7 +168,7 @@ class PartsDataTable implements DataTableTypeInterface
return sprintf(
'
',
'Part image',
- $this->urlGenerator->viewURL($preview_attachment),
+ $this->attachmentURLGenerator->getThumbnailURL($preview_attachment),
'img-fluid hoverpic'
);
}
diff --git a/src/Entity/Attachments/Attachment.php b/src/Entity/Attachments/Attachment.php
index a3a61d07..e62149c4 100644
--- a/src/Entity/Attachments/Attachment.php
+++ b/src/Entity/Attachments/Attachment.php
@@ -64,7 +64,7 @@ abstract class Attachment extends NamedDBElement
/**
* When the path begins with one of this placeholders
*/
- public const INTERNAL_PLACEHOLDER = ['%BASE%', '%MEDIA%'];
+ public const INTERNAL_PLACEHOLDER = ['%BASE%', '%MEDIA%', '%SECURE%'];
/** @var array Placeholders for attachments which using built in files. */
public const BUILTIN_PLACEHOLDER = ['%FOOTPRINTS%', '%FOOTPRINTS3D%'];
@@ -156,6 +156,23 @@ abstract class Attachment extends NamedDBElement
return !in_array($tmp[0], array_merge(static::INTERNAL_PLACEHOLDER, static::BUILTIN_PLACEHOLDER), false);
}
+ /**
+ * Check if this attachment is saved in a secure place.
+ * This means that it can not be accessed directly via a web request, but must be viewed via a controller.
+ * @return bool True, if the file is secure.
+ */
+ public function isSecure() : bool
+ {
+ //After the %PLACEHOLDER% comes a slash, so we can check if we have a placholder via explode
+ $tmp = explode("/", $this->path);
+
+ if (empty($tmp)) {
+ return false;
+ }
+
+ return $tmp[0] === '%SECURE%';
+ }
+
/**
* Checks if the attachment file is using a builtin file. (see BUILTIN_PLACEHOLDERS const for possible placeholders)
* If a file is built in, the path is shown to user in url field (no sensitive infos are provided)
diff --git a/src/Services/AttachmentHelper.php b/src/Services/AttachmentHelper.php
index fd06626b..e280115d 100644
--- a/src/Services/AttachmentHelper.php
+++ b/src/Services/AttachmentHelper.php
@@ -75,7 +75,8 @@ class AttachmentHelper
}
/**
- * Returns the absolute filepath of the attachment. Null is returned, if the attachment is externally saved.
+ * Returns the absolute filepath of the attachment. Null is returned, if the attachment is externally saved,
+ * or is not existing.
* @param Attachment $attachment The attachment for which the filepath should be determined
* @return string|null
*/
@@ -95,7 +96,13 @@ class AttachmentHelper
if ($path === null) {
return null;
}
- return realpath($path);
+
+ $tmp = realpath($path);
+ //If path is not existing realpath returns false.
+ if ($tmp === false) {
+ return null;
+ }
+ return $tmp;
}
/**
diff --git a/src/Services/Attachments/AttachmentURLGenerator.php b/src/Services/Attachments/AttachmentURLGenerator.php
new file mode 100644
index 00000000..7ed1896b
--- /dev/null
+++ b/src/Services/Attachments/AttachmentURLGenerator.php
@@ -0,0 +1,156 @@
+assets = $assets;
+ $this->pathResolver = $pathResolver;
+ $this->urlGenerator = $urlGenerator;
+ $this->attachmentHelper = $attachmentHelper;
+ $this->filterService = $filterService;
+
+
+ //Determine a normalized path to the public folder (assets are relative to this folder)
+ $this->public_path = $this->pathResolver->parameterToAbsolutePath('public');
+ }
+
+ /**
+ * Converts the absolute file path to a version relative to the public folder, that can be passed to asset
+ * Asset Component functions.
+ * @param string $absolute_path The absolute path that should be converted.
+ * @param string|null $public_path The public path to which the relative pathes should be created.
+ * The path must NOT have a trailing slash!
+ * If this is set to null, the global public/ folder is used.
+ * @return string|null The relative version of the string. Null if the absolute path was not a child folder
+ * of public path
+ */
+ public function absolutePathToAssetPath(string $absolute_path, ?string $public_path = null) : ?string
+ {
+ if ($public_path === null) {
+ $public_path = $this->public_path;
+ }
+
+ //Our absolute path must begin with public path or we can not use it for asset pathes.
+ if (strpos($absolute_path, $public_path) !== 0) {
+ return null;
+ }
+
+ //Return the part relative after public path.
+ return substr($absolute_path, strlen($public_path) + 1);
+ }
+
+ /**
+ * Returns a URL under which the attachment file can be viewed.
+ * @param Attachment $attachment
+ * @return string
+ */
+ public function getViewURL(Attachment $attachment) : string
+ {
+ $absolute_path = $this->attachmentHelper->toAbsoluteFilePath($attachment);
+ if ($absolute_path === null) {
+ throw new \RuntimeException(
+ 'The given attachment is external or has no valid file, so no URL can get generated for it!
+ Use Attachment::getURL() to get the external URL!'
+ );
+ }
+
+ $asset_path = $this->absolutePathToAssetPath($absolute_path);
+ //If path is not relative to public path or marked as secure, serve it via controller
+ if ($asset_path === null || $attachment->isSecure()) {
+ return $this->urlGenerator->generate('attachment_view', ['id' => $attachment->getID()]);
+ }
+
+ //Otherwise we can serve the relative path via Asset component
+ return $this->assets->getUrl($asset_path);
+ }
+
+ /**
+ * Returns a URL to an thumbnail of the attachment file.
+ * @param Attachment $attachment
+ * @param string $filter_name
+ * @return string
+ */
+ public function getThumbnailURL(Attachment $attachment, string $filter_name = 'thumbnail_sm') : string
+ {
+ if (!$attachment->isPicture()) {
+ throw new \InvalidArgumentException('Thumbnail creation only works for picture attachments!');
+ }
+
+ $absolute_path = $this->attachmentHelper->toAbsoluteFilePath($attachment);
+ if ($absolute_path === null) {
+ throw new \RuntimeException(
+ 'The given attachment is external or has no valid file, so no URL can get generated for it!
+ Use Attachment::getURL() to get the external URL!'
+ );
+ }
+
+ $asset_path = $this->absolutePathToAssetPath($absolute_path);
+ //If path is not relative to public path or marked as secure, serve it via controller
+ if ($asset_path === null || $attachment->isSecure()) {
+ return $this->urlGenerator->generate('attachment_view', ['id' => $attachment->getID()]);
+ }
+
+ //Otherwise we can serve the relative path via Asset component
+ return $this->filterService->getUrlOfFilteredImage($asset_path, 'thumbnail_sm');
+ }
+
+ /**
+ * Returns a download link to the file associated with the attachment
+ * @param Attachment $attachment
+ * @return string
+ */
+ public function getDownloadURL(Attachment $attachment) : string
+ {
+ //Redirect always to download controller, which sets the correct headers for downloading:
+ $this->urlGenerator->generate('attachment_download', ['id' => $attachment->getID()]);
+ }
+}
\ No newline at end of file
diff --git a/src/Services/EntityURLGenerator.php b/src/Services/EntityURLGenerator.php
index c032cc2b..44ff15b6 100644
--- a/src/Services/EntityURLGenerator.php
+++ b/src/Services/EntityURLGenerator.php
@@ -45,6 +45,7 @@ use App\Entity\PriceInformations\Currency;
use App\Entity\UserSystem\Group;
use App\Entity\UserSystem\User;
use App\Exceptions\EntityNotSupportedException;
+use App\Services\Attachments\AttachmentURLGenerator;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
@@ -60,10 +61,12 @@ class EntityURLGenerator
* @var UrlGeneratorInterface
*/
protected $urlGenerator;
+ protected $attachmentURLGenerator;
- public function __construct(UrlGeneratorInterface $urlGenerator)
+ public function __construct(UrlGeneratorInterface $urlGenerator, AttachmentURLGenerator $attachmentURLGenerator)
{
$this->urlGenerator = $urlGenerator;
+ $this->attachmentURLGenerator = $attachmentURLGenerator;
}
/**
@@ -138,7 +141,8 @@ class EntityURLGenerator
if ($entity->isExternal()) { //For external attachments, return the link to external path
return $entity->getURL();
}
- return $this->urlGenerator->generate('attachment_view', ['id' => $entity->getID()]);
+ //return $this->urlGenerator->generate('attachment_view', ['id' => $entity->getID()]);
+ return $this->attachmentURLGenerator->getViewURL($entity);
}
//Otherwise throw an error
@@ -151,7 +155,7 @@ class EntityURLGenerator
if ($entity->isExternal()) { //For external attachments, return the link to external path
return $entity->getURL();
}
- return $this->urlGenerator->generate('attachment_download', ['id' => $entity->getID()]);
+ return $this->attachmentURLGenerator->getDownloadURL($entity);
}
//Otherwise throw an error
diff --git a/symfony.lock b/symfony.lock
index d8d76bac..98c1a9b1 100644
--- a/symfony.lock
+++ b/symfony.lock
@@ -141,9 +141,25 @@
"guzzlehttp/psr7": {
"version": "1.6.1"
},
+ "imagine/imagine": {
+ "version": "1.2.2"
+ },
"jdorn/sql-formatter": {
"version": "v1.2.17"
},
+ "liip/imagine-bundle": {
+ "version": "1.8",
+ "recipe": {
+ "repo": "github.com/symfony/recipes-contrib",
+ "branch": "master",
+ "version": "1.8",
+ "ref": "1d42bc3f713130582e6e0c475c49bc327ab0a2a2"
+ },
+ "files": [
+ "./config/packages/liip_imagine.yaml",
+ "./config/routes/liip_imagine.yaml"
+ ]
+ },
"monolog/monolog": {
"version": "1.24.0"
},
@@ -550,6 +566,9 @@
"./config/packages/test/swiftmailer.yaml"
]
},
+ "symfony/templating": {
+ "version": "v4.3.4"
+ },
"symfony/test-pack": {
"version": "v1.0.5"
},
diff --git a/tests/Services/Attachments/AttachmentPathResolverTest.php b/tests/Services/Attachments/AttachmentPathResolverTest.php
index cd0c03d6..e8011202 100644
--- a/tests/Services/Attachments/AttachmentPathResolverTest.php
+++ b/tests/Services/Attachments/AttachmentPathResolverTest.php
@@ -56,7 +56,7 @@ class AttachmentPathResolverTest extends WebTestCase
self::bootKernel();
self::$projectDir_orig = realpath(self::$kernel->getProjectDir());
self::$projectDir = str_replace('\\', '/', self::$projectDir_orig);
- self::$media_path = self::$projectDir . '/data/media';
+ self::$media_path = self::$projectDir . '/public/media';
self::$footprint_path = self::$projectDir . '/public/img/footprints';
}
diff --git a/tests/Services/Attachments/AttachmentURLGeneratorTest.php b/tests/Services/Attachments/AttachmentURLGeneratorTest.php
new file mode 100644
index 00000000..eee43db9
--- /dev/null
+++ b/tests/Services/Attachments/AttachmentURLGeneratorTest.php
@@ -0,0 +1,72 @@
+get(AttachmentURLGenerator::class);
+ }
+
+ public function dataProvider()
+ {
+ return [
+ ['/public/test.jpg', 'test.jpg'],
+ ['/public/folder/test.jpg', 'folder/test.jpg'],
+ ['/not/public/test.jpg', null],
+ ['/public/', ''],
+ ['not/absolute/test.jpg', null]
+ ];
+ }
+
+ /**
+ * @dataProvider dataProvider
+ * @param $input
+ * @param $expected
+ */
+ public function testabsolutePathToAssetPath($input, $expected)
+ {
+ $this->assertEquals($expected, static::$service->absolutePathToAssetPath($input, static::PUBLIC_DIR));
+ }
+}
\ No newline at end of file