core/lib/Thelia/Action/Document.php line 68

  1. <?php
  2. /*
  3.  * This file is part of the Thelia package.
  4.  * http://www.thelia.net
  5.  *
  6.  * (c) OpenStudio <info@thelia.net>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Thelia\Action;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use Thelia\Core\Event\Document\DocumentEvent;
  14. use Thelia\Core\Event\TheliaEvents;
  15. use Thelia\Exception\DocumentException;
  16. use Thelia\Model\ConfigQuery;
  17. use Thelia\Tools\URL;
  18. /**
  19.  * Document management actions. This class handles document processing an caching.
  20.  *
  21.  * Basically, documents are stored outside the web space (by default in local/media/documents),
  22.  * and cached in the web space (by default in web/local/documents).
  23.  *
  24.  * In the documents caches directory, a subdirectory for documents categories (eg. product, category, folder, etc.) is
  25.  * automatically created, and the cached document is created here. Plugin may use their own subdirectory as required.
  26.  *
  27.  * The cached document name contains a hash of the processing options, and the original (normalized) name of the document.
  28.  *
  29.  * A copy (or symbolic link, by default) of the original document is always created in the cache, so that the full
  30.  * resolution document is always available.
  31.  *
  32.  * If a problem occurs, an DocumentException may be thrown.
  33.  *
  34.  * @author Franck Allimant <franck@cqfdev.fr>
  35.  */
  36. class Document extends BaseCachedFile implements EventSubscriberInterface
  37. {
  38.     /**
  39.      * @var string Config key for document delivery mode
  40.      */
  41.     public const CONFIG_DELIVERY_MODE 'original_document_delivery_mode';
  42.     /**
  43.      * @return string root of the document cache directory in web space
  44.      */
  45.     protected function getCacheDirFromWebRoot()
  46.     {
  47.         return ConfigQuery::read('document_cache_dir_from_web_root''cache'.DS.'documents');
  48.     }
  49.     /**
  50.      * Process document and write the result in the document cache.
  51.      *
  52.      * When the original document is required, create either a symbolic link with the
  53.      * original document in the cache dir, or copy it in the cache dir if it's not already done.
  54.      *
  55.      * This method updates the cache_file_path and file_url attributes of the event
  56.      *
  57.      * @param DocumentEvent $event Event
  58.      *
  59.      * @throws \Thelia\Exception\DocumentException
  60.      * @throws \InvalidArgumentException           , DocumentException
  61.      */
  62.     public function processDocument(DocumentEvent $event): void
  63.     {
  64.         $subdir $event->getCacheSubdirectory();
  65.         $sourceFile $event->getSourceFilepath();
  66.         if (null == $subdir || null == $sourceFile) {
  67.             throw new \InvalidArgumentException('Cache sub-directory and source file path cannot be null');
  68.         }
  69.         $originalDocumentPathInCache $this->getCacheFilePath($subdir$sourceFiletrue);
  70.         if (!file_exists($originalDocumentPathInCache)) {
  71.             if (!file_exists($sourceFile)) {
  72.                 throw new DocumentException(sprintf('Source document file %s does not exists.'$sourceFile));
  73.             }
  74.             $mode ConfigQuery::read(self::CONFIG_DELIVERY_MODE'symlink');
  75.             if ($mode == 'symlink') {
  76.                 if (false === symlink($sourceFile$originalDocumentPathInCache)) {
  77.                     throw new DocumentException(sprintf('Failed to create symbolic link for %s in %s document cache directory'basename($sourceFile), $subdir));
  78.                 }
  79.             } else {
  80.                 // mode = 'copy'
  81.                 if (false === @copy($sourceFile$originalDocumentPathInCache)) {
  82.                     throw new DocumentException(sprintf('Failed to copy %s in %s document cache directory'basename($sourceFile), $subdir));
  83.                 }
  84.             }
  85.         }
  86.         // Compute the document URL
  87.         $documentUrl $this->getCacheFileURL($subdirbasename($originalDocumentPathInCache));
  88.         // Update the event with file path and file URL
  89.         $event->setDocumentPath($documentUrl);
  90.         $event->setDocumentUrl(URL::getInstance()->absoluteUrl($documentUrlnullURL::PATH_TO_FILE$this->cdnBaseUrl));
  91.     }
  92.     /**
  93.      * {@inheritdoc}
  94.      */
  95.     public static function getSubscribedEvents()
  96.     {
  97.         return [
  98.             TheliaEvents::DOCUMENT_PROCESS => ['processDocument'128],
  99.             // Implemented in parent class BaseCachedFile
  100.             TheliaEvents::DOCUMENT_CLEAR_CACHE => ['clearCache'128],
  101.             TheliaEvents::DOCUMENT_DELETE => ['deleteFile'128],
  102.             TheliaEvents::DOCUMENT_SAVE => ['saveFile'128],
  103.             TheliaEvents::DOCUMENT_UPDATE => ['updateFile'128],
  104.             TheliaEvents::DOCUMENT_UPDATE_POSITION => ['updatePosition'128],
  105.             TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY => ['toggleVisibility'128],
  106.         ];
  107.     }
  108. }