Add file option type
authorMatthias Schmidt <gravatronics@live.com>
Sun, 14 Dec 2014 10:46:41 +0000 (11:46 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 14 Dec 2014 10:46:41 +0000 (11:46 +0100)
wcfsetup/install/files/acp/templates/fileOptionType.tpl [new file with mode: 0644]
wcfsetup/install/files/acp/templates/option.tpl
wcfsetup/install/files/lib/system/option/FileOptionType.class.php [new file with mode: 0644]

diff --git a/wcfsetup/install/files/acp/templates/fileOptionType.tpl b/wcfsetup/install/files/acp/templates/fileOptionType.tpl
new file mode 100644 (file)
index 0000000..85c035d
--- /dev/null
@@ -0,0 +1,4 @@
+<input type="file" id="{$option->optionName}" name="{$option->optionName}" value="" />
+{if $value}
+       <label><input type="checkbox" id="{$option->optionName}_remove_file" name="values[{$option->optionName}]" /> {lang}wcf.acp.option.{$option->optionName}.removeFile{/lang}</label>
+{/if}
index 93e48eb100eefb779d5baea2e66e26c3966c332d..bcf535c4bcd10961f7117ab01c9ac1280c39ae9c 100644 (file)
@@ -47,7 +47,7 @@
        {/hascontent}
 </div>
 
-<form method="post" action="{link controller='Option' id=$category->categoryID}{/link}">
+<form method="post" action="{link controller='Option' id=$category->categoryID}{/link}" enctype="multipart/form-data">
        <div class="tabMenuContainer" data-active="{$activeTabMenuItem}" data-store="activeTabMenuItem">
                <nav class="tabMenu">
                        <ul>
diff --git a/wcfsetup/install/files/lib/system/option/FileOptionType.class.php b/wcfsetup/install/files/lib/system/option/FileOptionType.class.php
new file mode 100644 (file)
index 0000000..4cd788a
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+namespace wcf\system\option;
+use wcf\data\option\Option;
+use wcf\data\package\PackageCache;
+use wcf\system\exception\UserInputException;
+use wcf\system\exception\SystemException;
+use wcf\system\upload\IUploadFileValidationStrategy;
+use wcf\system\upload\UploadHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Option type implementation for uploading a file.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2014 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.option
+ * @category   Community Framework
+ */
+class FileOptionType extends AbstractOptionType {
+       /**
+        * upload handler for option files
+        * @var array<\wcf\system\upload\UploadHandler>
+        */
+       protected $uploadHandlers = array();
+       
+       /**
+        * Creates the upload handler for the given option.
+        * 
+        * @param       \wcf\data\option\Option         $option
+        */
+       protected function createUploadHandler(Option $option) {
+               if (!isset($this->uploadHandlers[$option->optionName])) {
+                       $this->uploadHandlers[$option->optionName] = UploadHandler::getUploadHandler($option->optionName);
+               }
+       }
+       
+       /**
+        * @see \wcf\system\option\IOptionType::getData()
+        */
+       public function getData(Option $option, $newValue) {
+               $this->createUploadHandler($option);
+               
+               $files = $this->uploadHandlers[$option->optionName]->getFiles();
+               $file = reset($files);
+               
+               // check if file has been uploaded
+               if (!$file->getFilename()) {
+                       // if checkbox is checked, remove file
+                       if ($newValue) {
+                               @unlink($option->optionValue);
+                               
+                               return '';
+                       }
+                       
+                       // use old value
+                       return $option->optionValue;
+               }
+               else if ($option->optionValue) {
+                       // delete old file first
+                       @unlink($option->optionValue);
+               }
+               
+               // determine location the file will be stored at
+               $package = PackageCache::getInstance()->getPackage($option->packageID);
+               $fileLocation = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$package->packageDir)).$option->filelocation.'.'.$file->getFileExtension();
+               
+               // save file
+               move_uploaded_file($file->getLocation(), $fileLocation);
+               
+               // return file location as the value to store in the database
+               return $fileLocation;
+       }
+       
+       /**
+        * @see \wcf\system\option\IOptionType::getFormElement()
+        */
+       public function getFormElement(Option $option, $value) {
+               WCF::getTPL()->assign(array(
+                       'option' => $option,
+                       'value' => $value
+               ));
+               
+               return WCF::getTPL()->fetch('fileOptionType');
+       }
+       
+       /**
+        * @see \wcf\system\option\IOptionType::validate()
+        */
+       public function validate(Option $option, $newValue) {
+               $this->createUploadHandler($option);
+               
+               $files = $this->uploadHandlers[$option->optionName]->getFiles();
+               $file = reset($files);
+               
+               // check if file has been uploaded
+               if (!$file->getFilename()) {
+                       return;
+               }
+               
+               // validate file
+               if ($option->filevalidation) {
+                       $fileValidation = new $option->filevalidation();
+                       if (!($fileValidation instanceof IUploadFileValidationStrategy)) {
+                               throw new SystemException("The file validation class needs to implement 'wcf\system\upload\IUploadFileValidationStrategy'");
+                       }
+                       
+                       if (!$this->uploadHandlers[$option->optionName]->validateFiles($fileValidation)) {
+                               $erroneousFiles = $this->uploadHandlers[$option->optionName]->getErroneousFiles();
+                               $erroneousFile = reset($erroneousFiles);
+                               
+                               throw new UserInputException($option->optionName, 'file.'.$erroneousFile->getValidationErrorType());
+                       }
+               }
+       }
+}