378 lines
13 KiB
PHP
378 lines
13 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* as published by the Free Software Foundation; under version 2
|
||
|
* of the License (non-upgradable).
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
*
|
||
|
* Copyright (c) 2008-2010 (original work) Deutsche Institut für Internationale Pädagogische Forschung (under the project TAO-TRANSFER);
|
||
|
* 2009-2016 (update and modification) Public Research Centre Henri Tudor (under the project TAO-SUSTAIN & TAO-DEV);
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
use oat\tao\helpers\form\elements\xhtml\XhtmlRenderingTrait;
|
||
|
|
||
|
/**
|
||
|
* Short description of class tao_helpers_form_elements_xhtml_GenerisAsyncFile
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @package tao
|
||
|
*/
|
||
|
class tao_helpers_form_elements_xhtml_GenerisAsyncFile extends tao_helpers_form_elements_GenerisAsyncFile
|
||
|
{
|
||
|
use XhtmlRenderingTrait;
|
||
|
|
||
|
/**
|
||
|
* Short description of method feed
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function feed()
|
||
|
{
|
||
|
if (isset($_POST[$this->name])) {
|
||
|
$structure = json_decode($_POST[$this->name], true);
|
||
|
if ($structure !== false) {
|
||
|
$description = new tao_helpers_form_data_UploadFileDescription(
|
||
|
array_key_exists(
|
||
|
'name',
|
||
|
$structure
|
||
|
) ? $structure['name'] : null,
|
||
|
array_key_exists('size', $structure) ? $structure['size'] : null,
|
||
|
array_key_exists('type', $structure) ? $structure['type'] : null,
|
||
|
array_key_exists('uploaded_file', $structure) ? $structure['uploaded_file'] : null,
|
||
|
array_key_exists('action', $structure) ? $structure['action'] : null
|
||
|
);
|
||
|
$this->setValue($description);
|
||
|
} else {
|
||
|
// else, no file was selected by the end user.
|
||
|
// set the value as empty in order
|
||
|
$this->setValue($_POST[$this->name]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method render
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function render()
|
||
|
{
|
||
|
$widgetContainerId = $this->buildWidgetContainerId();
|
||
|
|
||
|
$returnValue = $this->renderLabel();
|
||
|
$returnValue .= "<div id='${widgetContainerId}' class='form-elt-container file-uploader'>";
|
||
|
|
||
|
if ($this->value instanceof tao_helpers_form_data_UploadFileDescription && $this->value->getAction() == tao_helpers_form_data_UploadFileDescription::FORM_ACTION_DELETE) {
|
||
|
// File deleted, nothing to render
|
||
|
} elseif ($this->value instanceof tao_helpers_form_data_FileDescription && ($file = $this->value->getFile()) != null) {
|
||
|
// A file is stored or has just been uploaded.
|
||
|
$shownFileName = $this->value->getName();
|
||
|
$shownFileSize = $this->value->getSize();
|
||
|
$shownFileSize = number_format($shownFileSize / 1000, 2); // to kb.
|
||
|
$shownFileTxt = sprintf(__('%s (%s kb)'), $shownFileName, $shownFileSize);
|
||
|
$deleteButtonTitle = __("Delete");
|
||
|
$deleteButtonId = $this->buildDeleteButtonId();
|
||
|
$downloadButtonTitle = __("Download");
|
||
|
$downloadButtonId = $this->buildDownloadButtonId();
|
||
|
$iFrameId = $this->buildIframeId();
|
||
|
$returnValue .= "<span class=\"widget_AsyncFile_fileinfo\">${shownFileTxt}</span>";
|
||
|
$returnValue .= "<button id=\"${downloadButtonId}\" type=\"button\" class=\"download btn-neutral small icon-download\" title=\"${downloadButtonTitle}\">";
|
||
|
$returnValue .= "<button id=\"${deleteButtonId}\" type=\"button\" class=\"delete btn-error small icon-bin\" title=\"${deleteButtonTitle}\"/>";
|
||
|
$returnValue .= "<iframe style=\"display:none\" id=\"${iFrameId}\" frameborder=\"0\"/>";
|
||
|
|
||
|
// Inject behaviour of the Delete/Download buttons component in response.
|
||
|
$returnValue .= self::embedBehaviour($this->buildDeleterBehaviour() . $this->buildDownloaderBehaviour());
|
||
|
} else {
|
||
|
// No file stored yet.
|
||
|
// Inject behaviour of the AsyncFileUpload component in response.
|
||
|
$returnValue .= self::embedBehaviour($this->buildUploaderBehaviour());
|
||
|
}
|
||
|
|
||
|
$returnValue .= "</div>";
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method getEvaluatedValue
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function getEvaluatedValue()
|
||
|
{
|
||
|
return $this->getRawValue();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildDeleterBehaviour
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildDeleterBehaviour()
|
||
|
{
|
||
|
return '$(document).ready(function() {
|
||
|
$("#' . $this->buildDeleteButtonId() . '").click(function() {
|
||
|
var $form = $(this).parents("form"),
|
||
|
$fileHandling = $form.find("[name=\'' . $this->getName() . '\']");
|
||
|
if(!$fileHandling.length) {
|
||
|
$fileHandling = $("<input>", { name: "' . $this->getName() . '", type: "hidden" });
|
||
|
$form.prepend($fileHandling);
|
||
|
}
|
||
|
$fileHandling.val("{\\"action\\":\\"delete\\"}");
|
||
|
$("#' . $this->buildWidgetContainerId() . '").empty();
|
||
|
' . $this->buildUploaderBehaviour(true) . '
|
||
|
});
|
||
|
});';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildUploaderBehaviour
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @param boolean deleted
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildUploaderBehaviour($deleted = false)
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$widgetName = $this->buildWidgetName();
|
||
|
|
||
|
// get the upload max size (the min of those 3 directives)
|
||
|
$max_upload = (int) (ini_get('upload_max_filesize'));
|
||
|
$max_post = (int) (ini_get('post_max_size'));
|
||
|
$memory_limit = (int) (ini_get('memory_limit'));
|
||
|
$fileSize = min($max_upload, $max_post, $memory_limit) * 1024 * 1024;
|
||
|
|
||
|
$mimetypes = [];
|
||
|
|
||
|
// add a client validation
|
||
|
foreach ($this->validators as $validator) {
|
||
|
// get the valid file extensions
|
||
|
if ($validator instanceof tao_helpers_form_validators_FileMimeType) {
|
||
|
$options = $validator->getOptions();
|
||
|
if (isset($options['mimetype'])) {
|
||
|
$mimetypes = $options['mimetype'];
|
||
|
}
|
||
|
}
|
||
|
// get the max file size
|
||
|
if ($validator instanceof tao_helpers_form_validators_FileSize) {
|
||
|
$options = $validator->getOptions();
|
||
|
if (isset($options['max'])) {
|
||
|
$validatorMax = (int) $options['max'];
|
||
|
if ($validatorMax > 0 && $validatorMax < $fileSize) {
|
||
|
$fileSize = $validatorMax;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// default value for 'auto' is 'true':
|
||
|
$auto = 'true';
|
||
|
if (isset($this->attributes['auto'])) {
|
||
|
if (! $this->attributes['auto'] || $this->attributes['auto'] === 'false') {
|
||
|
$auto = 'false';
|
||
|
}
|
||
|
unset($this->attributes['auto']);
|
||
|
}
|
||
|
|
||
|
// initialize the Uploader Js component
|
||
|
$returnValue .= '
|
||
|
require([\'jquery\', \'ui/feedback\', \'ui/uploader\'], function($, feedback){
|
||
|
$("#' . $this->buildWidgetContainerId() . '").uploader({
|
||
|
uploadUrl: "' . ROOT_URL . 'tao/File/upload",
|
||
|
autoUpload: "' . $auto . '" ,
|
||
|
showResetButton: "' . ! $auto . '" ,
|
||
|
showUploadButton: "' . ! $auto . '" ,
|
||
|
fileSelect : function(files, done){
|
||
|
var error = [],
|
||
|
givenLength = files.length,
|
||
|
filters = "' . implode(',', $mimetypes) . '".split(",").filter(function(e){return e.length});
|
||
|
|
||
|
if (filters.length){
|
||
|
|
||
|
files = _.filter(files, function(file){
|
||
|
return _.contains(filters, file.type);
|
||
|
});
|
||
|
|
||
|
if(files.length !== givenLength){
|
||
|
error.push( "Unauthorized files have been removed");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
files = _.filter(files, function(file){
|
||
|
return file.size <= ' . $fileSize . ';
|
||
|
});
|
||
|
|
||
|
if(files.length !== givenLength && !error.length){
|
||
|
error.push( "Size limit is ' . $fileSize . ' bytes");
|
||
|
}
|
||
|
|
||
|
if (error.length){
|
||
|
feedback().error(error.join(","));
|
||
|
}
|
||
|
|
||
|
done(files);
|
||
|
if ( ' . $auto . ' ){
|
||
|
$(this).uploader("upload");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}).on("upload.uploader", function(e, file, result){
|
||
|
if ( result && result.uploaded ){
|
||
|
var $container = $(e.target);
|
||
|
var $form = $container.parents("form");
|
||
|
var $fileHandling = $form.find("[name=\'file_handling\']");
|
||
|
$container.append($("<input type=\'hidden\' name=\'' . $this->getName() . '\'/>").val(result.data));
|
||
|
}
|
||
|
})
|
||
|
});';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildWidgetName
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildWidgetName()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = 'AsyncFileUploader_' . md5($this->name);
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildDeleteButtonId
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildDeleteButtonId()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = $this->buildWidgetName() . '_deleter';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildWidgetContainerId
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildWidgetContainerId()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = $this->buildWidgetName() . '_container';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method embedBehaviour
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @param string behaviour
|
||
|
* @return string
|
||
|
*/
|
||
|
public function embedBehaviour($behaviour)
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = '<script type="text/javascript">' . $behaviour . '</script>';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildDownloadButtonId
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildDownloadButtonId()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = $this->buildWidgetName() . '_downloader';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildDownloaderBehaviour
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildDownloaderBehaviour()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$downloadButtonId = $this->buildDownloadButtonId();
|
||
|
$iFrameId = $this->buildIframeId();
|
||
|
$serial = $this->value->getFileSerial();
|
||
|
|
||
|
$returnValue .= '$(document).ready(function() {';
|
||
|
$returnValue .= ' $("#' . $downloadButtonId . '").click(function() {';
|
||
|
$returnValue .= ' $("#' . $iFrameId . '").attr("src", ' . json_encode(_url('downloadFile', 'File', 'tao', [
|
||
|
'id' => $serial])) . ')';
|
||
|
$returnValue .= ' });';
|
||
|
$returnValue .= '});';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Short description of method buildIframeId
|
||
|
*
|
||
|
* @access public
|
||
|
* @author Jerome Bogaerts, <jerome@taotesting.com>
|
||
|
* @return string
|
||
|
*/
|
||
|
public function buildIframeId()
|
||
|
{
|
||
|
$returnValue = (string) '';
|
||
|
|
||
|
$returnValue = $this->buildWidgetName() . '_iframe';
|
||
|
|
||
|
return (string) $returnValue;
|
||
|
}
|
||
|
}
|