*/ WBClass::load('WBHtml_JS', 'WBUser'); /** * patForms Elemenbt: vfsselect * * Select files from VFS * * @version 1.2.1 * @package Wombat * @subpackage patForms */ class patForms_Element_Vfsselect 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'; /** * element type to create HTML output * @var array */ public $elementType = array("html" => "input"); /** * session * @var patSession_Storage */ private $sess; /** * session * @var WBVFS_File */ private $file; /** * Template engine * @var patTemplate */ private $tmpl; /** * 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(), ), 'default' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), '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(''), ), '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() ), ), '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()), ), '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('html'), ), 'des' => array( 'required' => false, 'format' => 'int', 'default' => -1, 'outputFormats' => array('html') ), 'chroot' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'defaultdir' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array('html') ), 'multiple' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array( 'html' ), ), 'min' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'max' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'listformat' => array( 'required' => false, 'format' => 'string', 'default' => 'array', 'outputFormats' => array(), ), 'mimetype' => array( 'required' => false, 'format' => 'string', 'default' => '*/*', 'outputFormats' => array(), ), 'thumbnailsize' => array( 'required' => false, 'format' => 'string', 'default' => '50x50', 'outputFormats' => array(), ), ); /** * 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 values given for the element does not match any of the possible values.' ), 3 => patI18n::dgettext('wombat', 'You have to select at least [MIN] entries.' ), 4 => patI18n::dgettext('wombat', 'You may not select more than [MAX] entries.' ), 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. * * @param mixed value of the element * @return mixed $element The element, or false if failed. */ public function serializeHtmlDefault($value) { $this->startSession(); $value = $this->normalizeValue($value); // editable or not? if (isset($this->attributes['edit']) && $this->attributes['edit'] == 'no') { return $this->serializeHtmlReadonly($value); } $id = $this->attributes['id']; WBHtml_JS::add('WB/Form'); WBHtml_JS::add('WB/Form/Element'); WBHtml_JS::add('WB/Form/Element/Vfsselect'); //WBHtml_JS::add(sprintf('$("#%s")[0].vfsselect = new WB.Form.Element.Vfsselect("%1$s", "file");', $id), WBHtml_JS::AREA_FOOT); $this->tmpl = WBClass::create('patTemplate'); $this->tmpl->readTemplatesFromInput('Form/Element/vfsselect.tmpl'); $this->tmpl->clearTemplate('form-element-snippet', true); $atts = $this->getAttributesFor($this->getFormat()); $atts['value'] = implode(',', $value); $this->tmpl->addGlobalVars($atts, 'root_'); $list = array(); foreach ($value as $v) { if (empty($v)) { continue; } $file = $this->file->loadById($v); if (!$file->isOK()) { continue; } $list[] = array( 'id' => $v, 'obscureid' => $file->getObscureId(), 'name' => $file->getName() ); } $list[] = array( 'id' => 'proto', 'obscureid' => 'proto', 'name' => 'proto' ); $this->tmpl->addRows('list_entry', $list); return $this->tmpl->getParsedTemplate('form-element-snippet'); } /** * 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->startSession(); $value = $this->normalizeValue($value); return $this->createHiddenTag(implode(',', $value)); } /** * Add Uploaded Files * * Method will create VFS files from uploaded files if there are any uploads. * VFS files will be placed in folder specified by "des" attribute. In case * "des" is negative (default: -1), this feature is switched off. * * @param array $values */ private function addUploadFiles(&$value) { if (0 > $this->attributes['des']) { return; } if (!isset($_FILES[$this->attributes['name']]) || !is_array($_FILES[$this->attributes['name']])) { return; } $this->file->setCurrentDir($this->attributes['des']); $files = $_FILES[$this->attributes['name']]; foreach ($files['name'] as $i => $name) { if (0 < $files['error'][$i]) { continue; } if (WBVFS_File::QUOTA_OK != $this->file->checkQuota($files['size'][$i]) ) { $this->addValidationError(5); return; } $tmpFile = tempnam(WBParam::get('wb/dir/base') . '/var/tmp/', 'upload'); move_uploaded_file($files['tmp_name'][$i], $tmpFile); $file = $this->file->import($tmpFile, $name); $value[] = $file->getId(); } return; } /** * validates the element. * * Verify file selection * * @param stringd $value of the element * @return bool $isValid True if element could be validated, false otherwise. */ public function validateElement($value) { $this->startSession(); $value = $this->normalizeValue($value); $this->addUploadFiles($value); // required & empty if (isset($this->attributes['required']) && $this->attributes['required'] == 'yes' && empty($value)) { $this->addValidationError(1); return false; } // remove unwanted $mimetype = array('*'); if (isset($this->attributes['mimetype']) && !empty($this->attributes['mimetype'])) { $mimetype = explode('/', strtolower($this->attributes['mimetype'])); if (empty($mimetype) || empty($mimetype[0])) { $mimetype = array('*'); } } $validated = array(); foreach($value as $v) { // check for existing file $file = $this->file->loadById($v); if (!$file->isOK()) { continue; } // remove files of unwanted mime type if ($mimetype[0] != '*') { $mime = $file->getMime(WBVFS_File::MIME_MAJOR); if ($mime != $mimetype[0]) { continue; } if (isset($mimetype[1]) && $mimetype[1] != '*') { $mime = $file->getMime(WBVFS_File::MIME_MINOR); if ($mime != $mimetype[1]) { continue; } } } $validated[] = $v; } // set value after validation $this->value = $validated; // count $amountSelected = count($validated); if (isset($this->attributes['min']) && $amountSelected < $this->attributes['min']) { $this->addValidationError(3, array('min' => $this->attributes['min'])); return false; } if (isset($this->attributes['max']) && $amountSelected > $this->attributes['max']) { $this->addValidationError( 4, array('max' => $this->attributes['max'])); return false; } return true; } /** * Redefinition of the main patForms_Element method that manages * converting string values to the internal format. * * @access public * @param string|array A single value as string, or a selected values list * @see patForms_Element::setValue() */ public function setValue($value) { $value = $this->normalizeValue($value); return parent::setValue($value); } /** * implement special behaviour for array * * Format value as configured in attribute: "listformat": * * - string: a comma separated list of ids * - array: an array with ids * * @see patForms_Element::getValue() * @param bool tell wheather used external * @return mixed $value */ public function getValue($external = true) { $value = parent::getValue($external); if (empty($value)) { $value = array(); } $value = $this->normalizeValue($value); if (isset($this->attributes['listformat']) && $this->attributes['listformat'] == 'array') { return $value; } // "string" otherwise return implode(',', $value); } /** * normalize value array * * Normalize array or string list of comma separated ids to array * * @param mixed $value * @return array $value */ private function normalizeValue($value) { if (empty($value)) { $value = array(); } if (!is_array($value)) { $value = array_map('trim', explode(',', $value)); } for ($i = 0; $i < count($value); ++$i) { if (empty($value[$i])) { unset($value[$i]); } } $value = array_values(array_unique($value)); return $value; } /** * start session and other object * * this method runs only once per instance */ private function startSession() { if ($this->sess) { return; } $this->sess = WBClass::create('patSession'); // user id for VFS $user = null; if (isset($this->attributes['user']) && !empty($this->attributes['user'])) { $user = $this->attributes['user']; } $params = array(); if ($user) { $this->sess->set('vfsfile_user', $user); $params['user'] = $user; } else { $this->sess->clear('vfsfile_user'); $user = WBUser::getCurrent(); $params['user'] = $user->getId(); } $this->file = WBClass::create('WBVFS_File', $params); // chroot if (isset($this->attributes['chroot']) && !empty($this->attributes['chroot'])) { $this->sess->set('vfsfile_chroot', $this->attributes['chroot']); } else { $this->sess->clear('vfsfile_chroot'); } } }