diff --git a/composer.json b/composer.json index 5b48dd20b9..72298297b0 100755 --- a/composer.json +++ b/composer.json @@ -164,7 +164,8 @@ "league/csv": "^9.1", "brumann/polyfill-unserialize": "^1.0", "vich/uploader-bundle": "1.8.*", - "maennchen/zipstream-php": "^1.2" + "maennchen/zipstream-php": "^1.2", + "league/glide-symfony": "^1.0" }, "config": { "component-dir": "public/assets" diff --git a/config/packages/oneup_flysystem.yaml b/config/packages/oneup_flysystem.yaml index 2c7b84ab22..d031670d2e 100644 --- a/config/packages/oneup_flysystem.yaml +++ b/config/packages/oneup_flysystem.yaml @@ -3,9 +3,15 @@ oneup_flysystem: resource_adapter: local: directory: '%kernel.project_dir%/var/upload/resource' - + resource_cache_adapter: + local: + directory: '%kernel.project_dir%/var/cache/resource' filesystems: resources: adapter: resource_adapter mount: resources_fs visibility: private + cache_resources: + adapter: resource_cache_adapter + mount: cache_resources_fs + visibility: private \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 9224bb4397..2f045b57a0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,3 +1,35 @@ +# Put parameters here that don't need to change on each machine where the app is deployed +# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration +parameters: + password_encryption: '%env(APP_ENCRYPT_METHOD)%' + secret: '%env(APP_SECRET)%' + locale: '%env(APP_LOCALE)%' + url_append: '%env(APP_URL_APPEND)%' + installed: '%env(APP_INSTALLED)%' + twig: + form: + resources: + - 'GeneratorBundle::fields.html.twig' + + mailer_transport: smtp + mailer_host: 127.0.0.1 + mailer_user: admin@example.com + mailer_password: null + course_info_is_not_editable: false + sonata_media.cdn.host: '%url_append%/public/resource' + sonata_page.varnish.command: 'if [ ! -r "/etc/varnish/secret" ]; then echo "VALID ERROR :/"; else varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 {{ COMMAND }} "{{ EXPRESSION }}"; fi;' + router.request_context.base_url: '%url_append%' + asset.request_context.base_path: '%url_append%' + + glide_config: + source: 'oneup_flysystem.resources_filesystem' + cache: 'oneup_flysystem.cache_resources_filesystem' + + glide_media_filters: + document_thumbnail_small: + w: 100 + h: 100 + services: # default configuration for services in *this* file _defaults: @@ -9,6 +41,11 @@ services: bind: $passwordEncrypt: '%password_encryption%' + Chamilo\CoreBundle\Component\Utils\Glide: + arguments: + - {source: '@oneup_flysystem.resources_filesystem', cache: '@oneup_flysystem.cache_resources_filesystem'} + - '%glide_media_filters%' + # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name _instanceof: @@ -140,25 +177,3 @@ imports: # - "%kernel.root_dir%/../doclib/uploads" # - true -# Put parameters here that don't need to change on each machine where the app is deployed -# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration -parameters: - password_encryption: '%env(APP_ENCRYPT_METHOD)%' - secret: '%env(APP_SECRET)%' - locale: '%env(APP_LOCALE)%' - url_append: '%env(APP_URL_APPEND)%' - installed: '%env(APP_INSTALLED)%' - twig: - form: - resources: - - 'GeneratorBundle::fields.html.twig' - - mailer_transport: smtp - mailer_host: 127.0.0.1 - mailer_user: admin@example.com - mailer_password: null - course_info_is_not_editable: false - sonata_media.cdn.host: '%url_append%/public/resource' - sonata_page.varnish.command: 'if [ ! -r "/etc/varnish/secret" ]; then echo "VALID ERROR :/"; else varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082 {{ COMMAND }} "{{ EXPRESSION }}"; fi;' - router.request_context.base_url: '%url_append%' - asset.request_context.base_path: '%url_append%' diff --git a/src/CoreBundle/Component/Utils/Glide.php b/src/CoreBundle/Component/Utils/Glide.php new file mode 100644 index 0000000000..6a94bbcb10 --- /dev/null +++ b/src/CoreBundle/Component/Utils/Glide.php @@ -0,0 +1,51 @@ +<?php +/* For licensing terms, see /license.txt */ + +namespace Chamilo\CoreBundle\Component\Utils; + +use League\Glide\Responses\SymfonyResponseFactory; +use League\Glide\Server; +use League\Glide\ServerFactory; + +/** + * Class Glide. + */ +class Glide +{ + protected $server; + protected $filters; + + /** + * Glide constructor. + * + * @param array $config + * @param array $filters + */ + public function __construct(array $config, array $filters) + { + $this->server = ServerFactory::create( + [ + 'response' => new SymfonyResponseFactory(), + 'source' => $config['source'], + 'cache' => $config['cache'], + ] + ); + $this->filters = $filters; + } + + /** + * @return Server + */ + public function getServer(): Server + { + return $this->server; + } + + /** + * @return array + */ + public function getFilters(): array + { + return $this->filters; + } +} diff --git a/src/CoreBundle/Controller/ResourceController.php b/src/CoreBundle/Controller/ResourceController.php index 10efaa955a..060873c354 100644 --- a/src/CoreBundle/Controller/ResourceController.php +++ b/src/CoreBundle/Controller/ResourceController.php @@ -9,6 +9,7 @@ use APY\DataGridBundle\Grid\Export\CSVExport; use APY\DataGridBundle\Grid\Export\ExcelExport; use APY\DataGridBundle\Grid\Grid; use APY\DataGridBundle\Grid\Source\Entity; +use Chamilo\CoreBundle\Component\Utils\Glide; use Chamilo\CoreBundle\Entity\Resource\ResourceNode; use Chamilo\CoreBundle\Entity\Resource\ResourceRight; use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter; @@ -17,8 +18,6 @@ use Chamilo\CourseBundle\Controller\CourseControllerTrait; use Chamilo\CourseBundle\Entity\CDocument; use Chamilo\CourseBundle\Repository\CDocumentRepository; use FOS\RestBundle\View\View; -use League\Flysystem\MountManager; -use Liip\ImagineBundle\Service\FilterService; use Sonata\MediaBundle\Provider\ImageProvider; use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent; use Sylius\Component\Resource\Exception\UpdateHandlingException; @@ -35,8 +34,6 @@ use Vich\UploaderBundle\Util\Transliterator; * Class ResourceController. * * @author Julio Montoya <gugli100@gmail.com>. - * - * @package Chamilo\CoreBundle\Controller */ class ResourceController extends BaseController implements CourseControllerInterface { @@ -404,23 +401,19 @@ class ResourceController extends BaseController implements CourseControllerInter * * @param Request $request * @param CDocumentRepository $documentRepo - * @param FilterService $filterService * * @return Response */ public function showAction( Request $request, CDocumentRepository $documentRepo, - FilterService $filterService, - MountManager $mountManager + Glide $glide ): Response { $file = $request->get('file'); $type = $request->get('type'); - $filter = $request->get('filter'); // see list of filters in config/packages/liip_imagine.yaml - - if (empty($type)) { - $type = 'show'; - } + // see list of filters in config/packages/liip_imagine.yaml + $filter = $request->get('filter'); + $type = !empty($type) ? $type : 'show'; $criteria = [ 'path' => "/$file", @@ -448,18 +441,11 @@ class ResourceController extends BaseController implements CourseControllerInter throw new NotFoundHttpException(); } - //$media = $resourceFile->getMedia(); - //$format = MediaProviderInterface::FORMAT_REFERENCE; $fileName = $resourceNode->getName(); $filePath = $resourceFile->getFile()->getPathname(); $mimeType = $resourceFile->getMimeType(); - // @todo use $documentRepo - $fs = $this->get('oneup_flysystem.mount_manager')->getFilesystem('resources_fs'); - $stream = $fs->readStream($filePath); - $response = new StreamedResponse(function () use ($stream): void { - stream_copy_to_stream($stream, fopen('php://output', 'wb')); - }); + //ServerFactory switch ($type) { case 'download': @@ -470,41 +456,21 @@ class ResourceController extends BaseController implements CourseControllerInter case 'show': default: $forceDownload = false; - // $resourceFile = $fs->readStream($resourceFile->getFile()->getPathname()); - //var_dump($resourceFile->getFile()->getPathname()); - //var_dump($fs->read($resourceFile->getFile()->getPathname())); - // $downloadHandler doesn't work with flysystem: - // https://github.com/dustin10/VichUploaderBundle/issues/827 - //return $downloadHandler->downloadObject($resourceFile, 'file', ResourceFile::class, $name); - - /** @var ImageProvider $provider */ - /* $provider = $this->get('sonata.media.pool')->getProvider($media->getProviderName()); - $filename = sprintf( - '%s/%s', - $provider->getFilesystem()->getAdapter()->getDirectory(), - $provider->generatePrivateUrl($media, $format) - ); - + // See filter definition if (!empty($filter)) { - $resourcePath = $filterService->getUrlOfFilteredImage( - $provider->generatePrivateUrl($media, $format), - $filter - ); - if ($resourcePath) { - $cacheFolder = '/var/cache/resource/'; - $pos = strpos($resourcePath, $cacheFolder); - $cacheValue = substr($resourcePath, $pos + strlen($cacheFolder), strlen($resourcePath)); - $cachedFile = $this->get('kernel')->getResourceCacheDir().$cacheValue; - - if (is_file($cachedFile)) { - $filename = $cachedFile; - } - } + $server = $glide->getServer(); + $filter = $glide->getFilters()[$filter] ?? []; + + return $server->getImageResponse($filePath, $filter); } - return new BinaryFileResponse($filename);*/ break; } + $fs = $documentRepo->getFileSystem(); + $stream = $fs->readStream($filePath); + $response = new StreamedResponse(function () use ($stream): void { + stream_copy_to_stream($stream, fopen('php://output', 'wb')); + }); $disposition = $response->headers->makeDisposition( $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE, Transliterator::transliterate($fileName) diff --git a/src/CoreBundle/Repository/ResourceRepository.php b/src/CoreBundle/Repository/ResourceRepository.php index 7f6638d553..44674caea9 100644 --- a/src/CoreBundle/Repository/ResourceRepository.php +++ b/src/CoreBundle/Repository/ResourceRepository.php @@ -61,6 +61,22 @@ class ResourceRepository extends EntityRepository $this->entityManager = $entityManager; } + /** + * @return FilesystemInterface + */ + public function getFileSystem() + { + return $this->fs; + } + + /** + * @return EntityManager + */ + public function getEntityManager(): EntityManager + { + return $this->entityManager; + } + /** * @return EntityRepository */ @@ -92,13 +108,7 @@ class ResourceRepository extends EntityRepository return $this->getRepository()->findOneBy($criteria, $orderBy); } - /** - * @return EntityManager - */ - public function getEntityManager(): EntityManager - { - return $this->entityManager; - } + /** * Creates a ResourceNode.