Chamilo is a learning management system focused on ease of use and accessibility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
chamilo-lms/main/inc/lib/pear/HTML/QuickForm/file.php

485 lines
16 KiB

<?php
/**
* HTML class for a file upload field
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.01 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_01.txt If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category HTML
* @package HTML_QuickForm
* @author Adam Daniel <adaniel1@eesus.jnj.com>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Alexey Borzov <avb@php.net>
* @copyright 2001-2009 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: file.php,v 1.25 2009/04/04 21:34:02 avb Exp $
* @link http://pear.php.net/package/HTML_QuickForm
*/
/**
* HTML class for a file upload field
*
* @category HTML
* @package HTML_QuickForm
* @author Adam Daniel <adaniel1@eesus.jnj.com>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Alexey Borzov <avb@php.net>
* @version Release: 3.2.11
* @since 1.0
*/
class HTML_QuickForm_file extends HTML_QuickForm_input
{
/**
* Uploaded file data, from $_FILES
* @var array
*/
var $_value = null;
/**
* Class constructor
*
* @param string Input field name attribute
* @param string Input field label
* @param mixed (optional)Either a typical HTML attribute string
* or an associative array
* @since 1.0
* @access public
*/
public function __construct($elementName=null, $elementLabel=null, $attributes=null)
{
parent::__construct($elementName, $elementLabel, $attributes);
$this->setType('file');
}
/**
* Sets size of file element
*
* @param int Size of file element
* @since 1.0
* @access public
*/
function setSize($size)
{
$this->updateAttributes(array('size' => $size));
}
/**
* Returns size of file element
*
* @since 1.0
* @access public
* @return int
*/
function getSize()
{
return $this->getAttribute('size');
}
/**
* Freeze the element so that only its value is returned
*
* @access public
* @return bool
*/
function freeze()
{
return false;
}
/**
* Sets value for file element.
*
* Actually this does nothing. The function is defined here to override
* HTML_Quickform_input's behaviour of setting the 'value' attribute. As
* no sane user-agent uses <input type="file">'s value for anything
* (because of security implications) we implement file's value as a
* read-only property with a special meaning.
*
* @param mixed Value for file element
* @since 3.0
* @access public
*/
function setValue($value)
{
return null;
}
/**
* Returns information about the uploaded file
*
* @since 3.0
* @access public
* @return array
*/
public function getValue()
{
return $this->_value;
} // end func getValue
// }}}
// {{{ onQuickFormEvent()
/**
* Called by HTML_QuickForm whenever form event is made on this element
*
* @param string Name of event
* @param mixed event arguments
* @param object calling object
* @since 1.0
* @access public
* @return bool
*/
public function onQuickFormEvent($event, $arg, &$caller)
{
switch ($event) {
case 'updateValue':
if ($caller->getAttribute('method') == 'get') {
throw new \Exception('Cannot add a file upload field to a GET method form');
}
$this->_value = $this->_findValue();
$caller->updateAttributes(array('enctype' => 'multipart/form-data'));
$caller->setMaxFileSize();
break;
case 'addElement':
$this->onQuickFormEvent('createElement', $arg, $caller);
return $this->onQuickFormEvent('updateValue', null, $caller);
break;
case 'createElement':
//$className = get_class($this);
//$this &= new $className($arg[0], $arg[1], $arg[2]);
break;
}
return true;
}
/**
* Moves an uploaded file into the destination
*
* @param string Destination directory path
* @param string New file name
* @access public
* @return bool Whether the file was moved successfully
*/
public function moveUploadedFile($dest, $fileName = '')
{
if ($dest != '' && substr($dest, -1) != '/') {
$dest .= '/';
}
$fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName);
}
/**
* Checks if the element contains an uploaded file
*
* @access public
* @return bool true if file has been uploaded, false otherwise
*/
public function isUploadedFile()
{
return self::_ruleIsUploadedFile($this->_value);
}
/**
* Checks if the given element contains an uploaded file
*
* @param array Uploaded file info (from $_FILES)
* @access private
* @return bool true if file has been uploaded, false otherwise
*/
public static function _ruleIsUploadedFile($elementValue)
{
if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
(!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
return is_uploaded_file($elementValue['tmp_name']);
} else {
return false;
}
}
/**
* Tries to find the element value from the values array
*
* Needs to be redefined here as $_FILES is populated differently from
* other arrays when element name is of the form foo[bar]
*
* @access public
* @return mixed
*/
public function _findValue(&$values = null)
{
if (empty($_FILES)) {
return null;
}
$elementName = $this->getName();
if (isset($_FILES[$elementName])) {
return $_FILES[$elementName];
} elseif (false !== ($pos = strpos($elementName, '['))) {
$base = str_replace(
array('\\', '\''), array('\\\\', '\\\''),
substr($elementName, 0, $pos)
);
$idx = "['" . str_replace(
array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
substr($elementName, $pos + 1, -1)
) . "']";
$props = array('name', 'type', 'size', 'tmp_name', 'error');
$code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
" return null;\n" .
"} else {\n" .
" \$value = array();\n";
foreach ($props as $prop) {
$code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
}
return eval($code . " return \$value;\n}\n");
} else {
return null;
}
}
/**
* @return string
*/
public function getElementJS($param)
{
$id = $this->getAttribute('id');
$ratio = 'aspectRatio: 16 / 9';
if (!empty($param['ratio'])) {
$ratio = 'aspectRatio: '.$param['ratio'].',';
}
$scalable = 'false';
if (!empty($param['scalable']) && $param['scalable'] != 'false') {
$ratio = '';
$scalable = $param['scalable'];
}
return '<script>
$(function() {
var $inputFile = $(\'#'.$id.'\'),
$image = $(\'#'.$id.'_preview_image\'),
$input = $(\'[name="'.$id.'_crop_result"]\'),
$cropButton = $(\'#'.$id.'_crop_button\'),
$formGroup = $(\'#'.$id.'-form-group\');
function isValidType(file) {
var fileTypes = [\'image/jpg\', \'image/jpeg\', \'image/gif\', \'image/png\'];
for(var i = 0; i < fileTypes.length; i++) {
if(file.type === fileTypes[i]) {
return true;
}
}
return false;
}
function imageCropper() {
$formGroup.show();
$cropButton.show();
$image
.cropper(\'destroy\')
.cropper({
'.$ratio.'
responsive : true,
preview: \'.img-preview\',
center : false,
guides : false,
movable: false,
zoomable: false,
rotatable: false,
scalable: '.$scalable.',
crop: function(e) {
// Output the result data for cropping image.
$input.val(event.detail.x + \',\' + event.detail.y + \',\' + event.detail.width + \',\' + event.detail.height);
}
});
}
$inputFile.on(\'change\', function () {
var inputFile = this,
file = inputFile.files[0],
fileReader = new FileReader();
$(".img-box").hide();
$(".img-preview").show();
if (!isValidType(file)) {
$formGroup.hide();
$cropButton.hide();
if (inputFile.setCustomValidity) {
inputFile.setCustomValidity(
inputFile.title ? inputFile.title : \''.get_lang('OnlyImagesAllowed').'\'
);
}
return;
}
if (inputFile.setCustomValidity) {
inputFile.setCustomValidity(\'\');
}
fileReader.readAsDataURL(file);
fileReader.onload = function () {
$image
.attr(\'src\', this.result)
.on(\'load\', imageCropper);
};
});
$cropButton.on(\'click\', function () {
var $imageLarge = $("#image-cut-lg");
var canvas = $image.cropper(\'getCroppedCanvas\'),
dataUrl = canvas.toDataURL();
$(".img-box").show();
$(".img-preview").hide();
$image.attr(\'src\', dataUrl).cropper(\'destroy\').off(\'load\', imageCropper);
$imageLarge.attr(\'src\', dataUrl).cropper(\'destroy\').off(\'load\', imageCropper);
$(\'[name="'.$id.'_crop_image_base_64"]\').val(dataUrl);
$cropButton.hide();
});
});
</script>';
}
/**
* @return string
*/
public function toHtml()
{
$js = '';
if (isset($this->_attributes['crop_image'])) {
$ratio = '16 / 9';
if (!empty($this->_attributes['crop_ratio'])) {
$ratio = $this->_attributes['crop_ratio'];
}
$scalable = 'false';
if (!empty($this->_attributes['crop_scalable'])) {
$scalable = $this->_attributes['crop_scalable'];
}
$js = $this->getElementJS(array('ratio' => $ratio, 'scalable' => $scalable));
}
if ($this->isFrozen()) {
return $this->getFrozenHtml();
} else {
$class = '';
if (isset($this->_attributes['custom']) && $this->_attributes['custom']) {
$class = 'input-file';
}
return $js.$this->_getTabs().
'<input class="'.$class.'" '.$this->_getAttrString($this->_attributes).' />';
}
}
/**
* @param string $layout
*
* @return string
*/
public function getTemplate($layout)
{
$name = $this->getName();
$attributes = $this->getAttributes();
$size = $this->calculateSize();
switch ($layout) {
case FormValidator::LAYOUT_INLINE:
return '
<div class="form-group {error_class}">
<label {label-for} >
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
{label}
</label>
{element}
</div>';
break;
case FormValidator::LAYOUT_HORIZONTAL:
if (isset($attributes['custom']) && $attributes['custom']) {
$template = '
<div class="input-file-container">
{element}
<label tabindex="0" {label-for} class="input-file-trigger">
<i class="fa fa-picture-o fa-lg" aria-hidden="true"></i> {label}
</label>
</div>
<p class="file-return"></p>
<script>
document.querySelector("html").classList.add(\'js\');
var fileInput = document.querySelector( ".input-file" ),
button = document.querySelector( ".input-file-trigger" ),
the_return = document.querySelector(".file-return");
button.addEventListener("keydown", function(event) {
if ( event.keyCode == 13 || event.keyCode == 32 ) {
fileInput.focus();
}
});
button.addEventListener("click", function(event) {
fileInput.focus();
return false;
});
fileInput.addEventListener("change", function(event) {
fileName = this.value;
if (this.files[0]) {
fileName = this.files[0].name;
}
the_return.innerHTML = fileName;
});
</script>
';
} else {
$template = '
<div id="file_'.$name.'" class="form-group row {error_class}">
<label {label-for} class="col-sm-'.$size[0].' control-label" >
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
{label}
</label>
<div class="col-sm-'.$size[1].'">
{icon}
{element}
<!-- BEGIN label_2 -->
<p class="help-block">{label_2}</p>
<!-- END label_2 -->
<!-- BEGIN error -->
<span class="help-inline help-block">{error}</span>
<!-- END error -->
</div>
<div class="col-sm-'.$size[2].'">
<!-- BEGIN label_3 -->
{label_3}
<!-- END label_3 -->
</div>
</div>';
}
return $template;
break;
case FormValidator::LAYOUT_BOX_NO_LABEL:
return '
<label {label-for}>{label}</label>
<div class="input-group">
{icon}
{element}
</div>';
break;
}
}
}