diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bfe817 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor/* +composer.lock diff --git a/README.md b/README.md index a7d361f..c3e7588 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # jQuery-FileUpload -[![Latest stable](https://img.shields.io/packagist/v/jzechy/jquery-fileupload.svg?style=flat-square)](https://packagist.org/packages/jzechy/jquery-fileupload) -[![license](https://img.shields.io/github/license/jzechy/jquery-fileupload.svg?maxAge=2592000&style=flat-square)](https://github.com/JZechy/jQuery-FileUpload/blob/master/LICENSE) -[![Downloads Total](https://img.shields.io/packagist/dt/jzechy/jquery-fileupload.svg?style=flat-square)](https://packagist.org/packages/jzechy/jquery-fileupload) -[![Open Issues](https://img.shields.io/github/issues/jzechy/jquery-fileupload.svg?style=flat-square)](https://github.com/JZechy/jquery-fileupload/issues) +[![Latest stable](https://img.shields.io/packagist/v/ijvo/jquery-fileupload.svg?style=flat-square)](https://packagist.org/packages/ijvo/jquery-fileupload) +[![license](https://img.shields.io/github/license/ijvo/jquery-fileupload.svg?maxAge=2592000&style=flat-square)](https://github.com/JZechy/jQuery-FileUpload/blob/master/LICENSE) +[![Downloads Total](https://img.shields.io/packagist/dt/ijvo/jquery-fileupload.svg?style=flat-square)](https://packagist.org/packages/ijvo/jquery-fileupload) +[![Open Issues](https://img.shields.io/github/issues/ijvo/jquery-fileupload.svg?style=flat-square)](https://github.com/JZechy/jquery-fileupload/issues) jQuery-FileUpload je komponenta, fungující jako rozšíření UploadControl v Nette formuláři, která pro nahrávání souborů využívá [blueimp/jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload). @@ -11,7 +11,7 @@ Komponenta nabízí možnost [vlastního uživatelského rozhraní](https://gith ## Composer ``` -composer require jzechy/jquery-fileupload +composer require ijvo/jquery-fileupload ``` ## Odkazy diff --git a/composer.json b/composer.json index f70591d..b53ee0a 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,29 @@ -{ - "name": "jzechy/jquery-fileupload", - "description": "Nette UploadControl rozšířené o blueimp jQuery FileUpload.", - "homepage": "https://github.com/JZechy/jQuery-FileUpload", - "license": "MIT", - "authors": [ - { - "name": "Jan 'Zechy' Zechovský", - "email": "email@zechy.cz", - "homepage": "http://zechy.cz" - } - ], - "require": { - "php": ">=5.6.0", - "nette/forms": "^v2.4.0", - "nette/http": "^v2.4.0", - "nette/utils": "^v2.4.0", - "nette/di": "^v2.4.0", - "nette/application": "^v2.4.0", - "latte/latte": "^v2.4.0" - }, - "autoload": { - "classmap": ["src/"] - } -} +{ + "name": "ijvo/jquery-fileupload", + "description": "Nette UploadControl rozšířené o blueimp jQuery FileUpload.", + "homepage": "https://github.com/JZechy/jQuery-FileUpload", + "license": "MIT", + "authors": [ + { + "name": "Jan 'Zechy' Zechovský", + "email": "email@zechy.cz", + "homepage": "http://zechy.cz" + }, + { + "name": "Ing. Jaroslav Vaculik -IJVo", + "homepage": "https://ijvo.cz" + } + ], + "require": { + "php": ">=8.0 <8.2", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/utils": "^3.0", + "nette/di": "^3.0", + "nette/application": "^3.0", + "latte/latte": "^3.0" + }, + "autoload": { + "classmap": ["src/"] + } +} diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..9a4606f --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +includes: + - c:\Wamp\NetteTools\phpstan\vendor\phpstan\phpstan-nette\extension.neon + - c:\Wamp\NetteTools\phpstan\vendor\phpstan\phpstan-nette\rules.neon + +parameters: \ No newline at end of file diff --git a/src/Exceptions.php b/src/Exceptions.php index f72c4ed..da1bc2c 100644 --- a/src/Exceptions.php +++ b/src/Exceptions.php @@ -1,12 +1,18 @@ - - * @package Zet\FileUpload - */ -class InvalidFileException extends \Exception {} - -class InvalidValueException extends \Exception {} \ No newline at end of file + + * @package Zet\FileUpload + */ +class InvalidFileException extends \Exception +{ // @CSIgnoreLine +} + +class InvalidValueException extends \Exception +{ // @CSIgnoreLine +} diff --git a/src/FileUploadControl.php b/src/FileUploadControl.php index fadfbde..cd42da4 100644 --- a/src/FileUploadControl.php +++ b/src/FileUploadControl.php @@ -1,617 +1,679 @@ - - * @package Zet\FileUpload - */ -class FileUploadControl extends \Nette\Forms\Controls\UploadControl { - - # -------------------------------------------------------------------- - # Registration - # -------------------------------------------------------------------- - /** - * @static - * @param $systemContainer - * @param array $configuration - */ - public static function register(\Nette\DI\Container $systemContainer, $configuration = []) { - $class = __CLASS__; - \Nette\Forms\Container::extensionMethod("addFileUpload", function( - \Nette\Forms\Container $container, $name, $maxFiles = null, $maxFileSize = null - ) use ($class, $systemContainer, $configuration) { - $maxFiles = is_null($maxFiles) ? $configuration["maxFiles"] : $maxFiles; - $maxFileSize = is_null($maxFileSize) ? $configuration["maxFileSize"] : $maxFileSize; - - /** @var FileUploadControl $component */ - $component = new $class($name, $maxFiles, $maxFileSize); - $component->setContainer($systemContainer); - $component->setUploadModel($configuration["uploadModel"]); - $component->setFileFilter($configuration["fileFilter"]); - $component->setRenderer($configuration["renderer"]); - - if($configuration["translator"] === null) { - $translator = $systemContainer->getByType(ITranslator::class, FALSE); - $component->setTranslator($translator); - } else { - $component->setTranslator($configuration["translator"]); - } - - $component->setAutoTranslate($configuration["autoTranslate"]); - $component->setMessages($configuration["messages"]); - $component->setUploadSettings($configuration["uploadSettings"]); - - $container->addComponent($component, $name); - - return $component; - }); - } - - /** - * Vloží CSS do stránky. - * - * @static - * @param string $basePath - */ - public static function getHead($basePath) { - echo ''; - } - - /** - * Vloží skripty do stránky. - * - * @static - * @param string $basePath - */ - public static function getScripts($basePath) { - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - - # -------------------------------------------------------------------- - # Control definition - # -------------------------------------------------------------------- - /** - * Povolí nahrávat pouze obrázky png, jpeg, jpg, gif. - * - * @var string - */ - const FILTER_IMAGES = 'Zet\FileUpload\Filter\ImageFilter'; - - /** - * Povolí nahrávat pouze dokumenty typu txt, doc, docx, xls, xlsx, ppt, pptx, pdf. - * - * @var string - */ - const FILTER_DOCUMENTS = 'Zet\FileUpload\Filter\DocumentFilter'; - - /** - * Povolí nahrávat soubory zip, tar, rar, 7z. - * - * @var string - */ - const FILTER_ARCHIVE = 'Zet\FileUpload\Filter\ArchiveFilter'; - - /** - * Povolí nahrávat pouze soubory mp3, ogg, aiff. - * - * @var string - */ - const FILTER_AUDIO = 'Zet\FileUpload\Filter\AudioFilter'; - - /** - * @var \Nette\DI\Container - */ - private $container; - - /** - * @var \Nette\Caching\Cache - */ - private $cache; - - /** - * @var int - */ - private $maxFiles; - - /** - * @var int - */ - private $maxFileSize; - - /** - * @var string - */ - private $fileSizeString; - - /** - * @var \Zet\FileUpload\Model\UploadController - */ - private $controller; - - /** - * @var string - */ - private $uploadModel; - - /** - * Třída pro filtrování nahrávaných souborů. - * - * @var string - */ - private $fileFilter; - - /** - * Pole vlastních definovaných parametrů. - * - * @var array - */ - private $params = []; - - /** - * @var string - */ - private $renderer; - - /** - * @var string - */ - private $token; - - /** - * @var DefaultFile[] - */ - private $defaultFiles = []; - - /** - * Seznam chybových hlášek. - * Chyby uploaderu: - * - maxFiles - * - maxSize - * - fileTypes - * - * Chyby v PHP: - * - fileSize - * - partialUpload - * - noFile - * - tmpFolder - * - cannotWrite - * - stopped - * - * @var string[] - */ - private $messages = []; - - /** - * Automaticky překládat všechny chybové zprávy? - * - * @var bool - */ - private $autoTranslate = false; - - /** - * Pole vlastních hodnot pro konfiguraci uploaderu. - * - * @var array - */ - private $uploadSettings = []; - - /** - * FileUploadControl constructor. - * - * @param string $name Název inputu. - * @param int $maxFiles Maximální počet souborů. - * @param string $maxFileSize Maximální velikosti souboru. - */ - public function __construct($name, $maxFiles, $maxFileSize = null) { - parent::__construct($name); - $this->maxFiles = $maxFiles; - if(is_null($maxFileSize)) { - $this->fileSizeString = ini_get("upload_max_filesize") . "B"; - $this->maxFileSize = $this->parseIniSize(ini_get("upload_max_filesize")); - } else { - $this->fileSizeString = $maxFileSize . "B"; - $this->maxFileSize = $this->parseIniSize($maxFileSize); - } - $this->controller = new Model\UploadController($this); - $this->token = uniqid(); - } - - /** - * Ověření nastavených direktiv, zda nepřekročují nastavení serveru. - * - * @throws \Zet\FileUpload\InvalidValueException - */ - private function checkSettings() { - $postMaxSize = $this->parseIniSize($postMaxSizeString = ini_get("post_max_size")); - $iniMaxFileSize = $this->parseIniSize($iniMaxFileSizeString = ini_get("upload_max_filesize")); - - if($this->maxFileSize > $postMaxSize) { - throw new InvalidValueException( - sprintf( - "Nastavení pro maximální velikost souboru je větší, než dovoluje direktiva `post_max_size` (%s).", - $postMaxSizeString - ) - ); - } else if($this->maxFileSize > $iniMaxFileSize) { - throw new InvalidValueException( - sprintf( - "Nastavení pro maximální velikost souboru je větší, než dovoluje direktiva `upload_max_filesize` (%s).", - $iniMaxFileSizeString - ) - ); - } - } - - /** - * @param Form $form - */ - protected function attached($form) { - parent::attached($form); - $this->form->addComponent($this->controller, "uploadController" . ucfirst($this->name)); - } - - # -------------------------------------------------------------------- - # Setters \ Getters - # -------------------------------------------------------------------- - /** - * @param \Nette\DI\Container $container - * @internal - */ - public function setContainer($container) { - $this->container = $container; - /** @noinspection PhpParamsInspection */ - $this->cache = new \Nette\Caching\Cache($this->container->getByType('Nette\Caching\IStorage')); - /** @noinspection PhpParamsInspection */ - $this->controller->setRequest($container->getByType('\Nette\Http\Request')); - } - - /** - * @return \Nette\DI\Container - * @internal - */ - public function getContainer() { - return $this->container; - } - - /** - * @return int - * @internal - */ - public function getMaxFiles() { - return $this->maxFiles; - } - - /** - * @param int $maxFiles - * @return $this - */ - public function setMaxFiles($maxFiles) { - $this->maxFiles = $maxFiles; - - return $this; - } - - /** - * @return Model\IUploadModel - * @internal - */ - public function getUploadModel() { - if(is_null($this->uploadModel)) { - return new Model\BaseUploadModel(); - } else { - $model = $this->container->getByType($this->uploadModel); - if($model instanceof Model\IUploadModel) { - return $model; - } else { - throw new \Nette\InvalidStateException( - "Předaný model není instancí \\Zet\\FileUpload\\Model\\IUploadModel." - ); - } - } - } - - /** - * @param string $uploadModel - * @return $this - */ - public function setUploadModel($uploadModel) { - $this->uploadModel = $uploadModel; - - return $this; - } - - /** - * @return int - * @internal - */ - public function getMaxFileSize() { - return $this->maxFileSize; - } - - /** - * @param int $maxFileSize - * @return $this - */ - public function setMaxFileSize($maxFileSize) { - $this->maxFileSize = $this->parseIniSize($maxFileSize); - - return $this; - } - - /** - * @return \Nette\Caching\Cache - */ - public function getCache() { - return $this->cache; - } - - /** - * @return string - * @internal - */ - public function getFileSizeString() { - return $this->fileSizeString; - } - - /** - * @return string - * @internal - */ - public function getFileFilter() { - return $this->fileFilter; - } - - /** - * Nastaví třídu pro filtrování nahrávaných souborů. - * - * @param string $fileFilter - * @return $this - */ - public function setFileFilter($fileFilter) { - $this->fileFilter = $fileFilter; - - return $this; - } - - /** - * Vrátí název pro frontu s tokenem. - * - * @param string $token - * @return string - * @internal - */ - public function getTokenizedCacheName($token) { - return $this->getHtmlId() . "-" . $token; - } - - /** - * Vrátí identifikační token. - * - * @return string - * @internal - */ - public function getToken() { - return $this->token; - } - - /** - * Nastavení vlastních parametrů k uploadovanému souboru. - * - * @param array $params - * @return FileUploadControl - */ - public function setParams(array $params) { - $this->params = $params; - - return $this; - } - - /** - * @return array - */ - public function getParams() { - return $this->params; - } - - /** - * @param string $renderer - * @return FileUploadControl - */ - public function setRenderer($renderer) { - $this->renderer = $renderer; - - return $this; - } - - /** - * @return string - */ - public function getRenderer() { - return $this->renderer; - } - - /** - * @return DefaultFile[] - */ - public function getDefaultFiles() { - return $this->defaultFiles; - } - - /** - * @param DefaultFile[] $defaultFiles - * @return FileUploadControl - */ - public function setDefaultFiles($defaultFiles) { - $this->defaultFiles = $defaultFiles; - - return $this; - } - - /** - * @param DefaultFile $defaultFile - * @return FileUploadControl - */ - public function addDefaultFile($defaultFile) { - $this->defaultFiles[] = $defaultFile; - - return $this; - } - - /** - * @param string[] $messages - * @return FileUploadControl - */ - public function setMessages(array $messages) { - $this->messages = $messages; - - return $this; - } - - /** - * @param string $index - * @param string $message - * @return FileUploadControl - */ - public function setMessage($index, $message) { - $this->messages[ $index ] = $message; - - return $this; - } - - /** - * @return string[] - */ - public function getMessages() { - return $this->messages; - } - - /** - * @return bool - */ - public function isAutoTranslate() { - return $this->autoTranslate; - } - - /** - * @param bool $autoTranslate - * @return FileUploadControl - */ - public function setAutoTranslate($autoTranslate) { - $this->autoTranslate = $autoTranslate; - - return $this; - } - - /** - * @return array - */ - public function getUploadSettings() { - return $this->uploadSettings; - } - - /** - * @param array $uploadSettings - * @return FileUploadControl - */ - public function setUploadSettings($uploadSettings) { - $this->uploadSettings = $uploadSettings; - - return $this; - } - - /** - * @param string $name - * @param mixed $value - * @return FileUploadControl - */ - public function addUploadSettings($name, $value) { - $this->uploadSettings[ $name ] = $value; - - return $this; - } - - # -------------------------------------------------------------------- - # Methods - # -------------------------------------------------------------------- - /** - * Získání identifikačního tokenu. - */ - public function loadHttpData() { - parent::loadHttpData(); - - /** @var \Nette\Http\Request $request */ - $request = $this->getContainer()->getByType('\Nette\Http\Request'); - $this->token = $request->getPost($this->getHtmlName() . "-token"); - } - - /** - * @return \Nette\Utils\Html - * @throws InvalidValueException - */ - public function getControl() { - $this->checkSettings(); - - $this->setOption("rendered", true); - - $container = \Nette\Utils\Html::el("div class='zet-fileupload-container'"); - $container->id = $this->getHtmlId() . "-container"; - - $token = \Nette\Utils\Html::el("input type='hidden' value='" . $this->token . "'"); - $token->addAttributes(["name" => $this->getHtmlName() . "-token"]); - - $container->addHtml($token); - $container->addHtml($this->controller->getJavaScriptTemplate()); - $container->addHtml($this->controller->getControlTemplate()); - - return $container; - } - - /** - * Vrátí nacachované hodnoty z controlleru. - * - * @return mixed|NULL - */ - public function getValue() { - $files = $this->cache->load($this->getTokenizedCacheName($this->token)); - - return $files; - } - - /** - * Delete cache - */ - public function __destruct() { - $this->cache->remove($this->getTokenizedCacheName($this->token)); - } - - /** - * Parses ini size - * - * @param string $value - * @return int - */ - private function parseIniSize($value) { - $units = ['k' => 1024, 'm' => 1048576, 'g' => 1073741824]; - $unit = strtolower(substr($value, -1)); - if(is_numeric($unit) || !isset($units[ $unit ])) { - return $value; - } - - return ((int)$value) * $units[ $unit ]; - } - -} + + * @package Zet\FileUpload + */ +class FileUploadControl extends \Nette\Forms\Controls\UploadControl +{ + + use \Nette\SmartObject; + + private const PREFIX = 'jqfu'; + + // -------------------------------------------------------------------- + // Control definition + // -------------------------------------------------------------------- + + /** + * Povolí nahrávat pouze obrázky png, jpeg, jpg, gif, tif. + * + * @var string + */ + private const FILTER_IMAGES = 'Zet\FileUpload\Filter\ImageFilter'; + + /** + * Povolí nahrávat pouze dokumenty typu txt, doc, docx, xls, xlsx, ppt, pptx, pdf. + * + * @var string + */ + private const FILTER_DOCUMENTS = 'Zet\FileUpload\Filter\DocumentFilter'; + + /** + * Povolí nahrávat soubory zip, tar, rar, 7z. + * + * @var string + */ + private const FILTER_ARCHIVE = 'Zet\FileUpload\Filter\ArchiveFilter'; + + /** + * Povolí nahrávat pouze soubory mp3, ogg, aiff, wav. + * + * @var string + */ + private const FILTER_AUDIO = 'Zet\FileUpload\Filter\AudioFilter'; + + /** @var \Nette\DI\Container */ + private $container; + + /** @var \Nette\Caching\Cache */ + private $cache; + + /** @var int */ + private $maxFiles; + + /** @var int */ + private $maxFileSize; + + /** @var string */ + private $fileSizeString; + + /** @var \Zet\FileUpload\Model\UploadController */ + private $controller; + + /** @var string */ + private $uploadModel; + + /** + * Třída pro filtrování nahrávaných souborů. + * + * @var string + */ + private $fileFilter; + + /** + * Pole vlastních definovaných parametrů. + * + * @var array + */ + private $params = []; + + /** @var string */ + private $renderer; + + /** @var string */ + private $token; + + /** @var DefaultFile[] */ + private $defaultFiles = []; + + /** + * Seznam chybových hlášek. + * Chyby uploaderu: + * - maxFiles + * - maxSize + * - fileTypes + * + * Chyby v PHP: + * - fileSize + * - partialUpload + * - noFile + * - tmpFolder + * - cannotWrite + * - stopped + * + * @var string[] + */ + private $messages = []; + + /** + * Automaticky překládat všechny chybové zprávy? + * + * @var bool + */ + private $autoTranslate = false; + + /** + * Pole vlastních hodnot pro konfiguraci uploaderu. + * + * @var array + */ + private $uploadSettings = []; + + + // -------------------------------------------------------------------- + // Registration + // -------------------------------------------------------------------- + + + /** + * @static + * @param $systemContainer + * @param array $configuration + */ + public static function register(\Nette\DI\Container $systemContainer, $configuration = []) + { + $class = __CLASS__; + \Nette\Forms\Container::extensionMethod('addFileUpload', static function ( + \Nette\Forms\Container $container, $name, $maxFiles = null, $maxFileSize = null + ) use ($class, $systemContainer, $configuration) { + $maxFiles = $maxFiles ?? $configuration->maxFiles; + $maxFileSize = $maxFileSize ?? $configuration->maxFileSize; + + /** @var FileUploadControl $component */ + $component = new $class($name, $maxFiles, $maxFileSize); + $component->setContainer($systemContainer); + $component->setUploadModel($configuration->uploadModel); + $component->setFileFilter($configuration->fileFilter); + $component->setRenderer($configuration->renderer); + + if (($configuration->translator ?? null) === null) { + $translator = $systemContainer->getByType(ITranslator::class, false); + $component->setTranslator($translator); + } else { + $component->setTranslator($configuration->translator); + } + + $component->setAutoTranslate($configuration->autoTranslate ?? false); + $component->setMessages((array) ($configuration->messages ?? [])); + $component->setUploadSettings($configuration->uploadSettings ?? []); + + $container->addComponent($component, $name); + + return $component; + }); + } + + + /** + * Vloží CSS do stránky. + * + * @static + * @param string $basePath + */ + public static function getHead(string $basePath): void + { + echo ''; + } + + + /** + * Vloží skripty do stránky. + * + * @static + * @param string $basePath + */ + public static function getScripts(string $basePath) + { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + + /** + * FileUploadControl constructor. + * + * @param string $name Název inputu. + * @param int $maxFiles Maximální počet souborů. + * @param string $maxFileSize Maximální velikosti souboru. + */ + public function __construct(string $name, int $maxFiles, string $maxFileSize = null) + { + parent::__construct($name); + $this->maxFiles = $maxFiles; + if ($maxFileSize === null) { + $this->fileSizeString = ini_get('upload_max_filesize') . 'B'; + $this->maxFileSize = $this->parseIniSize(ini_get('upload_max_filesize')); + } else { + $this->fileSizeString = $maxFileSize . 'B'; + $this->maxFileSize = $this->parseIniSize($maxFileSize); + } + $this->controller = new Model\UploadController($this); + $this->monitor(\Nette\Forms\Form::class, function (\Nette\Forms\Form $form): void { + $form->addComponent($this->controller, 'uploadController' . ucfirst($this->name)); + }); + $this->token = uniqid(self::PREFIX, true); + } + + + /** + * Ověření nastavených direktiv, zda nepřekročují nastavení serveru. + * + * @throws \Zet\FileUpload\InvalidValueException + */ + private function checkSettings(): void + { + $postMaxSize = $this->parseIniSize($postMaxSizeString = ini_get('post_max_size')); + $iniMaxFileSize = $this->parseIniSize($iniMaxFileSizeString = ini_get('upload_max_filesize')); + + if ($this->maxFileSize > $postMaxSize) { + throw new InvalidValueException( + sprintf( + 'Nastavení pro maximální velikost souboru je větší, než dovoluje direktiva `post_max_size` (%s).', + $postMaxSizeString + ) + ); + } + + if ($this->maxFileSize > $iniMaxFileSize) { + throw new InvalidValueException( + sprintf( + 'Nastavení pro maximální velikost souboru je větší, než dovoluje direktiva `upload_max_filesize` (%s).', + $iniMaxFileSizeString + ) + ); + } + } + // -------------------------------------------------------------------- + // Setters \ Getters + // -------------------------------------------------------------------- + + + /** + * @param \Nette\DI\Container $container + * @internal + */ + public function setContainer(\Nette\DI\Container $container): void + { + $this->container = $container; + /** @noinspection PhpParamsInspection */ + $this->cache = new \Nette\Caching\Cache($this->container->getByType(\Nette\Caching\IStorage::class)); + /** @noinspection PhpParamsInspection */ + $this->controller->setRequest($container->getByType(\Nette\Http\Request::class)); + } + + + /** + * @return \Nette\DI\Container + * @internal + */ + public function getContainer(): \Nette\DI\Container + { + return $this->container; + } + + + /** + * @return int + * @internal + */ + public function getMaxFiles(): int + { + return $this->maxFiles; + } + + + /** + * @param int $maxFiles + * @return $this + */ + public function setMaxFiles(int $maxFiles): self + { + $this->maxFiles = $maxFiles; + + return $this; + } + + + /** + * @return Model\IUploadModel + * @internal + */ + public function getUploadModel(): Model\IUploadModel + { + if ($this->uploadModel === null) { + return new Model\BaseUploadModel(); + } else { + $model = $this->container->getByType($this->uploadModel); + if ($model instanceof Model\IUploadModel) { + return $model; + } else { + throw new \Nette\InvalidStateException( + 'Předaný model není instancí \\Zet\\FileUpload\\Model\\IUploadModel.' + ); + } + } + } + + + /** + * @param string $uploadModel + * @return $this + */ + public function setUploadModel(string $uploadModel): self + { + $this->uploadModel = $uploadModel; + + return $this; + } + + + /** + * @return int + * @internal + */ + public function getMaxFileSize(): int + { + return $this->maxFileSize; + } + + + /** + * @param string $maxFileSize + * @return $this + */ + public function setMaxFileSize(string $maxFileSize): self + { + $this->maxFileSize = $this->parseIniSize($maxFileSize); + + return $this; + } + + + /** + * @return \Nette\Caching\Cache + */ + public function getCache(): \Nette\Caching\Cache + { + return $this->cache; + } + + + /** + * @return string + * @internal + */ + public function getFileSizeString(): string + { + return $this->fileSizeString; + } + + + /** + * @return string + * @internal + */ + public function getFileFilter(): string + { + return $this->fileFilter; + } + + + /** + * Nastaví třídu pro filtrování nahrávaných souborů. + * + * @param string $fileFilter + * @return $this + */ + public function setFileFilter(string $fileFilter): self + { + $this->fileFilter = $fileFilter; + + return $this; + } + + + /** + * Vrátí název pro frontu s tokenem. + * + * @param string $token + * @return string + * @internal + */ + public function getTokenizedCacheName(string $token): string + { + return $this->getHtmlId() . '-' . $token; + } + + + /** + * Vrátí identifikační token. + * + * @return string + * @internal + */ + public function getToken(): string + { + return $this->token; + } + + + /** + * Nastavení vlastních parametrů k uploadovanému souboru. + * + * @param array $params + * @return FileUploadControl + */ + public function setParams(array $params): self + { + $this->params = $params; + + return $this; + } + + + /** + * @return array + */ + public function getParams(): array + { + return $this->params; + } + + + /** + * @param string $renderer + * @return FileUploadControl + */ + public function setRenderer(string $renderer): self + { + $this->renderer = $renderer; + + return $this; + } + + + /** + * @return string + */ + public function getRenderer(): string + { + return $this->renderer; + } + + + /** + * @return DefaultFile[] + */ + public function getDefaultFiles(): array + { + return $this->defaultFiles; + } + + + /** + * @param DefaultFile[] $defaultFiles + * @return FileUploadControl + */ + public function setDefaultFiles(array $defaultFiles): self + { + $this->defaultFiles = $defaultFiles; + + return $this; + } + + + /** + * @param DefaultFile $defaultFile + * @return FileUploadControl + */ + public function addDefaultFile(DefaultFile $defaultFile): self + { + $this->defaultFiles[] = $defaultFile; + + return $this; + } + + + /** + * @param string[] $messages + * @return FileUploadControl + */ + public function setMessages(array $messages): self + { + $this->messages = $messages; + + return $this; + } + + + /** + * @param string $index + * @param string $message + * @return FileUploadControl + */ + public function setMessage(string $index, string $message): self + { + $this->messages[$index] = $message; + + return $this; + } + + + /** + * @return string[] + */ + public function getMessages(): array + { + return $this->messages; + } + + + /** + * @return bool + */ + public function isAutoTranslate(): bool + { + return $this->autoTranslate; + } + + + /** + * @param bool $autoTranslate + * @return FileUploadControl + */ + public function setAutoTranslate(bool $autoTranslate): self + { + $this->autoTranslate = $autoTranslate; + + return $this; + } + + + /** + * @return array + */ + public function getUploadSettings(): array + { + return $this->uploadSettings; + } + + + /** + * @param array $uploadSettings + * @return FileUploadControl + */ + public function setUploadSettings(array $uploadSettings): self + { + $this->uploadSettings = $uploadSettings; + + return $this; + } + + + /** + * @param string $name + * @param mixed $value + * @return FileUploadControl + */ + public function addUploadSettings(string $name, mixed $value): self + { + $this->uploadSettings[$name] = $value; + + return $this; + } + // -------------------------------------------------------------------- + // Methods + // -------------------------------------------------------------------- + + + /** + * Získání identifikačního tokenu. + */ + public function loadHttpData(): void + { + parent::loadHttpData(); + + /** @var \Nette\Http\Request $request */ + $request = $this->getContainer()->getByType('\Nette\Http\Request'); + $this->token = $request->getPost($this->getHtmlName() . '-token'); + } + + + /** + * @return \Nette\Utils\Html + * @throws InvalidValueException + */ + public function getControl(): \Nette\Utils\Html + { + $this->checkSettings(); + + $this->setOption('rendered', true); + + $container = \Nette\Utils\Html::el("div class='zet-fileupload-container'"); + $container->id = $this->getHtmlId() . '-container'; + + $token = \Nette\Utils\Html::el("input type='hidden' value='" . $this->token . "'"); + $token->addAttributes(['name' => $this->getHtmlName() . '-token']); + + $container->addHtml($token); + $container->addHtml($this->controller->getJavaScriptTemplate()); + $container->addHtml($this->controller->getControlTemplate()); + + return $container; + } + + + /** + * Vrátí nacachované hodnoty z controlleru. + * + * @return mixed|NULL + */ + public function getValue() + { + $files = $this->cache->load($this->getTokenizedCacheName($this->token)); + + return $files; + } + + + /** + * Delete cache + */ + public function __destruct() + { + $this->cache->remove($this->getTokenizedCacheName($this->token)); + } + + + /** + * Parses ini size + * + * @param string $value + * @return int + */ + private function parseIniSize(string $value): int + { + $units = ['k' => 1024, 'm' => 1048576, 'g' => 1073741824]; + $unit = strtolower(substr($value, -1)); + if (is_numeric($unit) || !isset($units[$unit])) { + return $value; + } + + return ((int) $value) * $units[$unit]; + } +} diff --git a/src/FileUploadExtension.php b/src/FileUploadExtension.php index 9256fda..337814d 100644 --- a/src/FileUploadExtension.php +++ b/src/FileUploadExtension.php @@ -1,63 +1,97 @@ * @package Zet\FileUpload */ -final class FileUploadExtension extends \Nette\DI\CompilerExtension { - - /** - * Výchozí konfigurační hodnoty. - * @var array - */ - private $defaults = [ - "maxFiles" => 25, - "maxFileSize" => NULL, - "uploadModel" => NULL, - "fileFilter" => NULL, - "renderer" => '\Zet\FileUpload\Template\Renderer\Html5Renderer', - "translator" => NULL, - "autoTranslate" => false, - "messages" => [ - "maxFiles" => "Maximální počet souborů je {maxFiles}.", - "maxSize" => "Maximální velikost souboru je {maxSize}.", - "fileTypes" => "Povolené typy souborů jsou {fileTypes}.", - - // PHP Errors - "fileSize" => "Soubor je příliš veliký.", - "partialUpload" => "Soubor byl nahrán pouze částěčně.", - "noFile" => "Nebyl nahrán žádný soubor.", - "tmpFolder" => "Chybí dočasná složka.", - "cannotWrite" => "Nepodařilo se zapsat soubor na disk.", - "stopped" => "Nahrávání souboru bylo přerušeno." - ], - "uploadSettings" => [] - ]; - - /** - * Konfigurace nastavená uživatelem. - * @var array - */ - private $configuration = []; - - /** - * - */ - public function loadConfiguration() { - $this->configuration = $this->getConfig($this->defaults); +final class FileUploadExtension extends \Nette\DI\CompilerExtension +{ + + +// /** +// * Výchozí konfigurační hodnoty. +// * @var array +// */ +// private $defaults = [ +// "maxFiles" => 25, +// "maxFileSize" => NULL, +// "uploadModel" => NULL, +// "fileFilter" => NULL, +// "renderer" => '\Zet\FileUpload\Template\Renderer\Html5Renderer', +// "translator" => NULL, +// "autoTranslate" => false, +// "messages" => [ +// "maxFiles" => "Maximální počet souborů je {maxFiles}.", +// "maxSize" => "Maximální velikost souboru je {maxSize}.", +// "fileTypes" => "Povolené typy souborů jsou {fileTypes}.", +// +// // PHP Errors +// "fileSize" => "Soubor je příliš veliký.", +// "partialUpload" => "Soubor byl nahrán pouze částěčně.", +// "noFile" => "Nebyl nahrán žádný soubor.", +// "tmpFolder" => "Chybí dočasná složka.", +// "cannotWrite" => "Nepodařilo se zapsat soubor na disk.", +// "stopped" => "Nahrávání souboru bylo přerušeno." +// ], +// "uploadSettings" => [] +// ]; + + public function getConfigSchema(): Schema + { + return Expect::structure([ + 'maxFiles' => Expect::int(25), + 'maxFileSize' => Expect::string(), + 'uploadModel' => Expect::string(), + 'fileFilter' => Expect::string(), + 'renderer' => Expect::string('\Zet\FileUpload\Template\Renderer\Html5Renderer'), + 'translator' => Expect::string(), + 'autoTranslate' => Expect::bool(false), + 'messages' => Expect::structure([ + 'maxFiles' => Expect::string('Maximální počet souborů je {maxFiles}.'), + 'maxSize' => Expect::string('Maximální velikost souboru je {maxSize}.'), + 'fileTypes' => Expect::string('Povolené typy souborů jsou {fileTypes}.'), + 'fileSize' => Expect::string('Soubor je příliš veliký.'), + 'partialUpload' => Expect::string('Soubor byl nahrán pouze částěčně.'), + 'noFile' => Expect::string('Nebyl nahrán žádný soubor.'), + 'tmpFolder' => Expect::string('Chybí dočasná složka.'), + 'cannotWrite' => Expect::string('Nepodařilo se zapsat soubor na disk.'), + 'stopped' => Expect::string('Nahrávání souboru bylo přerušeno.'), + ]), + 'uploadSettings' => Expect::array(), + ]); } - +// /** +// * Konfigurace nastavená uživatelem. +// * @var array +// */ +// private $configuration = []; +// /** +// * +// */ +// public function loadConfiguration() { +// $this->configuration = $this->getConfig($this->defaults); +// } + + /** * @param \Nette\PhpGenerator\ClassType $class */ - public function afterCompile(\Nette\PhpGenerator\ClassType $class) { - $init = $class->methods["initialize"]; - + public function afterCompile(\Nette\PhpGenerator\ClassType $class): void + { + $init = $class->getMethods()['initialize']; + $init->addBody('\Zet\FileUpload\FileUploadControl::register($this->getService(?), ?);', [ - $this->getContainerBuilder()->getByType('\Nette\DI\Container'), $this->configuration +// $this->getContainerBuilder()->getByType('\Nette\DI\Container'), $this->configuration, + $this->getContainerBuilder()->getByType(Container::class), $this->getConfig(), ]); } -} \ No newline at end of file +} diff --git a/src/Filter/ArchiveFilter.php b/src/Filter/ArchiveFilter.php index 637c926..3c87cc4 100644 --- a/src/Filter/ArchiveFilter.php +++ b/src/Filter/ArchiveFilter.php @@ -1,27 +1,32 @@ - - * @package Zet\FileUpload\Filter - */ -class ArchiveFilter extends BaseFilter { - - /** - * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. - * - * @example array("text/plain" => "txt") - * @return string[] - */ - protected function getMimeTypes() { - return [ - "application/zip" => "zip", - "application/x-rar-compressed" => "rar", - "application/x-tar" => "tar", - "application/x-7z-compressed" => "7z" - ]; - } -} \ No newline at end of file + + * @package Zet\FileUpload\Filter + */ +class ArchiveFilter extends BaseFilter +{ + + + /** + * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. + * + * @example array("text/plain" => "txt") + * @return string[] + */ + protected function getMimeTypes() + { + return [ + 'application/zip' => 'zip', + 'application/x-rar-compressed' => 'rar', + 'application/x-tar' => 'tar', + 'application/x-7z-compressed' => '7z', + ]; + } +} diff --git a/src/Filter/AudioFilter.php b/src/Filter/AudioFilter.php index 1e607d3..e275af3 100644 --- a/src/Filter/AudioFilter.php +++ b/src/Filter/AudioFilter.php @@ -1,27 +1,34 @@ - - * @package Zet\FileUpload\Filter - */ -class AudioFilter extends BaseFilter { - - /** - * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. - * - * @example array("text/plain" => "txt") - * @return string[] - */ - protected function getMimeTypes() { - return [ - "audio/mpeg3" => "mp3", - "audio/x-mpeg-3" => "mp3", - "audio/ogg" => "ogg", - "audio/x-aiff" => "aiff" - ]; - } -} \ No newline at end of file + + * @package Zet\FileUpload\Filter + */ +class AudioFilter extends BaseFilter +{ + + + /** + * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. + * + * @example array("text/plain" => "txt") + * @return string[] + */ + protected function getMimeTypes() + { + return [ + 'audio/mpeg3' => 'mp3', + 'audio/x-mpeg-3' => 'mp3', + 'audio/ogg' => 'ogg', + 'audio/x-aiff' => 'aiff', + 'audio/x-wav' => 'wav', + 'audio/wav' => 'wav', + ]; + } +} diff --git a/src/Filter/BaseFilter.php b/src/Filter/BaseFilter.php index 5a61ae8..2bde84f 100644 --- a/src/Filter/BaseFilter.php +++ b/src/Filter/BaseFilter.php @@ -1,63 +1,74 @@ - - * @package Zet\FileUpload\Filter - */ -abstract class BaseFilter implements IMimeTypeFilter { - use SmartObject; - - /** - * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. - * - * @example array("text/plain" => "txt") - * @return string[] - */ - abstract protected function getMimeTypes(); - - /** - * Ověří mimetype předaného souboru. - * - * @param \Nette\Http\FileUpload $file Nahraný soubor k ověření. - * @return bool Má soubor správný mimetype? - */ - public function checkType(\Nette\Http\FileUpload $file) { - if(\Nette\Utils\Arrays::searchKey($this->getMimeTypes(), $file->getContentType()) !== false) { - return true; - } else { - // Pokud se nepodaří ověřit mimetype, ověříme alespoň koncovku. - if(array_search($this->getExtension($file->getName()), array_unique($this->getMimeTypes())) !== false) { - return true; - } else { - return false; - } - } - } - - /** - * Vrátí seznam povolených typů souborů. - * - * @return string - */ - public function getAllowedTypes() { - return implode(array_unique($this->getMimeTypes()), ", "); - } - - /** - * Vrátí koncovku souboru. - * - * @param string $filename - * @return string - */ - private function getExtension($filename) { - $exploded = explode(".", $filename); - - return $exploded[ count($exploded) - 1 ]; - } -} + + * @package Zet\FileUpload\Filter + */ +abstract class BaseFilter implements IMimeTypeFilter +{ + + use SmartObject; + + + /** + * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. + * + * @example array("text/plain" => "txt") + * @return string[] + */ + abstract protected function getMimeTypes(); + + + /** + * Ověří mimetype předaného souboru. + * + * @param \Nette\Http\FileUpload $file Nahraný soubor k ověření. + * @return bool Má soubor správný mimetype? + */ + public function checkType(\Nette\Http\FileUpload $file) + { + if (\Nette\Utils\Arrays::searchKey($this->getMimeTypes(), $file->getContentType()) !== null) { + return true; + } else { + // Pokud se nepodaří ověřit mimetype, ověříme alespoň koncovku. + if (array_search($this->getExtension($file->getName()), array_unique($this->getMimeTypes()), true) !== false) { + return true; + } else { + return false; + } + } + } + + + /** + * Vrátí seznam povolených typů souborů. + * + * @return string + */ + public function getAllowedTypes() + { + return implode(', ', array_unique($this->getMimeTypes())); + } + + + /** + * Vrátí koncovku souboru. + * + * @param string $filename + * @return string + */ + private function getExtension($filename) + { + $exploded = explode('.', $filename); + + return $exploded[count($exploded) - 1]; + } +} diff --git a/src/Filter/DocumentFilter.php b/src/Filter/DocumentFilter.php index 6b7d342..dca3e61 100644 --- a/src/Filter/DocumentFilter.php +++ b/src/Filter/DocumentFilter.php @@ -1,31 +1,36 @@ - - * @package Zet\FileUpload\Filter - */ -class DocumentFilter extends BaseFilter { - - /** - * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. - * - * @example array("text/plain" => "txt") - * @return string[] - */ - protected function getMimeTypes() { - return [ - "text/plain" => "txt", - "application/msword" => "doc", - "application/vnd.ms-excel" => "xls", - "application/pdf" => "pdf", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document" => "docx", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => "xlsx", - "application/vnd.ms-powerpoint" => "ppt", - "application/vnd.openxmlformats-officedocument.presentationml.presentation" => "pptx" - ]; - } -} \ No newline at end of file + + * @package Zet\FileUpload\Filter + */ +class DocumentFilter extends BaseFilter +{ + + + /** + * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. + * + * @example array("text/plain" => "txt") + * @return string[] + */ + protected function getMimeTypes() + { + return [ + 'text/plain' => 'txt', + 'application/msword' => 'doc', + 'application/vnd.ms-excel' => 'xls', + 'application/pdf' => 'pdf', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', + 'application/vnd.ms-powerpoint' => 'ppt', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx', + ]; + } +} diff --git a/src/Filter/IMimeTypeFilter.php b/src/Filter/IMimeTypeFilter.php index f365821..29a5a82 100644 --- a/src/Filter/IMimeTypeFilter.php +++ b/src/Filter/IMimeTypeFilter.php @@ -1,28 +1,33 @@ - - * @package Zet\FileUpload\Filter - */ -interface IMimeTypeFilter { - - /** - * Ověří mimetype předaného souboru. - * - * @param \Nette\Http\FileUpload $file Nahraný soubor k ověření. - * @return bool Má soubor správný mimetype? - */ - public function checkType(\Nette\Http\FileUpload $file); - - /** - * Vrátí seznam povolených typů souborů. - * - * @return string - */ - public function getAllowedTypes(); -} \ No newline at end of file + + * @package Zet\FileUpload\Filter + */ +interface IMimeTypeFilter +{ + + + /** + * Ověří mimetype předaného souboru. + * + * @param \Nette\Http\FileUpload $file Nahraný soubor k ověření. + * @return bool Má soubor správný mimetype? + */ + public function checkType(\Nette\Http\FileUpload $file); + + + /** + * Vrátí seznam povolených typů souborů. + * + * @return string + */ + public function getAllowedTypes(); +} diff --git a/src/Filter/ImageFilter.php b/src/Filter/ImageFilter.php index 69cbbd2..515e3df 100644 --- a/src/Filter/ImageFilter.php +++ b/src/Filter/ImageFilter.php @@ -1,28 +1,33 @@ - - * @package Zet\FileUpload\Filter - */ -class ImageFilter extends BaseFilter { - - /** - * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. - * - * @example array("text/plain" => "txt") - * @return string[] - */ - protected function getMimeTypes() { - return [ - "image/png" => "png", - "image/pjpeg" => "jpeg", - "image/jpeg" => "jpg", - "image/gif" => "gif", - ]; - } - -} \ No newline at end of file + + * @package Zet\FileUpload\Filter + */ +class ImageFilter extends BaseFilter +{ + + + /** + * Vrátí seznam povolených typů souborů s jejich typickou koncovkou. + * + * @example array("text/plain" => "txt") + * @return string[] + */ + protected function getMimeTypes() + { + return [ + 'image/png' => 'png', + 'image/pjpeg' => 'jpeg', + 'image/jpeg' => 'jpg', + 'image/gif' => 'gif', + 'image/tif' => 'tif', + ]; + } +} diff --git a/src/Model/BaseUploadModel.php b/src/Model/BaseUploadModel.php index 5a81c83..61180cc 100644 --- a/src/Model/BaseUploadModel.php +++ b/src/Model/BaseUploadModel.php @@ -1,46 +1,56 @@ - - * @package Zet\FileUpload\Model - */ -class BaseUploadModel implements IUploadModel { - use SmartObject; - - /** - * Uložení nahraného souboru. - * - * @param \Nette\Http\FileUpload $file - * @param array $params Pole vlastních parametrů. - * @return mixed Vlastní navrátová hodnota. - */ - public function save(\Nette\Http\FileUpload $file, array $params = []) { - return $file->getSanitizedName(); - } - - /** - * Zpracování požadavku o smazání souboru. - * - * @param mixed $uploaded Hodnota navrácená funkcí save. - */ - public function remove($uploaded) { - # By Pass... - } - - /** - * Zpracování přejmenování souboru. - * - * @param mixed $upload Hodnota navrácená funkcí save. - * @param string $newName Nové jméno souboru. - * @return mixed Vlastní návratová hodnota. - */ - public function rename($upload, $newName) { - return \Nette\Utils\Strings::webalize($newName); - } -} + + * @package Zet\FileUpload\Model + */ +class BaseUploadModel implements IUploadModel +{ + + use SmartObject; + + + /** + * Uložení nahraného souboru. + * + * @param \Nette\Http\FileUpload $file + * @param array $params Pole vlastních parametrů. + * @return mixed Vlastní navrátová hodnota. + */ + public function save(\Nette\Http\FileUpload $file, array $params = []) + { + return $file->getSanitizedName(); + } + + + /** + * Zpracování požadavku o smazání souboru. + * + * @param mixed $uploaded Hodnota navrácená funkcí save. + */ + public function remove($uploaded) + { + // By Pass... + } + + + /** + * Zpracování přejmenování souboru. + * + * @param mixed $upload Hodnota navrácená funkcí save. + * @param string $newName Nové jméno souboru. + * @return mixed Vlastní návratová hodnota. + */ + public function rename($upload, $newName) + { + return \Nette\Utils\Strings::webalize($newName); + } +} diff --git a/src/Model/DefaultFile.php b/src/Model/DefaultFile.php index 589da8f..57dd52a 100644 --- a/src/Model/DefaultFile.php +++ b/src/Model/DefaultFile.php @@ -1,5 +1,7 @@ * @package Zet\FileUpload\Model */ -class DefaultFile { +class DefaultFile +{ + use SmartObject; - + /** * Callback pro smazání výchozího souboru s parametry (mixed $identifier). * * @var array */ public $onDelete = []; - + /** * Odkaz na náhled obrázku. * * @var string */ private $preview; - + /** * Název souboru. * * @var string */ private $filename; - + /** * Identifikátor souboru sloužící pro jeho smazání. * * @var mixed */ private $identifier; - + + /** * @return array */ - public function toArray() { + public function toArray() + { return [ - "preview" => $this->preview, - "filename" => $this->filename, - "id" => $this->identifier + 'preview' => $this->preview, + 'filename' => $this->filename, + 'id' => $this->identifier, ]; } - + + /** * @return string */ - public function getPreview() { + public function getPreview() + { return $this->preview; } - + + /** * @param string $preview */ - public function setPreview($preview) { + public function setPreview($preview) + { $this->preview = $preview; } - + + /** * @return string */ - public function getFilename() { + public function getFilename() + { return $this->filename; } - + + /** * @param string $filename */ - public function setFilename($filename) { + public function setFilename($filename) + { $this->filename = $filename; } - + + /** * @return mixed */ - public function getIdentifier() { + public function getIdentifier() + { return $this->identifier; } - + + /** * @param mixed $identifier */ - public function setIdentifier($identifier) { + public function setIdentifier($identifier) + { $this->identifier = $identifier; } - - } diff --git a/src/Model/IUploadModel.php b/src/Model/IUploadModel.php index 7a4b8f6..9aa01eb 100644 --- a/src/Model/IUploadModel.php +++ b/src/Model/IUploadModel.php @@ -1,38 +1,43 @@ - - * @package Zet\FileUpload\Model - */ -interface IUploadModel { - - /** - * Uložení nahraného souboru. - * - * @param \Nette\Http\FileUpload $file - * @param array $params Pole vlastních parametrů. - * @return mixed Vlastní navrátová hodnota. - */ - public function save(\Nette\Http\FileUpload $file, array $params = []); - - /** - * Zpracování přejmenování souboru. - * - * @param mixed $upload Hodnota navrácená funkcí save. - * @param string $newName Nové jméno souboru. - * @return mixed Vlastní návratová hodnota. - */ - public function rename($upload, $newName); - - /** - * Zpracování požadavku o smazání souboru. - * - * @param mixed $uploaded Hodnota navrácená funkcí save. - */ - public function remove($uploaded); - -} \ No newline at end of file + + * @package Zet\FileUpload\Model + */ +interface IUploadModel +{ + + + /** + * Uložení nahraného souboru. + * + * @param \Nette\Http\FileUpload $file + * @param array $params Pole vlastních parametrů. + * @return mixed Vlastní navrátová hodnota. + */ + public function save(\Nette\Http\FileUpload $file, array $params = []); + + + /** + * Zpracování přejmenování souboru. + * + * @param mixed $upload Hodnota navrácená funkcí save. + * @param string $newName Nové jméno souboru. + * @return mixed Vlastní návratová hodnota. + */ + public function rename($upload, $newName); + + + /** + * Zpracování požadavku o smazání souboru. + * + * @param mixed $uploaded Hodnota navrácená funkcí save. + */ + public function remove($uploaded); +} diff --git a/src/Model/UploadController.php b/src/Model/UploadController.php index c0f47ac..73d282f 100644 --- a/src/Model/UploadController.php +++ b/src/Model/UploadController.php @@ -1,232 +1,246 @@ - - * @package Zet\FileUpload - */ -class UploadController extends \Nette\Application\UI\Control { - - /** - * @var \Zet\FileUpload\FileUploadControl - */ - private $uploadControl; - - /** - * @var \Nette\Http\Request - */ - private $request; - - /** - * @var \Zet\FileUpload\Filter\IMimeTypeFilter - */ - private $filter; - - /** - * @var BaseRenderer - */ - private $renderer; - - /** - * UploadController constructor. - * - * @param \Zet\FileUpload\FileUploadControl $uploadControl - */ - public function __construct(\Zet\FileUpload\FileUploadControl $uploadControl) { - parent::__construct(); - $this->uploadControl = $uploadControl; - } - - /** - * @param \Nette\Http\Request $request - */ - public function setRequest($request) { - $this->request = $request; - } - - /** - * @return \Zet\FileUpload\Filter\IMimeTypeFilter|NULL - */ - public function getFilter() { - if(is_null($this->filter)) { - /** @noinspection PhpInternalEntityUsedInspection */ - $className = $this->uploadControl->getFileFilter(); - if(!is_null($className)) { - $filterClass = new $className; - if($filterClass instanceof \Zet\FileUpload\Filter\IMimeTypeFilter) { - $this->filter = $filterClass; - } else { - throw new \Nette\UnexpectedValueException( - "Třída pro filtrování souborů neimplementuje rozhraní \\Zet\\FileUpload\\Filter\\IMimeTypeFilter." - ); - } - } - } - - return $this->filter; - } - - /** - * @return \Zet\FileUpload\FileUploadControl - */ - public function getUploadControl() { - return $this->uploadControl; - } - - /** - * @return BaseRenderer - */ - public function getRenderer() { - if(is_null($this->renderer)) { - $rendererClass = $this->uploadControl->getRenderer(); - $this->renderer = new $rendererClass($this->uploadControl, $this->uploadControl->getTranslator()); - - if(!($this->renderer instanceof BaseRenderer)) { - throw new InvalidStateException( - "Renderer musí být instancí třídy `\\Zet\\FileUpload\\Template\\BaseRenderer`." - ); - } - } - - return $this->renderer; - } - - /** - * Vytvoření šablony s JavaScriptem pro FileUpload. - * - * @return string - */ - public function getJavaScriptTemplate() { - $builder = new JavascriptBuilder( - $this->getRenderer(), - $this - ); - - return $builder->getJsTemplate(); - } - - /** - * Vytvoření šablony s přehledem o uploadu. - * - * @return \Nette\Utils\Html - */ - public function getControlTemplate() { - return $this->getRenderer()->buildDefaultTemplate(); - } - - /** - * Zpracování uploadu souboru. - */ - public function handleUpload() { - $files = $this->request->getFiles(); - $token = $this->request->getPost("token"); - $params = json_decode($this->request->getPost("params"), true); - - /** @var \Nette\Http\FileUpload $file */ - $file = $files[ $this->uploadControl->getHtmlName() ]; - /** @noinspection PhpInternalEntityUsedInspection */ - $model = $this->uploadControl->getUploadModel(); - $cache = $this->uploadControl->getCache(); - $filter = $this->getFilter(); - - try { - if(!is_null($filter) && !$filter->checkType($file)) { - throw new \Zet\FileUpload\InvalidFileException($this->getFilter()->getAllowedTypes()); - } - - if($file->isOk()) { - $returnData = $model->save($file, $params); - /** @noinspection PhpInternalEntityUsedInspection */ - $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); - if(empty($cacheFiles)) { - $cacheFiles = [$this->request->getPost("id") => $returnData]; - } else { - $cacheFiles[ $this->request->getPost("id") ] = $returnData; - } - /** @noinspection PhpInternalEntityUsedInspection */ - $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); - } - - } catch(\Zet\FileUpload\InvalidFileException $e) { - $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ - "id" => $this->request->getPost("id"), - "error" => 100, - "errorMessage" => $e->getMessage() - ])); - - } catch(\Exception $e) { - $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ - "id" => $this->request->getPost("id"), - "error" => 99, - "errorMessage" => $e->getMessage() - ])); - } - - $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ - "id" => $this->request->getPost("id"), - "error" => $file->getError() - ])); - } - - /** - * Odstraní nahraný soubor. - */ - public function handleRemove() { - $id = $this->request->getQuery("id"); - $token = $this->request->getQuery("token"); - $default = $this->request->getQuery("default", 0); - - if($default == 0) { - $cache = $this->uploadControl->getCache(); - /** @noinspection PhpInternalEntityUsedInspection */ - $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); - if(isset($cacheFiles[ $id ])) { - /** @noinspection PhpInternalEntityUsedInspection */ - $this->uploadControl->getUploadModel()->remove($cacheFiles[ $id ]); - unset($cacheFiles[ $id ]); - /** @noinspection PhpInternalEntityUsedInspection */ - $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); - } - } else { - $files = $this->uploadControl->getDefaultFiles(); - - foreach($files as $file) { - if($file->getIdentifier() == $id) { - $file->onDelete($id); - } - } - } - } - - /** - * Přejmenuje nahraný soubor. - */ - public function handleRename() { - $id = $this->request->getQuery("id"); - $newName = $this->request->getQuery("newName"); - $token = $this->request->getQuery("token"); - - $cache = $this->uploadControl->getCache(); - /** @noinspection PhpInternalEntityUsedInspection */ - $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); - - if(isset($cacheFiles[ $id ])) { - /** @noinspection PhpInternalEntityUsedInspection */ - $cacheFiles[ $id ] = $this->uploadControl->getUploadModel()->rename($cacheFiles[ $id ], $newName); - /** @noinspection PhpInternalEntityUsedInspection */ - $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); - } - } - - public function validate() { - // Nette ^2.3.10 bypass - } -} + + * @package Zet\FileUpload + */ +class UploadController extends \Nette\Application\UI\Control +{ + + /** @var \Zet\FileUpload\FileUploadControl */ + private $uploadControl; + + /** @var \Nette\Http\Request */ + private $request; + + /** @var \Zet\FileUpload\Filter\IMimeTypeFilter */ + private $filter; + + /** @var BaseRenderer */ + private $renderer; + + + /** + * UploadController constructor. + * + * @param \Zet\FileUpload\FileUploadControl $uploadControl + */ + public function __construct(\Zet\FileUpload\FileUploadControl $uploadControl) + { + $this->uploadControl = $uploadControl; + } + + + /** + * @param \Nette\Http\Request $request + */ + public function setRequest(\Nette\Http\Request $request): void + { + $this->request = $request; + } + + + /** + * @return \Zet\FileUpload\Filter\IMimeTypeFilter|NULL + */ + public function getFilter() + { + if ($this->filter === null) { + /** @noinspection PhpInternalEntityUsedInspection */ + $className = $this->uploadControl->getFileFilter(); + if ($className !== null) { + $filterClass = new $className; + if ($filterClass instanceof \Zet\FileUpload\Filter\IMimeTypeFilter) { + $this->filter = $filterClass; + } else { + throw new \Nette\UnexpectedValueException( + 'Třída pro filtrování souborů neimplementuje rozhraní \\Zet\\FileUpload\\Filter\\IMimeTypeFilter.' + ); + } + } + } + + return $this->filter; + } + + + /** + * @return \Zet\FileUpload\FileUploadControl + */ + public function getUploadControl(): \Zet\FileUpload\FileUploadControl + { + return $this->uploadControl; + } + + + /** + * @return BaseRenderer + */ + public function getRenderer(): BaseRenderer + { + if ($this->renderer === null) { + $rendererClass = $this->uploadControl->getRenderer(); + $this->renderer = new $rendererClass($this->uploadControl, $this->uploadControl->getTranslator()); + + if (!($this->renderer instanceof BaseRenderer)) { + throw new InvalidStateException( + 'Renderer musí být instancí třídy `\\Zet\\FileUpload\\Template\\BaseRenderer`.' + ); + } + } + + return $this->renderer; + } + + + /** + * Vytvoření šablony s JavaScriptem pro FileUpload. + * + * @return string + */ + public function getJavaScriptTemplate(): string + { + $builder = new JavascriptBuilder( + $this->getRenderer(), + $this + ); + + return $builder->getJsTemplate(); + } + + + /** + * Vytvoření šablony s přehledem o uploadu. + * + * @return \Nette\Utils\Html + */ + public function getControlTemplate(): \Nette\Utils\Html + { + return $this->getRenderer()->buildDefaultTemplate(); + } + + + /** + * Zpracování uploadu souboru. + */ + public function handleUpload(): void + { + $files = $this->request->getFiles(); + $token = $this->request->getPost('token'); + $params = json_decode($this->request->getPost('params'), true); + + /** @var \Nette\Http\FileUpload $file */ + $file = $files[$this->uploadControl->getHtmlName()]; + /** @noinspection PhpInternalEntityUsedInspection */ + $model = $this->uploadControl->getUploadModel(); + $cache = $this->uploadControl->getCache(); + $filter = $this->getFilter(); + + try { + if ($filter !== null && !$filter->checkType($file)) { + throw new \Zet\FileUpload\InvalidFileException($this->getFilter()->getAllowedTypes()); + } + + if ($file->isOk()) { + $returnData = $model->save($file, $params); + /** @noinspection PhpInternalEntityUsedInspection */ + $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); + if (empty($cacheFiles)) { + $cacheFiles = [$this->request->getPost('id') => $returnData]; + } else { + $cacheFiles[$this->request->getPost('id')] = $returnData; + } + /** @noinspection PhpInternalEntityUsedInspection */ + $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); + } + } catch (\Zet\FileUpload\InvalidFileException $e) { + $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ + 'id' => $this->request->getPost('id'), + 'error' => 100, + 'errorMessage' => $e->getMessage(), + ])); + } catch (\Exception $e) { + $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ + 'id' => $this->request->getPost('id'), + 'error' => 99, + 'errorMessage' => $e->getMessage(), + ])); + } + + $this->presenter->sendResponse(new \Nette\Application\Responses\JsonResponse([ + 'id' => $this->request->getPost('id'), + 'error' => $file->getError(), + ])); + } + + + /** + * Odstraní nahraný soubor. + */ + public function handleRemove(): void + { + $id = $this->request->getQuery('id'); + $token = $this->request->getQuery('token'); + //$default = $this->request->getQuery('default', 0); + $default = $this->request->getQuery('default'); + + if ($default == null) { + $cache = $this->uploadControl->getCache(); + /** @noinspection PhpInternalEntityUsedInspection */ + $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); + if (isset($cacheFiles[$id])) { + /** @noinspection PhpInternalEntityUsedInspection */ + $this->uploadControl->getUploadModel()->remove($cacheFiles[$id]); + unset($cacheFiles[$id]); + /** @noinspection PhpInternalEntityUsedInspection */ + $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); + } + } else { + $files = $this->uploadControl->getDefaultFiles(); + + foreach ($files as $file) { + if ($file->getIdentifier() == $id) { + $file->onDelete($id); + } + } + } + } + + + /** + * Přejmenuje nahraný soubor. + */ + public function handleRename(): void + { + $id = $this->request->getQuery('id'); + $newName = $this->request->getQuery('newName'); + $token = $this->request->getQuery('token'); + + $cache = $this->uploadControl->getCache(); + /** @noinspection PhpInternalEntityUsedInspection */ + $cacheFiles = $cache->load($this->uploadControl->getTokenizedCacheName($token)); + + if (isset($cacheFiles[$id])) { + /** @noinspection PhpInternalEntityUsedInspection */ + $cacheFiles[$id] = $this->uploadControl->getUploadModel()->rename($cacheFiles[$id], $newName); + /** @noinspection PhpInternalEntityUsedInspection */ + $cache->save($this->uploadControl->getTokenizedCacheName($token), $cacheFiles); + } + } + + + public function validate() + { + // Nette ^2.3.10 bypass + } +} diff --git a/src/Template/JavascriptBuilder.php b/src/Template/JavascriptBuilder.php index 2300d06..7bf61ed 100644 --- a/src/Template/JavascriptBuilder.php +++ b/src/Template/JavascriptBuilder.php @@ -1,5 +1,7 @@ * @package Zet\FileUpload */ -class JavascriptBuilder { +class JavascriptBuilder +{ + use SmartObject; - - /** - * @var \Nette\Application\UI\ITemplate - */ + + /** @var \Nette\Application\UI\ITemplate */ private $template; - - /** - * @var \Nette\Caching\Cache - */ + + /** @var \Nette\Caching\Cache */ private $cache; - - /** - * @var string - */ + + /** @var string */ private $uploadUrl; - - /** - * @var string - */ + + /** @var string */ private $renameLink; - - /** - * @var BaseRenderer - */ + + /** @var BaseRenderer */ private $renderer; - - /** - * @var UploadController - */ + + /** @var UploadController */ private $controller; - + + /** * JavascriptBuilder constructor. * @@ -53,47 +46,54 @@ class JavascriptBuilder { * @param UploadController $controller */ public function __construct( - BaseRenderer $renderer, - UploadController $controller - ) { + BaseRenderer $renderer, + UploadController $controller + ) + { $this->renderer = $renderer; $this->controller = $controller; $this->cache = $controller->getUploadControl()->getCache(); - + $this->template = $controller->template; - $this->template->setFile(__DIR__ . "/js.latte"); + $this->template->setFile(__DIR__ . '/js.latte'); } - + + /** * @return string */ - public function getJsTemplate() { + public function getJsTemplate() + { return $this->buildTemplate(); } - + + /** * @return string */ - private function buildTemplate() { + private function buildTemplate() + { $this->setSettings(); $this->setRendererSettings(); $this->buildTemplates(); - - return (string)$this->template; + + return (string) $this->template; } - + + /** * Základní nastavení. */ - private function setSettings() { - $this->template->uploadUrl = $this->controller->link("upload"); - $this->template->renameLink = $this->controller->link("rename"); - $this->template->removeLink = $this->controller->link("//remove"); - $this->template->inputId = $this->renderer->getElements()["input"]->attrs["id"]; - + private function setSettings() + { + $this->template->uploadUrl = $this->controller->link('upload'); + $this->template->renameLink = $this->controller->link('rename'); + $this->template->removeLink = $this->controller->link('//remove'); + $this->template->inputId = $this->renderer->getElements()['input']->attrs['id']; + $this->needTranslate(); $this->template->messages = $this->controller->getUploadControl()->getMessages(); - + /** @noinspection PhpInternalEntityUsedInspection */ $this->template->maxFiles = $this->controller->getUploadControl()->getMaxFiles(); /** @noinspection PhpInternalEntityUsedInspection */ @@ -105,50 +105,47 @@ private function setSettings() { $this->template->token = $this->controller->getUploadControl()->getToken(); $this->template->params = json_encode($this->controller->getUploadControl()->getParams()); $this->template->settings = $this->controller->getUploadControl()->getUploadSettings(); - + $default = $this->controller->getUploadControl()->getDefaultFiles(); - + $defaultFiles = []; - foreach($default as $file) { + foreach ($default as $file) { $defaultFiles[] = $file->toArray(); } - + $this->template->defaultFiles = $defaultFiles; } - - /** - * - */ - private function buildTemplates() { + + + private function buildTemplates() + { $this->template->fileContainerTemplate = $this->renderer->buildFileContainerTemplate(); $this->template->fileErrorTemplate = $this->renderer->buildFileError(); } - - /** - * - */ - private function setRendererSettings() { + + + private function setRendererSettings() + { $elements = $this->renderer->getElements(); - + $components = []; - foreach($elements as $type => $element) { - if($element !== null) { - $components[$type] = $element->getAttribute("data-upload-component"); + foreach ($elements as $type => $element) { + if ($element !== null) { + $components[$type] = $element->getAttribute('data-upload-component'); } else { $components[$type] = null; } } - + $this->template->components = $components; } - - /** - * - */ - private function needTranslate() { + + + private function needTranslate() + { $upload = $this->controller->getUploadControl(); - if($upload->isAutoTranslate()) { - foreach($upload->getMessages() as $key => $value) { + if ($upload->isAutoTranslate()) { + foreach ($upload->getMessages() as $key => $value) { $upload->setMessage($key, $upload->getTranslator()->translate($value)); } } diff --git a/src/Template/Renderer/BaseRenderer.php b/src/Template/Renderer/BaseRenderer.php index a6592ca..3d8a013 100644 --- a/src/Template/Renderer/BaseRenderer.php +++ b/src/Template/Renderer/BaseRenderer.php @@ -1,5 +1,7 @@ * @package Zet\FileUpload\Template\Renderer */ -abstract class BaseRenderer implements IUploadRenderer { +abstract class BaseRenderer implements IUploadRenderer +{ + use SmartObject; - - /** - * ID template ve tvaru: HtmlId-ElementType - * - * @var string - */ - private $idTemplate = "%s-%s"; - + /** * Seznam všech základních komponent uploaderu: *