*/ /** * patForms Elemenbt: vfsfile * * Upload and create VFSFile * * @version 0.2.0 * @package Wombat * @subpackage patForms */ class patForms_Element_Vfsfile extends patForms_Element { /** * Stores the name of the element - this is used mainly by the patForms * error management and should be set in every element class. * @var string */ public $elementName = 'Vfsfile'; /** * maximum file size in MByte * @var int */ protected $maxSize = 100; /** * Uploaded files stored in tmp * @var string */ protected $tmpFile = array(); /** * file * @var WBVFS_File */ protected $file; /** * element type to create HTML output * @var array */ public $elementType = array("html" => "input"); /** * set here which attributes you want to include in the element if you want to use * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically * convert the values from your element definition into element attributes. * * @see patForms_Element::convertDefinition2Attribute() * @var array */ public $attributeDefinition = array( 'id' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'name' => array( 'required' => true, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'type' => array( 'required' => false, 'format' => 'string', 'default' => 'file', 'outputFormats' => array('html'), ), 'title' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'description' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'modifiers' => array('insertSpecials' => array()), ), 'label' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'display' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'edit' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'required' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'value' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'default' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'style' => array( 'required' => false, 'outputFormats' => array('html'), 'format' => 'string', ), 'class' => array( 'required' => false, 'outputFormats' => array('html'), 'format' => 'string', ), 'onchange' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array() ), ), 'onclick' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onfocus' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onmouseover' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onmouseout' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onblur' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'accesskey' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'position' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'tabindex' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array('html'), ), 'format' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'disabled' => array( 'required' => false, 'format' => 'string', 'default' => 'no', 'outputFormats' => array('html'), ), 'user' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'des' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'multiple' => array( 'required' => false, 'format' => 'string', 'default' => '', 'outputFormats' => array('html'), ) ); /** * destructor * * remove unwanted temporary file */ public function __destruct() { // clean up upload file foreach ($this->tmpFile as $t) { if (!empty($t) && file_exists($t)) { unlink($t); } } $this->tmpFile = array(); } /** * set defautl value * * override parent's implementation * * @param mixed $value * @return mixed */ public function setDefaultValue($value) { if (empty($this->value)) { $this->setValue($value); } return parent::setDefaultValue($value); } /** * Initialize validation codes using gettext * * Overwrite this function to add element's error codes * * @return bool $success Always returns true. * @see $attributeDefaults */ public function loadValidatiorErrorCodes() { $this->validatorErrorCodes = array( 1 => patI18n::dgettext('wombat', 'This field is required, please complete it.'), 2 => patI18n::dgettext('wombat', 'The uploaded file was only partially uploaded.'), 3 => patI18n::dgettext('wombat', 'The uploaded file exceeds the maximum size of [MAXSIZE] MByte.'), 4 => patI18n::dgettext('wombat', 'The uploaded file is empty.' ), 5 => patI18n::dgettext('wombat', 'Your online storage is out of space.' ), ); return true; } /** * element creation method for the 'HTML' format in the 'default' form mode. * * @access public * @param mixed value of the element * @return mixed $element The element, or false if failed. */ public function serializeHtmlDefault( $value ) { $this->attributes['value'] = $value; // editable or not? if (isset($this->attributes['edit']) && $this->attributes['edit'] == 'no') { return $this->serializeHtmlReadonly($value); } $attributes = $this->getAttributesFor($this->getFormat()); if (empty($attributes['multiple']) || 'no' == $attributes['multiple']) { unset($attributes['multiple']); } else { $attributes['multiple'] = 'multiple'; $attributes['name'] .= '[]'; } if (isset($attributes['required']) && 'no' == $attributes['required']) { unset($attributes['required']); } return $this->createTag($this->elementType[$this->getFormat()], "full", $attributes); } /** * element creation method for the 'HTML' format in the 'readonly' form mode. * Very simple; just returns the stored element value. * * @access public * @param mixed value of the element * @return string $value The element's value */ public function serializeHtmlReadonly($value) { $this->getAttributesFor($this->getFormat()); return $value . $this->createHiddenTag($value); } /** * validates the element. * * Verify file upload * * @param stringd $value of the element * @return bool $isValid True if element could be validated, false otherwise. */ public function validateElement($value) { $required = false; $empty = false; $name = $this->attributes['name']; // store the required flag for easy access if (isset($this->attributes['required']) && $this->attributes['required'] == 'yes') { $required = true; } $files = array(); if (isset($_FILES)) { $files = $_FILES; if (($namespace = $this->getNamespace()) && isset($files[$namespace])) { $files = $files[$namespace]; } } // no file upload at all if (empty($files) || !isset($files[$name])) { $empty = true; } if ($empty && $required) { $this->addValidationError(1); return false; } if ($empty && !$required) { if (isset($this->attributes['default'])) { $this->setValue($this->attributes['default']); } return true; } // collect upload info if (!$namespace) { $upload = $files[$name]['tmp_name']; $error = $files[$name]['error']; $value = $files[$name]['name']; $size = $files[$name]['size']; } else { $upload = $files['tmp_name'][$name]; $error = $files['error'][$name]; $value = $files['name'][$name]; $size = $files['size'][$name]; } // normalize if (!is_array($upload)) { $upload = array($upload); } if (!is_array($error)) { $error = array($error); } if (!is_array($value)) { $value = array($value); } if (!is_array($size)) { $size = array($size); } // upload error foreach ($error as $e) { if (!$this->checkErrorCode($e)) { return false; } } // don't allow empty files if ($size < 2) { if (!$required) { $this->setValue(0); return true; } $this->addValidationError(4); return false; } // convert max-size in MByte to Bytes $config = WBClass::create('WBConfig'); $config->load('vfs'); $this->maxSize = $config->get('upload/maxsize', $this->maxSize); $maxSize = $this->maxSize * 1048576; $sizeSum = 0; foreach ($size as $s) { $sizeSum += $s; } if ($sizeSum > $maxSize) { $this->addValidationError(3, array('maxsize' => $this->maxSize)); return false; } foreach ($upload as $u) { $t = tempnam(WBParam::get('wb/dir/base') . '/var/tmp/', 'upload'); if (!move_uploaded_file($u, $t)) { WBClass::load('WBException_File'); throw new WBException_File('Could not move upload file to tmp folder', 1, __CLASS__); return false; } chmod($t, 0666); $this->tmpFile[] = $t; } if ('multiple' == $this->attributes['multiple']) { $this->setValue($value); } else { $this->setValue($value[0]); } $userId = null; if (isset($this->attributes['user']) && !empty($this->attributes['user'])) { $userId = $this->attributes['user']; } else { WBClass::load('WBUser'); $userId = WBUser::getCurrent()->getId(); } $this->file = WBClass::create('WBVFS_File', array('user' => $userId)); /** @var $file WBVFS_File */ if (WBVFS_File::QUOTA_OK != $this->file->checkQuota($sizeSum) ) { $this->file = null; $this->addValidationError(5); return false; } return true; } /** * finalize element * * Store file in user's VFS in case validation was successfull * * @see include/pat/patForms/patForms_Element#finalizeElement($value) * @param string $value file name * @return bool always true */ public function finalizeElement($value) { if (!$this->file) { return true; } if (!is_array($value)) { $value = array($value); } // finally impot uploaded file $des = 0; if (isset($this->attributes['des']) && !empty($this->attributes['des'])) { $des = $this->attributes['des']; } $this->file->setCurrentDir($des); $ids = array(); foreach ($this->tmpFile as $i => $t) { $file = $this->file->import($t, $value[$i]); $ids[] = $file->getId(); } if ('multiple' == $this->attributes['multiple']) { $this->setValue($ids); } else { $this->setValue($ids[0]); } $this->tmpFile = array(); return true; } /** * check the given code if it is an error * * @access private * @param int $code * @return boolean $result true on success */ function checkErrorCode($code) { // this is most likely the case if ($code == UPLOAD_ERR_OK) { return true; } // partial upload if ($code == UPLOAD_ERR_PARTIAL) { $this->addValidationError(2); return false; } // file too big if ($code == UPLOAD_ERR_INI_SIZE || $code == UPLOAD_ERR_FORM_SIZE) { $maxSize = str_split(ini_get('upload_max_filesize')); $multi = strtolower(array_pop($maxSize)); $maxSize = implode('', $maxSize); // convert from kilo, mega, giga, tera and simple bytes to mega byte switch ($multi) { case 'k'; $maxSize = round($maxSize / 1024, 1); break; case 'm': break; case 'g'; $maxSize = round($maxSize * 1024, 0); break; case 't'; $maxSize = round($maxSize * 1048576, 0); break; default: if (is_numeric($multi)) { $maxSize .= $multi; $maxSize = round($maxSize / 1048576, 1); } break; } $this->addValidationError(3, array('maxsize' => $maxSize)); return false; } // no file if ($code == UPLOAD_ERR_NO_FILE && $this->attributes['required'] == 'yes') { $this->addValidationError(1); return false; } // ignore other codes like NO FILE, etc return true; } }