src/Rhyme/WMassArtsHub/Widget/DMUploaderBase.php line 119

Open in your IDE?
  1. <?php
  2. /**
  3.  * Copyright (C) 2019 Rhyme Digital - Borrowed from http://github.com/terminal42/contao-fineuploader
  4.  *
  5.  * @copyright  Copyright (c) 2008-2017, terminal42 gmbh
  6.  * @author       Blair Winans <blair@rhyme.digital>
  7.  * @author       Adam Fisher <adam@rhyme.digital>
  8.  * @author     terminal42 gmbh <info@terminal42.ch>
  9.  * @license    http://opensource.org/licenses/lgpl-3.0.html LGPL
  10.  * @link       http://github.com/terminal42/contao-fineuploader
  11.  */
  12. namespace Rhyme\WMassArtsHub\Widget;
  13. use Contao\Widget;
  14. use Contao\Message;
  15. use Contao\Environment;
  16. use Contao\FrontendUser;
  17. /**
  18.  * Class DMUploaderBase
  19.  *
  20.  * Parent class for "DMUploaderWidgets" widgets.
  21.  */
  22. abstract class DMUploaderBase extends Widget
  23. {
  24.     /**
  25.      * Temporary upload path
  26.      * @var string
  27.      */
  28.     protected $strTemporaryPath 'system/tmp';
  29.     /**
  30.      * Initialize the object
  31.      * @param array
  32.      */
  33.     public function __construct($arrAttributes=null)
  34.     {
  35.         $arrAttributes['decodeEntities'] = true;
  36.         parent::__construct($arrAttributes);
  37.     }
  38.     /**
  39.      * Add the labels and messages.
  40.      *
  41.      * @param null $arrAttributes
  42.      */
  43.     public function parse($arrAttributes null)
  44.     {
  45.         // Messages (passed on to fineuploader JS)
  46.         $basicTextOptions = array(
  47.             'text'  => array(
  48.                 'formatProgress',
  49.                 'failUpload',
  50.                 'waitingForResponse',
  51.                 'paused',
  52.             ),
  53.             'messages'  => array(
  54.                 'typeError',
  55.                 'sizeError',
  56.                 'minSizeError',
  57.                 'emptyError',
  58.                 'noFilesError',
  59.                 'tooManyItemsError',
  60.                 'maxHeightImageError',
  61.                 'maxWidthImageError',
  62.                 'minHeightImageError',
  63.                 'minWidthImageError',
  64.                 'retryFailTooManyItems',
  65.                 'onLeave',
  66.                 'unsupportedBrowserIos8Safari',
  67.             ),
  68.             'retry' => array(
  69.                 'autoRetryNote',
  70.             ),
  71.             'deleteFile' => array(
  72.                 'confirmMessage',
  73.                 'deletingStatusText',
  74.                 'deletingFailedText',
  75.             ),
  76.             'paste' => array(
  77.                 'namePromptMessage',
  78.             )
  79.         );
  80.         $config = array();
  81.         foreach ($basicTextOptions as $category => $messages) {
  82.             foreach ($messages as $message) {
  83.                 // Only translate if available, otherwise fall back to default (EN)
  84.                 if (isset($GLOBALS['TL_LANG']['MSC']['dmuploder_trans'][$category][$message])) {
  85.                     $config[$category][$message] = $GLOBALS['TL_LANG']['MSC']['dmuploder_trans'][$category][$message];
  86.                 }
  87.             }
  88.         }
  89.         // Merge with custom options
  90.         $this->config json_encode(array_merge($config, (array) $this->arrConfiguration['uploaderConfig']));
  91.         // Labels (in HTML)
  92.         $labels = array(
  93.             'drop',
  94.             'upload',
  95.             'processing',
  96.             'cancel',
  97.             'retry',
  98.             'delete',
  99.             'close',
  100.             'yes',
  101.             'no',
  102.         );
  103.         $preparedLabels = array();
  104.         foreach ($labels as $label) {
  105.             $preparedLabels[$label] = $GLOBALS['TL_LANG']['MSC']['dmuploder_' $label];
  106.         }
  107.         // Set the upload button label
  108.         if ($this->uploadButtonLabel) {
  109.             $preparedLabels['upload'] = $this->uploadButtonLabel;
  110.         }
  111.         $this->labels $preparedLabels;
  112.         return parent::parse($arrAttributes);
  113.     }
  114.     /**
  115.      * Add the required attribute if mandatory
  116.      *
  117.      * @param string
  118.      * @param mixed
  119.      */
  120.     public function __set($strKey$varValue)
  121.     {
  122.         switch ($strKey) {
  123.             case 'mandatory':
  124.                 if ($varValue) {
  125.                     $this->arrAttributes['required'] = 'required';
  126.                 } else {
  127.                     unset($this->arrAttributes['required']);
  128.                 }
  129.             // DO NOT BREAK HERE
  130.         }
  131.         parent::__set($strKey$varValue);
  132.     }
  133.     /**
  134.      * Validate the upload
  135.      * @return string
  136.      */
  137.     public function validateUpload()
  138.     {
  139.         Message::reset();
  140.         $strTempName $this->strName '_dmuploader';
  141.         $objUploader = new \Haste\Util\FileUpload($this->strName);
  142.         // Convert the $_FILES array to Contao format
  143.         if (!empty($_FILES[$strTempName])) {
  144.             $arrFile = array
  145.             (
  146.                 'name' => array($_FILES[$strTempName]['name']),
  147.                 'type' => array($_FILES[$strTempName]['type']),
  148.                 'tmp_name' => array($_FILES[$strTempName]['tmp_name']),
  149.                 'error' => array($_FILES[$strTempName]['error']),
  150.                 'size' => array($_FILES[$strTempName]['size']),
  151.             );
  152.             // Replace the comma character (#22)
  153.             $arrFile['name'] = str_replace(',''_'$arrFile['name']);
  154.             // Check if the file exists
  155.             if (file_exists(TL_ROOT '/' $this->strTemporaryPath '/' $arrFile['name'][0])) {
  156.                 $arrFile['name'][0] = $this->getFileName($arrFile['name'][0], $this->strTemporaryPath);
  157.             }
  158.             $_FILES[$this->strName] = $arrFile;
  159.             unset($_FILES[$strTempName]); // Unset the temporary file
  160.         }
  161.         $varInput '';
  162.         // Validate the minlength
  163.         if ($this->arrConfiguration['minlength'] > 0) {
  164.             $objUploader->setMinFileSize($this->arrConfiguration['minlength']);
  165.         }
  166.         // Validate the maxlength
  167.         if ($this->arrConfiguration['maxlength'] > 0) {
  168.             $objUploader->setMaxFileSize($this->arrConfiguration['maxlength']);
  169.         }
  170.         // Set the maximum width
  171.         if ($this->arrConfiguration['maxWidth']) {
  172.             $objUploader->setImageWidth($this->arrConfiguration['maxWidth']);
  173.         }
  174.         // Set the maximum height
  175.         if ($this->arrConfiguration['maxHeight']) {
  176.             $objUploader->setImageHeight($this->arrConfiguration['maxHeight']);
  177.         }
  178.         try {
  179.             $varInput $objUploader->uploadTo($this->strTemporaryPath);
  180.             if ($objUploader->hasError()) {
  181.                 if (version_compare(VERSION'4.2''>=')) {
  182.                     $session = \System::getContainer()->get('session');
  183.                     foreach ($session->getFlashBag()->peek('contao.'.TL_MODE.'.error') as $strError) {
  184.                         $this->addError($strError);
  185.                     }
  186.                 } else {
  187.                     foreach ((array) $_SESSION['TL_ERROR'] as $strError) {
  188.                         $this->addError($strError);
  189.                     }
  190.                 }
  191.             }
  192.             Message::reset();
  193.         } catch (\Exception $e) {
  194.             $this->addError($e->getMessage());
  195.         }
  196.         if (!is_array($varInput) || empty($varInput)) {
  197.             $this->addError($GLOBALS['TL_LANG']['MSC']['dmuploader_error']);
  198.         }
  199.         $varInput $varInput[0];
  200.         // Validate and move the file immediately
  201.         if ($this->arrConfiguration['directUpload']) {
  202.             $varInput $this->validatorSingle($varInput$this->getDestinationFolder());
  203.         }
  204.         return $varInput;
  205.     }
  206.     /**
  207.      * Return an array if the "multiple" attribute is set
  208.      * @param mixed
  209.      * @return mixed
  210.      */
  211.     protected function validator($varInput)
  212.     {
  213.         $varReturn $this->blnIsMultiple ? array() : '';
  214.         $strDestination $this->getDestinationFolder();
  215.         // Check if mandatory
  216.         if ($varInput == '' && $this->mandatory) {
  217.             $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['mandatory'], $this->strLabel));
  218.         }
  219.         // Single file
  220.         elseif (strpos($varInput',') === false) {
  221.             $varInput $this->validatorSingle($varInput$strDestination);
  222.             $varReturn $this->blnIsMultiple ? array($varInput) : $varInput;
  223.         }
  224.         // Multiple files
  225.         else {
  226.             $arrValues array_filter(explode(','$varInput));
  227.             // Limit the number of uploads
  228.             if ($this->arrConfiguration['uploaderLimit'] > 0) {
  229.                 $arrValues array_slice($arrValues0$this->arrConfiguration['uploaderLimit']);
  230.             }
  231.             foreach ($arrValues as $k => $v) {
  232.                 $arrValues[$k] = $this->validatorSingle($v$strDestination);
  233.             }
  234.             $varReturn $this->blnIsMultiple $arrValues $arrValues[0];
  235.         }
  236.         return $varReturn;
  237.     }
  238.     /**
  239.      * Get the destination folder
  240.      *
  241.      * @return mixed
  242.      */
  243.     protected function getDestinationFolder()
  244.     {
  245.         $destination = \Config::get('uploadPath');
  246.         $folder null;
  247.         // Specify the target folder in the DCA (eval)
  248.         if (isset($this->arrConfiguration['uploadFolder'])) {
  249.             $folder $this->arrConfiguration['uploadFolder'];
  250.         }
  251.         // Use the user's home directory
  252.         if ($this->arrConfiguration['useHomeDir'] && FE_USER_LOGGED_IN) {
  253.             $user FrontendUser::getInstance();
  254.             if ($user->assignDir && $user->homeDir) {
  255.                 $folder $user->homeDir;
  256.             }
  257.         }
  258.         if ($folder !== null && \Validator::isUuid($folder)) {
  259.             $folderModel = \FilesModel::findByUuid($folder);
  260.             if ($folderModel !== null) {
  261.                 $destination $folderModel->path;
  262.             }
  263.         } else {
  264.             $destination $folder;
  265.         }
  266.         return $destination;
  267.     }
  268.     /**
  269.      * Validate a single file.
  270.      *
  271.      * @param mixed
  272.      * @param string
  273.      * @return mixed
  274.      */
  275.     protected function validatorSingle($varFile$strDestination)
  276.     {
  277.         // Move the temporary file
  278.         if (!\Validator::isStringUuid($varFile) && is_file(TL_ROOT '/' $varFile)) {
  279.             $varFile $this->moveTemporaryFile($varFile$strDestination);
  280.         }
  281.         // Convert uuid to binary format
  282.         if (\Validator::isStringUuid($varFile)) {
  283.             $varFile = \StringUtil::uuidToBin($varFile);
  284.         }
  285.         return $varFile;
  286.     }
  287.     /**
  288.      * Move the temporary file to its destination
  289.      * @param string
  290.      * @param string
  291.      * @return string
  292.      */
  293.     protected function moveTemporaryFile($strFile$strDestination)
  294.     {
  295.         if (!is_file(TL_ROOT '/' $strFile)) {
  296.             return '';
  297.         }
  298.         // Do not store the file
  299.         if (!$this->arrConfiguration['storeFile']) {
  300.             return $strFile;
  301.         }
  302.         // The file is not temporary
  303.         if (stripos($strFile$this->strTemporaryPath) === false) {
  304.             return $strFile;
  305.         }
  306.         $strNew $strDestination '/' basename($strFile);
  307.         // Do not overwrite existing files
  308.         if ($this->arrConfiguration['doNotOverwrite']) {
  309.             $strNew $strDestination '/' $this->getFileName(basename($strFile), $strDestination);
  310.         }
  311.         $blnRename = \Files::getInstance()->rename($strFile$strNew);
  312.         \Files::getInstance()->chmod($strNew, \Config::get('defaultFileChmod'));
  313.         // Add the file to Dbafs
  314.         if ($this->arrConfiguration['addToDbafs'] && $blnRename) {
  315.             $objModel = \Dbafs::addResource($strNew);
  316.             if ($objModel !== null) {
  317.                 $strNew $objModel->uuid;
  318.             }
  319.         }
  320.         return $strNew;
  321.     }
  322.     /**
  323.      * Get the new file name if it already exists in the folder
  324.      * @param string
  325.      * @param string
  326.      * @return string
  327.      */
  328.     protected function getFileName($strFile$strFolder)
  329.     {
  330.         if (!file_exists(TL_ROOT '/' $strFolder '/' $strFile)) {
  331.             return $strFile;
  332.         }
  333.         $offset 1;
  334.         $pathinfo pathinfo($strFile);
  335.         $name $pathinfo['filename'];
  336.         $arrAll scan(TL_ROOT '/' $strFolder);
  337.         $arrFiles preg_grep('/^' preg_quote($name'/') . '.*\.' preg_quote($pathinfo['extension'], '/') . '/'$arrAll);
  338.         foreach ($arrFiles as $file) {
  339.             if (preg_match('/__[0-9]+\.' preg_quote($pathinfo['extension'], '/') . '$/'$file)) {
  340.                 $file str_replace('.' $pathinfo['extension'], ''$file);
  341.                 $intValue intval(substr($file, (strrpos($file'_') + 1)));
  342.                 $offset max($offset$intValue);
  343.             }
  344.         }
  345.         return str_replace($name$name '__' . ++$offset$strFile);
  346.     }
  347.     /**
  348.      * Generate a file item and return it as HTML string
  349.      * @param string
  350.      * @return string
  351.      */
  352.     protected function generateFileItem($strPath)
  353.     {
  354.         if (!is_file(TL_ROOT '/' $strPath)) {
  355.             return '';
  356.         }
  357.         $imageSize $this->getImageSize();
  358.         $objFile = new \File($strPathtrue);
  359.         $strInfo $strPath ' <span class="tl_gray">(' . \System::getReadableSize($objFile->size) . ($objFile->isGdImage ', ' $objFile->width 'x' $objFile->height ' px' '') . ')</span>';
  360.         $allowedDownload trimsplit(','strtolower($GLOBALS['TL_CONFIG']['allowedDownload']));
  361.         $strReturn '';
  362.         // Show files and folders
  363.         if (!$this->blnIsGallery && !$this->blnIsDownloads) {
  364.             if ($objFile->isGdImage) {
  365.                 $strReturn = \Image::getHtml(\Image::get($strPath$imageSize[0], $imageSize[1], $imageSize[2]), '''class="gimage" title="' specialchars($strInfo) . '"');
  366.             } else {
  367.                 $strReturn = \Image::getHtml($objFile->icon) . ' ' $strInfo;
  368.             }
  369.         }
  370.         // Show a sortable list of files only
  371.         else {
  372.             if ($this->blnIsGallery) {
  373.                 // Only show images
  374.                 if ($objFile->isGdImage) {
  375.                     $strReturn = \Image::getHtml(\Image::get($strPath$imageSize[0], $imageSize[1], $imageSize[2]), '''class="gimage" title="' specialchars($strInfo) . '"');
  376.                 }
  377.             } else {
  378.                 // Only show allowed download types
  379.                 if (in_array($objFile->extension$allowedDownload) && !preg_match('/^meta(_[a-z]{2})?\.txt$/'$objFile->basename)) {
  380.                     $strReturn = \Image::getHtml($objFile->icon) . ' ' $strPath;
  381.                 }
  382.             }
  383.         }
  384.         return $strReturn;
  385.     }
  386.     /**
  387.      * Get the image size
  388.      *
  389.      * @return array
  390.      */
  391.     protected function getImageSize()
  392.     {
  393.         if (is_array($this->imageSize)) {
  394.             return $this->imageSize;
  395.         }
  396.         return [8060'center_center'];
  397.     }
  398. }