From 5709da9df59bfa1263a439fb51c73d715b0f53bf Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 3 May 2016 22:00:53 +0200 Subject: [PATCH] Upload and form submit fixes --- Admin/Routes/http.php | 38 ++++++++++++- Controller.js | 59 ++++++++++++--------- Controller.php | 28 ++-------- Models/Upload.js | 109 ++++++++++++++++++++++--------------- Models/UploadFile.php | 39 +++++++++----- Models/UploadStatus.php | 5 +- ModuleMedia.js | 115 ---------------------------------------- 7 files changed, 173 insertions(+), 220 deletions(-) delete mode 100644 ModuleMedia.js diff --git a/Admin/Routes/http.php b/Admin/Routes/http.php index acc3069..5c381b1 100644 --- a/Admin/Routes/http.php +++ b/Admin/Routes/http.php @@ -3,10 +3,44 @@ use phpOMS\Router\RouteVerb; return [ - '^.*/backend/accounting/personal/entries.*$' => [ + '^.*/backend/media/list.*$' => [ [ - 'dest' => '\Modules\Accounting\Controller:viewPersonalEntries', + 'dest' => '\Modules\Media\Controller:viewMediaList', 'verb' => RouteVerb::GET, ], ], + '^.*/backend/media/create.*$' => [ + [ + 'dest' => '\Modules\Media\Controller:setUpFileUploader', + 'verb' => RouteVerb::GET, + ], + [ + 'dest' => '\Modules\Media\Controller:viewMediaCreate', + 'verb' => RouteVerb::GET, + ], + ], + '^.*/backend/media/single.*$' => [ + [ + 'dest' => '\Modules\Media\Controller:viewMediaSingle', + 'verb' => RouteVerb::GET, + ], + ], + '^.*/api/media/collection.*$' => [ + [ + 'dest' => '\Modules\Media\Controller:apiCollectionCreate', + 'verb' => RouteVerb::SET, + ], + ], + '^.*/api/media$' => [ + [ + 'dest' => '\Modules\Media\Controller:apiMediaUpload', + 'verb' => RouteVerb::SET, + ], + ], + '^.*/api/media/create.*$' => [ + [ + 'dest' => '\Modules\Media\Controller:apiMediaCreate', + 'verb' => RouteVerb::SET, + ], + ], ]; diff --git a/Controller.js b/Controller.js index 9e60b7a..6283c86 100644 --- a/Controller.js +++ b/Controller.js @@ -1,45 +1,56 @@ -(function (jsOMS, undefined) { +(function (jsOMS, undefined) +{ jsOMS.Autoloader.defineNamespace('jsOMS.Modules'); - jsOMS.Modules.Media = function (app) { + jsOMS.Modules.Media = function (app) + { this.app = app; }; - jsOMS.Modules.Media.prototype.bind = function () { + jsOMS.Modules.Media.prototype.bind = function () + { let forms = document.getElementsByTagName('form'); /* Handle media forms */ - for (let c = 0; c < forms.length; c++) { + for (let i = 0; i < forms.length; i++) { let self = this; - if(typeof forms[i].querySelector('input[type=file]') !== 'undefined') { - this.app.uiManager.getFormManager().get(forms[c].id).injectSubmit(function (e) { - let fileFields = e.querySelectorAll('input[type=file]'), - uploader = new jsOMS.Modules.Media.Models.Upload(self.app.responseManager); + if (typeof forms[i].querySelector('input[type=file]') !== 'undefined') { + try { + this.app.uiManager.getFormManager().get(forms[i].id).injectSubmit('media-upload', function (e, requestId, requestGroup) + { + let fileFields = e.querySelectorAll('input[type=file]'), + uploader = new jsOMS.Modules.Models.Media.Upload(self.app.responseManager, self.app.logger); - uploader.setSuccess(e.id, function (type, response) { - e.querySelector('input[type=file]+input[type=hidden]').value = JSON.stringify(response.uploads); + uploader.setSuccess(e.id, function (type, response) + { + e.querySelector('input[type=file]+input[type=hidden]').value = JSON.stringify(response.uploads); + self.app.requestManager.triggerDone(requestId, requestGroup); + }); - let data = self.app.uiManager.getFormManager().getData(e); - self.app.uiManager.getFormManager().submit(e, data); - }); + uploader.setUri(Url + '{/lang}/api/media'); - uploader.setUri(jsOMS.Uri.UriFactory.build(Url + '/{lang}/api/media')); - - for (let i = 0; i < fileFields.length; i++) { - for (let j = 0; j < fileFields[i].files.length; j++) { - uploader.addFile(fileFields[i].files[j]); + for (let i = 0; i < fileFields.length; i++) { + for (let j = 0; j < fileFields[i].files.length; j++) { + uploader.addFile(fileFields[i].files[j]); + } } - } - uploader.upload(e.id); - }); + if (uploader.count() < 1) { + return; + } + + uploader.upload(e.id); + }); + } catch (e) { + this.app.logger.info('Tried to add media upload support for form without an ID.'); + } } } - } + }; }(window.jsOMS = window.jsOMS || {})); -jsOMS.ready(function () { - window.omsApp.moduleManager.initModule('Media'); +jsOMS.ready(function () +{ window.omsApp.moduleManager.get('Media').bind(); }); diff --git a/Controller.php b/Controller.php index 3151d0e..a72b8ad 100644 --- a/Controller.php +++ b/Controller.php @@ -85,25 +85,6 @@ class Controller extends ModuleAbstract implements WebInterface protected static $dependencies = [ ]; - /** - * Routing elements. - * - * @var array - * @since 1.0.0 - */ - protected static $routes = [ - '^.*/backend/media/list.*$' => [['dest' => '\Modules\Media\Controller:viewMediaList', 'method' => 'GET', 'type' => ViewLayout::MAIN],], - '^.*/backend/media/create.*$' => [ - ['dest' => '\Modules\Media\Controller:setUpFileUploader', 'method' => 'GET', 'type' => ViewLayout::NULL], - ['dest' => '\Modules\Media\Controller:viewMediaCreate', 'method' => 'GET', 'type' => ViewLayout::MAIN], - ], - '^.*/backend/media/single.*$' => [['dest' => '\Modules\Media\Controller:viewMediaSingle', 'method' => 'GET', 'type' => ViewLayout::MAIN],], - - '^.*/api/media/collection.*$' => [['dest' => '\Modules\Media\Controller:apiCollectionCreate', 'method' => 'POST', 'type' => ViewLayout::MAIN],], - '^.*/api/media$' => [['dest' => '\Modules\Media\Controller:apiMediaUpload', 'method' => 'POST', 'type' => ViewLayout::NULL],], - '^.*/api/media/create.*$' => [['dest' => '\Modules\Media\Controller:apiMediaCreate', 'method' => 'POST', 'type' => ViewLayout::NULL],], - ]; - /** * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -114,10 +95,11 @@ class Controller extends ModuleAbstract implements WebInterface * @since 1.0.0 * @author Dennis Eichhorn */ - public function setUpFileUploader(RequestAbstract $request, ResponseAbstract $response, $data = null) + public static function setUpFileUploader(RequestAbstract $request, ResponseAbstract $response, $data = null) { - $head = $response->getHead(); - $head->addAsset(AssetType::JS, $request->getUri()->getBase() . 'Modules/Media/ModuleMedia.js'); + $head = $response->get('Content')->getData('head'); + $head->addAsset(AssetType::JS, $request->getUri()->getBase() . 'Modules/Media/Models/Upload.js'); + $head->addAsset(AssetType::JS, $request->getUri()->getBase() . 'Modules/Media/Controller.js'); } /** @@ -229,7 +211,7 @@ class Controller extends ModuleAbstract implements WebInterface { $mediaCreated = []; - if (isset($files)) { + if (!empty($files)) { $upload = new UploadFile(); $rndPath = str_pad(dechex(rand(0, 65535)), 4, '0', STR_PAD_LEFT); $path = '/Modules/Media/Files/' . $rndPath[0] . $rndPath[1] . '/' . $rndPath[2] . $rndPath[3]; diff --git a/Models/Upload.js b/Models/Upload.js index 46ee879..174eddb 100644 --- a/Models/Upload.js +++ b/Models/Upload.js @@ -1,73 +1,98 @@ -(function (jsOMS, undefined) { - jsOMS.Autoloader.defineNamespace('jsOMS.Modules.Media.Models'); +(function (jsOMS, undefined) +{ + jsOMS.Autoloader.defineNamespace('jsOMS.Modules.Models.Media'); - jsOMS.Modules.Models.Media.Upload = function (responseManager) { + jsOMS.Modules.Models.Media.Upload = function (responseManager, logger) + { + this.logger = logger; this.responseManager = responseManager; - this.success = []; + this.success = []; - this.uri = ''; + this.uri = ''; this.allowedTypes = []; - this.maxFileSize = 0; - this.files = []; + this.maxFileSize = 0; + this.files = []; }; - jsOMS.Modules.Models.Media.Upload.prototype.setSuccess = function (id, callback) { - this.success[id] = callback; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setUri = function (uri) { - this.uri = uri; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setAllowedTypes = function (allowed) { - this.allowedTypes = allowed; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.addAllowedType = function (allowed) { - this.allowedTypes.push(allowed); - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setMaxFileSize = function (size) { + jsOMS.Modules.Models.Media.Upload.prototype.setMaxFileSize = function (size) + { this.maxFileSize = size; }; - jsOMS.Modules.Models.Media.Upload.prototype.addFile = function (file) { + jsOMS.Modules.Models.Media.Upload.prototype.getMaxFileSize = function (size) + { + return this.maxFileSize; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.setSuccess = function (id, callback) + { + this.success[id] = callback; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.setUri = function (uri) + { + this.uri = uri; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.setAllowedTypes = function (allowed) + { + this.allowedTypes = allowed; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.addAllowedType = function (allowed) + { + this.allowedTypes.push(allowed); + }; + + jsOMS.Modules.Models.Media.Upload.prototype.setMaxFileSize = function (size) + { + this.maxFileSize = size; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.addFile = function (file) + { this.files.push(file); }; - jsOMS.Modules.Models.Media.Upload.prototype.upload = function (formId) { + jsOMS.Modules.Models.Media.Upload.prototype.count = function () + { + return this.files.length; + }; + + jsOMS.Modules.Models.Media.Upload.prototype.upload = function (formId) + { // TODO: validate file type + file size - var request = new jsOMS.Message.Request.Request(), + let request = new jsOMS.Message.Request.Request(), formData = new FormData(), - self = this; + self = this; - this.files.forEach(function (element, index) { + this.files.forEach(function (element, index) + { formData.append('file' + index, element); }); request.setData(formData); - request.setType('raw'); + request.setType(jsOMS.Message.Request.RequestType.RAW); request.setUri(this.uri); - request.setMethod('POST'); + request.setMethod(jsOMS.Message.Request.RequestMethod.POST); request.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'); - request.setSuccess(function (xhr) { - console.log(xhr); // TODO: remove this is for error checking - var o = JSON.parse(xhr.response), - response = Object.keys(o).map(function (k) { - return o[k]; - }); + request.setSuccess(function (xhr) + { + try { + let response = JSON.parse(xhr.response); - console.log(response); - - for (var k = 0; k < response.length; k++) { - if (response[k] !== null) { + for (let k = 0; k < response.length; k++) { if (!self.success[formId]) { - self.responseManager.execute(response[k].type, response[k]); + self.responseManager.run(response[k].type, response[k]); } else { self.success[formId](response[k].type, response[k]); } } + } catch (exception) { + self.logger.error('Invalid media upload response: ' + xhr.response); + + return false; } }); request.send(); diff --git a/Models/UploadFile.php b/Models/UploadFile.php index 6e25105..b25c597 100644 --- a/Models/UploadFile.php +++ b/Models/UploadFile.php @@ -178,8 +178,13 @@ class UploadFile \mkdir($path, '0655', true); } - if (!move_uploaded_file($path = $f['tmp_name'], $path . '/' . $this->fileName) || !is_uploaded_file($path)) { - // couldn't move + if (!is_uploaded_file($f['tmp_name'])) { + $result[$key]['status'] = UploadStatus::NOT_UPLOADED; + + return $result; + } + + if (!move_uploaded_file($f['tmp_name'], $path . '/' . $this->fileName)) { $result[$key]['status'] = UploadStatus::NOT_MOVABLE; return $result; @@ -198,7 +203,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function getMaxSize() : int + public + function getMaxSize() : int { return $this->maxSize; } @@ -211,7 +217,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function setMaxSize(int $maxSize) + public + function setMaxSize(int $maxSize) { $this->maxSize = $maxSize; } @@ -222,7 +229,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function getAllowedTypes() : array + public + function getAllowedTypes() : array { return $this->allowedTypes; } @@ -235,7 +243,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function setAllowedTypes(array $allowedTypes) + public + function setAllowedTypes(array $allowedTypes) { $this->allowedTypes = $allowedTypes; } @@ -248,7 +257,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function addAllowedTypes($allowedTypes) + public + function addAllowedTypes($allowedTypes) { $this->allowedTypes[] = $allowedTypes; } @@ -259,7 +269,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function getOutputDir() : string + public + function getOutputDir() : string { return $this->outputDir; } @@ -272,7 +283,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function setOutputDir(string $outputDir) + public + function setOutputDir(string $outputDir) { $this->outputDir = $outputDir; } @@ -283,7 +295,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function getFileName() : string + public + function getFileName() : string { return $this->fileName; } @@ -296,7 +309,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function setFileName(string $fileName) + public + function setFileName(string $fileName) { $this->fileName = $fileName; } @@ -309,7 +323,8 @@ class UploadFile * @since 1.0.0 * @author Dennis Eichhorn */ - public function setPreserveFileName(bool $preserveFileName) + public + function setPreserveFileName(bool $preserveFileName) { $this->preserveFileName = $preserveFileName; } diff --git a/Models/UploadStatus.php b/Models/UploadStatus.php index 303e200..8e7c10b 100644 --- a/Models/UploadStatus.php +++ b/Models/UploadStatus.php @@ -37,6 +37,7 @@ abstract class UploadStatus extends Enum const UNKNOWN_ERROR = -4; const CONFIG_SIZE = -5; const WRONG_EXTENSION = -6; - const NOT_MOVABLE = -7; - const FAILED_HASHING = -8; + const NOT_UPLOADED = -7; + const NOT_MOVABLE = -8; + const FAILED_HASHING = -9; } diff --git a/ModuleMedia.js b/ModuleMedia.js deleted file mode 100644 index 63b571a..0000000 --- a/ModuleMedia.js +++ /dev/null @@ -1,115 +0,0 @@ -(function (jsOMS, undefined) { - jsOMS.Modules.Models.Media = typeof jsOMS.Modules.Models.Media == 'undefined' ? {} : jsOMS.Modules.Models.Media; - - jsOMS.Modules.Models.Media.Upload = function (responseManager) { - this.responseManager = responseManager; - this.success = []; - - this.uri = ''; - this.allowedTypes = []; - this.maxFileSize = 0; - this.files = []; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setSuccess = function (id, callback) { - this.success[id] = callback; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setUri = function (uri) { - this.uri = uri; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setAllowedTypes = function (allowed) { - this.allowedTypes = allowed; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.addAllowedType = function (allowed) { - this.allowedTypes.push(allowed); - }; - - jsOMS.Modules.Models.Media.Upload.prototype.setMaxFileSize = function (size) { - this.maxFileSize = size; - }; - - jsOMS.Modules.Models.Media.Upload.prototype.addFile = function (file) { - this.files.push(file); - }; - - jsOMS.Modules.Models.Media.Upload.prototype.upload = function (formId) { - // TODO: validate file type + file size - - var request = new jsOMS.Message.Request.Request(), - formData = new FormData(), - self = this; - - this.files.forEach(function (element, index) { - formData.append('file' + index, element); - }); - - request.setData(formData); - request.setType('raw'); - request.setUri(this.uri); - request.setMethod('POST'); - request.setRequestHeader('HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'); - request.setSuccess(function (xhr) { - console.log(xhr); // TODO: remove this is for error checking - var o = JSON.parse(xhr.response), - response = Object.keys(o).map(function (k) { - return o[k]; - }); - - console.log(response); - - for (var k = 0; k < response.length; k++) { - if (response[k] !== null) { - if (!self.success[formId]) { - self.responseManager.execute(response[k].type, response[k]); - } else { - self.success[formId](response[k].type, response[k]); - } - } - } - }); - request.send(); - }; -}(window.jsOMS = window.jsOMS || {})); -(function (jsOMS, undefined) { - jsOMS.Modules.Media = function (app) { - this.app = app; - }; - - jsOMS.Modules.Media.prototype.bind = function () { - var forms = document.getElementsByTagName('form'); - - /* Handle media forms */ - for (var c = 0; c < forms.length; c++) { - var self = this; - - this.app.uiManager.getFormManager().injectSubmit(forms[c].id, function (e) { - var fileFields = e.querySelectorAll('input[type=file]'), - uploader = new jsOMS.Modules.Models.Media.Upload(self.app.responseManager); - - uploader.setSuccess(e.id, function (type, response) { - e.querySelector('input[type=file]+input[type=hidden]').value = JSON.stringify(response.uploads); - - var data = self.app.uiManager.getFormManager().getData(e); - self.app.uiManager.getFormManager().submit(e, data); - }); - - uploader.setUri('http://127.0.0.1/en/api/media'); - - for (var i = 0; i < fileFields.length; i++) { - for (var j = 0; j < fileFields[i].files.length; j++) { - uploader.addFile(fileFields[i].files[j]); - } - } - - uploader.upload(e.id); - }); - } - } -}(window.jsOMS = window.jsOMS || {})); - -jsOMS.ready(function () { - window.omsApp.moduleManager.get('Media').bind(); -});