partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 9d5f342d315c3496fd144e2dc4c721056d9b9f87
parent 12281fd5bfeca744f991e72795e7ef461153ac7c
Author: Felicitus <felicitus@felicitus.org>
Date:   Fri, 17 Jul 2015 18:02:56 +0200

Implemented the temporary file service, removed obsolete code, refactored frontend exception window

Diffstat:
A.jshintrc | 6++++++
Mapp/config/config.yml | 44++++++++++++++++++++++++++++++++++++++++++--
Mapp/config/partkeepr.yml | 5+++--
Msrc/PartKeepr/FootprintBundle/Entity/Footprint.php | 4++--
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartFilterPanel.js | 4----
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectEditorComponent.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/StockReport/AbstractStockHistoryGrid.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditorComponent.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/SystemNotice/SystemNoticeEditorComponent.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/User/UserEditorComponent.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/RemotePartComboBox.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/StorageLocationComboBox.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Data/HydraProxy.js | 15+--------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/ExceptionWindow.js | 18+++++++++++++++---
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/FileUploadDialog.js | 344+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Models/TipOfTheDay.js | 1-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js | 76----------------------------------------------------------------------------
Msrc/PartKeepr/ImageBundle/Controller/ImageController.php | 28+++-------------------------
Msrc/PartKeepr/ImageBundle/Services/ImageService.php | 5++---
Asrc/PartKeepr/UploadedFileBundle/Controller/FileController.php | 29+++++++++++++++++++++++++++++
Asrc/PartKeepr/UploadedFileBundle/Controller/TemporaryFileController.php | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/PartKeepr/UploadedFileBundle/Entity/TempUploadedFile.php | 19+++++++++++++++++++
Msrc/PartKeepr/UploadedFileBundle/Services/UploadedFileService.php | 17++++++++++++++---
Dsrc/backend/PartKeepr/FootprintAttachment/FootprintAttachmentService.php | 103-------------------------------------------------------------------------------
Msrc/backend/PartKeepr/Part/PartManager.php | 2+-
Msrc/backend/PartKeepr/PartKeepr.php | 2+-
Msrc/backend/PartKeepr/Printing/PrintingJob/PrintingJob.php | 2+-
Msrc/backend/PartKeepr/Printing/PrintingService.php | 2+-
Msrc/backend/PartKeepr/ProjectAttachment/ProjectAttachmentService.php | 2+-
Dsrc/backend/PartKeepr/TempFile/TempFileService.php | 106-------------------------------------------------------------------------------
Dsrc/backend/PartKeepr/UploadedFile/TempUploadedFile.php | 18------------------
33 files changed, 379 insertions(+), 549 deletions(-)

diff --git a/.jshintrc b/.jshintrc @@ -0,0 +1,5 @@ +{ + "undef": true, + "unused": true, + "predef": [ "PartKeepr", "i18n", "Ext" ] +}+ \ No newline at end of file diff --git a/app/config/config.yml b/app/config/config.yml @@ -394,4 +394,44 @@ services: - method: "initCollectionOperations" arguments: [ [ "@resource.tempimage.collection_operation.custom_post" ] ] - method: "initItemOperations" - arguments: [ [ "@resource.tempimage.item_operation.custom_get" ] ]- \ No newline at end of file + arguments: [ [ "@resource.tempimage.item_operation.custom_get" ] ] + + resource.tempfile.collection_operation.custom_post: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createCollectionOperation" ] + arguments: + - "@resource.tempfile" # Resource + - [ "POST" ] # Methods + - "/temporaryFile/upload" # Path + - "PartKeeprUploadedFileBundle:TemporaryFile:upload" # Controller + - "TemporaryFileUpload" # Route name + - # Context (will be present in Hydra documentation) + "@type": "hydra:Operation" + "hydra:title": "A custom operation" + "returns": "xmls:string" + + resource.tempfile.item_operation.custom_get: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: + - "@resource.tempfile" # Resource + - [ "GET" ] # Methods + - "/temporaryFile/{id}/getFile" # Path + - "PartKeeprUploadedFileBundle:TemporaryFile:getFile" # Controller + - "TemporaryFileGet" # Route name + - # Context (will be present in Hydra documentation) + "@type": "hydra:Operation" + "hydra:title": "A custom operation" + "returns": "xmls:string" + + resource.tempfile: + parent: "api.resource" + arguments: [ "PartKeepr\\UploadedFileBundle\\Entity\\TempUploadedFile" ] + tags: [ { name: "api.resource" } ] + calls: + - method: "initCollectionOperations" + arguments: [ [ "@resource.tempfile.collection_operation.custom_post" ] ] + - method: "initItemOperations" + arguments: [ [ "@resource.tempfile.item_operation.custom_get" ] ]+ \ No newline at end of file diff --git a/app/config/partkeepr.yml b/app/config/partkeepr.yml @@ -2,4 +2,5 @@ partkeepr: image_cache_directory: %kernel.cache_dir%/imagecache/ directories: iclogo: %kernel.root_dir%/../data/images/iclogo/ - temp: %kernel.root_dir%/../data/temp/- \ No newline at end of file + temp: %kernel.root_dir%/../data/temp/ + tempfile: %kernel.root_dir%/../data/files/Temporary/+ \ No newline at end of file diff --git a/src/PartKeepr/FootprintBundle/Entity/Footprint.php b/src/PartKeepr/FootprintBundle/Entity/Footprint.php @@ -4,7 +4,6 @@ namespace PartKeepr\FootprintBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use PartKeepr\DoctrineReflectionBundle\Annotation\TargetService; -use PartKeepr\UploadedFile\TempUploadedFile; use PartKeepr\Util\BaseEntity; use Symfony\Component\Serializer\Annotation\Groups; @@ -176,7 +175,8 @@ class Footprint extends BaseEntity /** * Adds an IC Logo. * - * @param FootprintAttachment|TempUploadedFile $attachment Either a FootprintAttachment or a TempUploadedFile + * @param FootprintAttachment|\PartKeepr\UploadedFileBundle\Entity\TempUploadedFile $attachment + * Either a FootprintAttachment or a TempUploadedFile * * @return void */ diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartFilterPanel.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartFilterPanel.js @@ -109,10 +109,6 @@ Ext.define('PartKeepr.PartFilterPanel', { * @return nothing */ onApply: function () { - if (!this.store) { - PartKeepr.getApplication().raiseRuntimeError("PartFilterPanel.store is not set"); - return; - } this.applyFilterParameters(this.store.getProxy().extraParams); this.store.currentPage = 1; this.store.load({ start: 0}); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js @@ -29,7 +29,6 @@ Ext.define('PartKeepr.PartManager', { */ this.createStore({ model: 'PartKeepr.Part.Part', - proxy: PartKeepr.getRESTProxy("Part"), groupField: 'categoryPath', sorters: [{ property: 'name', diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectEditorComponent.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectEditorComponent.js @@ -11,7 +11,6 @@ Ext.define('PartKeepr.ProjectEditorComponent', { initComponent: function () { this.createStore({ sorters: [{ - proxy: PartKeepr.getRESTProxy("Project"), property: 'name', direction:'ASC' }] diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StockReport/AbstractStockHistoryGrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StockReport/AbstractStockHistoryGrid.js @@ -79,7 +79,6 @@ Ext.define('PartKeepr.AbstractStockHistoryGrid', { autoSync: true, remoteFilter: true, remoteSort: true, - proxy: PartKeepr.getRESTProxy("Stock"), model: this.model, sorters: [{ property: 'dateTime', diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js @@ -14,7 +14,6 @@ Ext.define('PartKeepr.StorageLocationEditor', { autoSync: false, // Do not change. If true, new (empty) records would be immediately commited to the database. remoteFilter: true, remoteSort: true, - proxy: PartKeepr.getRESTProxy("Part"), pageSize: 15 }); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditorComponent.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditorComponent.js @@ -8,7 +8,6 @@ Ext.define('PartKeepr.StorageLocationEditorComponent', { initComponent: function () { this.createStore({ sorters: [{ - proxy: PartKeepr.getRESTProxy("StorageLocation"), property: 'name', direction:'ASC' }] diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/SystemNotice/SystemNoticeEditorComponent.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/SystemNotice/SystemNoticeEditorComponent.js @@ -11,7 +11,6 @@ Ext.define('PartKeepr.SystemNoticeEditorComponent', { initComponent: function () { this.createStore({ sorters: [{ - proxy: PartKeepr.getRESTProxy("SystemNotice"), property: 'date', direction:'DESC' }] diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/UserEditorComponent.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/User/UserEditorComponent.js @@ -12,7 +12,6 @@ Ext.define('PartKeepr.UserEditorComponent', { initComponent: function () { this.createStore({ sorters: [{ - proxy: PartKeepr.getRESTProxy("User"), property: 'username', direction:'ASC' }] diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/RemotePartComboBox.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/RemotePartComboBox.js @@ -21,7 +21,6 @@ Ext.define("PartKeepr.RemotePartComboBox",{ */ this.createStore({ model: 'PartKeepr.Part.Part', - proxy: PartKeepr.getRESTProxy("Part"), groupField: 'categoryPath', sorters: [{ property: 'name', diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/StorageLocationComboBox.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/StorageLocationComboBox.js @@ -19,7 +19,6 @@ Ext.define("PartKeepr.StorageLocationComboBox",{ this.store = Ext.create("Ext.data.Store", { model: 'PartKeepr.StorageLocation.StorageLocation', - proxy: PartKeepr.getRESTProxy("StorageLocation"), pageSize: -1, autoLoad: true }); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Data/HydraProxy.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Data/HydraProxy.js @@ -107,19 +107,6 @@ Ext.define("PartKeepr.data.HydraProxy", { this.showException(response); }, showException: function (response) { - try { - var data = Ext.decode(response.responseText); - - var exception = Ext.create("PartKeepr.data.HydraException", data); - - PartKeepr.ExceptionWindow.showException(exception, response); - } catch (ex) { - var exception = Ext.create("PartKeepr.data.HydraException", { - title: i18n("Critical Error"), - description: i18n("The server returned a response which we were not able to interpret.") - }); - - PartKeepr.ExceptionWindow.showException(exception, response); - } + PartKeepr.ExceptionWindow.showException(response); } }); \ No newline at end of file diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/ExceptionWindow.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/ExceptionWindow.js @@ -274,14 +274,26 @@ Ext.define('PartKeepr.ExceptionWindow', { * @param {PartKeepr.data.HydraException} exception The exception object * @param {Object} response The response object */ - showException: function (exception, response) + showException: function (response) { if (!PartKeepr.ExceptionWindow.activeInstance) { PartKeepr.ExceptionWindow.activeInstance = new PartKeepr.ExceptionWindow(); } - PartKeepr.ExceptionWindow.activeInstance._showException(exception, response); - } + try { + var data = Ext.decode(response.responseText); + + var exception = Ext.create("PartKeepr.data.HydraException", data); + + PartKeepr.ExceptionWindow.activeInstance._showException(exception, response); + } catch (ex) { + var exception = Ext.create("PartKeepr.data.HydraException", { + title: i18n("Critical Error"), + description: i18n("The server returned a response which we were not able to interpret.") + }); + PartKeepr.ExceptionWindow.activeInstance._showException(exception, response); + } + } } }); \ No newline at end of file diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/FileUploadDialog.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/FileUploadDialog.js @@ -1,193 +1,191 @@ Ext.define('PartKeepr.FileUploadDialog', { extend: 'Ext.window.Window', - + title: i18n("File Upload"), fileFieldLabel: i18n("File"), uploadButtonText: i18n('Select File...'), - uploadURL: PartKeepr.getBasePath()+"/TempFile", + uploadURL: PartKeepr.getBasePath() + "/api/temporaryFile/upload", layout: 'fit', resizable: false, modal: true, iconCls: 'icon-drive-upload', - initComponent: function () { - - if (this.imageUpload) { - this.uploadURL = PartKeepr.getBasePath() + "/api/temporaryImage/upload"; - } - - this.uploadButton = Ext.create("Ext.button.Button", - { - text: i18n('Upload'), - iconCls: 'icon-drive-upload', - width: 120, - handler: Ext.bind(function() { - var form = this.form.getForm(); - - if (this.fileField.getValue() === "" && this.urlField.getValue() === "") { - Ext.Msg.alert(i18n("Error"), i18n("Please select a file to upload or enter an URL")); - return; - } - - - if(form.isValid()){ - form.submit({ - url: this.uploadURL, - params: { - session: PartKeepr.getApplication().getSession() - }, - success: Ext.bind(function(fp, o) { - this.fireEvent("fileUploaded", o.result.response); - this.close(); - },this), - failure: function(form, action) { - var exception = { - message: i18n("Critical Error"), - detail: i18n("The server returned a response which we were not able to interpret.") - }; - - - var requestData = { options: {}}; - - request = { - responseText: action.response.responseText - }; - - PartKeepr.ExceptionWindow.showException(exception, request); - } - }); - } - }, this) - }); - - this.urlField = Ext.create("Ext.form.field.Text", { - fieldLabel: i18n("URL"), - labelWidth: 50, - name: "url", - anchor: '100%' - }); - - this.tbButtons = [ this.uploadButton ]; - - if (this.imageUpload) { - - this.title = i18n("Image Upload"); - this.fileFieldLabel = i18n("Image"); - this.uploadButtonText = i18n("Select Image..."); - - this.fileFormatButton = Ext.create("Ext.button.Button", { - text: i18n("Available Formats"), - width: 120, - iconCls: 'icon-infocard', - handler: this.showAvailableFormats, - scope: this - }); - - this.tbButtons.push(this.fileFormatButton); - } - - this.fileField = Ext.create("Ext.form.field.File",{ - xtype: 'filefield', - name: 'userfile', - fieldLabel: this.fileFieldLabel, - labelWidth: 50, - msgTarget: 'side', - anchor: '100%', - buttonText: this.uploadButtonText - }); - - this.uploadSizeButton = Ext.create("Ext.button.Button", { - xtype: 'button', - icon: 'bundles/brainbitsfugueicons/icons/fugue/16/information-frame.png', - handler: this.showUploadSizeInformation, - scope: this - }); - - this.form = Ext.create('Ext.form.Panel', { - width: 400, - bodyPadding: 10, - border: false, - items: [{ - html: i18n("Select a file to upload or enter an URL to load the file from"), - border: false, - style: "margin-bottom: 20px;" - }, - this.fileField, - { - border: false, - style: 'margin-bottom: 20px;margin-left: 55px;', - layout: { - type: 'hbox', - pack: 'start', - align: 'middle' - }, - items: [ - { - html: sprintf(i18n("Maximum upload size: %s"), PartKeepr.bytesToSize(PartKeepr.getMaxUploadSize())), - style: 'margin-right: 10px;', - border: false - }, - this.uploadSizeButton - ] - }, - this.urlField], - buttons: this.tbButtons - }); - - this.on("beforedestroy", this.onBeforeDestroy, this); - - this.items = this.form; - this.callParent(); + initComponent: function () + { + + if (this.imageUpload) { + this.uploadURL = PartKeepr.getBasePath() + "/api/temporaryImage/upload"; + } + + this.uploadButton = Ext.create("Ext.button.Button", + { + text: i18n('Upload'), + iconCls: 'icon-drive-upload', + width: 120, + handler: Ext.bind(function () + { + var form = this.form.getForm(); + + if (this.fileField.getValue() === "" && this.urlField.getValue() === "") { + Ext.Msg.alert(i18n("Error"), i18n("Please select a file to upload or enter an URL")); + return; + } + + + if (form.isValid()) { + form.submit({ + url: this.uploadURL, + params: { + session: PartKeepr.getApplication().getSession() + }, + success: Ext.bind(function (fp, o) + { + this.fireEvent("fileUploaded", o.result.response); + this.close(); + }, this), + failure: function (form, action) + { + PartKeepr.ExceptionWindow.showException(action.response); + } + }); + } + }, this) + }); + + this.urlField = Ext.create("Ext.form.field.Text", { + fieldLabel: i18n("URL"), + labelWidth: 50, + name: "url", + anchor: '100%' + }); + + this.tbButtons = [this.uploadButton]; + + if (this.imageUpload) { + + this.title = i18n("Image Upload"); + this.fileFieldLabel = i18n("Image"); + this.uploadButtonText = i18n("Select Image..."); + + this.fileFormatButton = Ext.create("Ext.button.Button", { + text: i18n("Available Formats"), + width: 120, + iconCls: 'icon-infocard', + handler: this.showAvailableFormats, + scope: this + }); + + this.tbButtons.push(this.fileFormatButton); + } + + this.fileField = Ext.create("Ext.form.field.File", { + xtype: 'filefield', + name: 'userfile', + fieldLabel: this.fileFieldLabel, + labelWidth: 50, + msgTarget: 'side', + anchor: '100%', + buttonText: this.uploadButtonText + }); + + this.uploadSizeButton = Ext.create("Ext.button.Button", { + xtype: 'button', + icon: 'bundles/brainbitsfugueicons/icons/fugue/16/information-frame.png', + handler: this.showUploadSizeInformation, + scope: this + }); + + this.form = Ext.create('Ext.form.Panel', { + width: 400, + bodyPadding: 10, + border: false, + items: [ + { + html: i18n("Select a file to upload or enter an URL to load the file from"), + border: false, + style: "margin-bottom: 20px;" + }, + this.fileField, + { + border: false, + style: 'margin-bottom: 20px;margin-left: 55px;', + layout: { + type: 'hbox', + pack: 'start', + align: 'middle' + }, + items: [ + { + html: sprintf(i18n("Maximum upload size: %s"), + PartKeepr.bytesToSize(PartKeepr.getMaxUploadSize())), + style: 'margin-right: 10px;', + border: false + }, + this.uploadSizeButton + ] + }, + this.urlField + ], + buttons: this.tbButtons + }); + + this.on("beforedestroy", this.onBeforeDestroy, this); + + this.items = this.form; + this.callParent(); }, /** * Displays a little hint regarding the maximum upload size */ - showUploadSizeInformation: function () { - if (!this.uploadSizeTip) { - this.uploadSizeTip = Ext.create("Ext.tip.ToolTip", { - title: i18n("Upload Size Information"), - anchor: 'left', - width: 350, - height: 132, - autoScroll: true, - target: this.uploadSizeButton.getEl(), - closable: true, - html: i18n("The maximum upload size can be configured in your php.ini file. There are two separate options:<br/>- post_max_size<br/>- upload_max_filesize<br/><br/>You need to set both values high enough.")+ - '<br/><br/><a target="_blank" href="http://de2.php.net/manual/en/ini.core.php#ini.post-max-size">'+i18n("More Information")+'</a>', - autoHide: false - }); - } - - - this.uploadSizeTip.show(); + showUploadSizeInformation: function () + { + if (!this.uploadSizeTip) { + this.uploadSizeTip = Ext.create("Ext.tip.ToolTip", { + title: i18n("Upload Size Information"), + anchor: 'left', + width: 350, + height: 132, + autoScroll: true, + target: this.uploadSizeButton.getEl(), + closable: true, + html: i18n("The maximum upload size can be configured in your php.ini file. There are two separate options:<br/>- post_max_size<br/>- upload_max_filesize<br/><br/>You need to set both values high enough.") + + '<br/><br/><a target="_blank" href="http://de2.php.net/manual/en/ini.core.php#ini.post-max-size">' + i18n("More Information") + '</a>', + autoHide: false + }); + } + + + this.uploadSizeTip.show(); }, /** * Shows a tooltip for all available image formats. */ - showAvailableFormats: function () { - if (!this.imageFormatsTip) { - this.imageFormatsTip = Ext.create("Ext.tip.ToolTip", { - title: i18n("Available Image Formats"), - anchor: 'left', - width: 200, - height: 300, - autoScroll: true, - target: this.fileFormatButton.getEl(), - closable: true, - html: implode("<br>", PartKeepr.getAvailableImageFormats()), - autoHide: false - }); - } - - - this.imageFormatsTip.show(); + showAvailableFormats: function () + { + if (!this.imageFormatsTip) { + this.imageFormatsTip = Ext.create("Ext.tip.ToolTip", { + title: i18n("Available Image Formats"), + anchor: 'left', + width: 200, + height: 300, + autoScroll: true, + target: this.fileFormatButton.getEl(), + closable: true, + html: implode("<br>", PartKeepr.getAvailableImageFormats()), + autoHide: false + }); + } + + + this.imageFormatsTip.show(); }, - onBeforeDestroy: function () { - if (this.imageFormatsTip) { - this.imageFormatsTip.destroy(); - } - - if (this.uploadSizeTip) { - this.uploadSizeTip.destroy(); - } + onBeforeDestroy: function () + { + if (this.imageFormatsTip) { + this.imageFormatsTip.destroy(); + } + + if (this.uploadSizeTip) { + this.uploadSizeTip.destroy(); + } } }); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Models/TipOfTheDay.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Models/TipOfTheDay.js @@ -6,5 +6,4 @@ Ext.define("PartKeepr.TipOfTheDay", { { name: 'url', type: 'string'}, { name: 'read', type: 'boolean' } ], - proxy: PartKeepr.getRESTProxy("TipOfTheDay") }); \ No newline at end of file diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js b/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js @@ -253,19 +253,6 @@ Ext.application({ this.centerPanel.removeAll(true); this.getSessionManager().logout(); }, - /** - * Handles a runtime error. - * - * @param error A string indicating which error has occured. - */ - raiseRuntimeError: function (error) { - var exception = { - message: i18n("Runtime Error"), - detail: error - }; - - PartKeepr.ExceptionWindow.showException(exception); - }, createGlobalStores: function () { this.footprintStore = Ext.create("Ext.data.Store", { @@ -592,69 +579,6 @@ Ext.application({ } }); -/** - * <p>This static method returns a REST object definition for use with any models.</p> - * <p>It automatically sets the session (if available) and the prefix for the given REST service.</p> - * @param {string} service The REST service to call. Only use the base name, e.g. "Footprint" instead of "FootprintService". - * @return {Object} The RESTProxy definition -*/ -PartKeepr.getRESTProxy = function (service) { - var request,requestData = {}; - - var obj = { - batchActions: false, - url: PartKeepr.getBasePath()+ '/'+service, - listeners: { - exception: function (proxy, response, operation) { - try { - var data = Ext.decode(response.responseText); - - requestData.method = operation.request.method; - requestData.headers = operation.request.headers; - requestData.jsonData = operation.request.jsonData; - - request = { - request: Ext.encode(requestData), - response: response.responseText - }; - - PartKeepr.ExceptionWindow.showException(data.exception, request); - } catch (ex) { - var exception = { - message: i18n("Critical Error"), - detail: i18n("The server returned a response which we were not able to interpret.") - }; - - - requestData.method = operation.request.method; - requestData.headers = operation.request.headers; - requestData.jsonData = operation.request.jsonData; - - request = { - request: Ext.encode(requestData), - response: response.responseText - }; - - PartKeepr.ExceptionWindow.showException(exception, request); - } - } - }, - reader: { - type: 'json', - rootProperty: 'response.data', - successProperty: "success", - messageProperty: 'message', - totalProperty : 'response.totalCount' - }, - writer: { - type: 'jsonwithassociations' - } - - }; - //Ext.data.AjaxProxy.superclass.constructor.apply(this, arguments); - return new Ext.data.proxy.Rest(obj); -}; - PartKeepr.getSession = function () { alert("This should not be called."); return "hli2ong0ktnise68p9f5nu6nk1"; diff --git a/src/PartKeepr/ImageBundle/Controller/ImageController.php b/src/PartKeepr/ImageBundle/Controller/ImageController.php @@ -2,7 +2,6 @@ namespace PartKeepr\ImageBundle\Controller; use Doctrine\ORM\EntityManager; -use Dunglas\ApiBundle\Controller\ResourceController; use Imagine\Gd\Imagine; use Imagine\Image\Box; use Imagine\Image\Point; @@ -10,10 +9,11 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc; use PartKeepr\Image\CachedImage; use PartKeepr\ImageBundle\Entity\Image as PartKeeprImage; use PartKeepr\ImageBundle\Response\ImageNotFoundResponse; +use PartKeepr\UploadedFileBundle\Controller\FileController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -abstract class ImageController extends ResourceController +abstract class ImageController extends FileController { /** * @@ -124,20 +124,6 @@ abstract class ImageController extends ResourceController } /** - * Returns the full path for the image - * - * @param PartKeeprImage $image - * - * @return string - */ - public function getFilename(PartKeeprImage $image) - { - $storageDirectory = $this->get("partkeepr_uploadedfile_service")->getStorageDirectory($image); - - return $storageDirectory."/".$image->getFilename().".".$image->getExtension(); - } - - /** * Returns the path to an image which has been cached in a particular width, height and mode. * * @param PartKeeprImage $image The image @@ -155,11 +141,4 @@ abstract class ImageController extends ResourceController return $outputFile; } - - /** - * Returns the entity class (FQDN) for operation, e.g. "PartKeepr\\ManufacturerBundle\\Entity\\ManufacturerICLogo" - * - * @return string - */ - abstract public function getEntityClass(); -}- \ No newline at end of file +} diff --git a/src/PartKeepr/ImageBundle/Services/ImageService.php b/src/PartKeepr/ImageBundle/Services/ImageService.php @@ -19,7 +19,7 @@ class ImageService extends UploadedFileService */ public function replace(UploadedFile $file, File $filesystemFile) { - parent::replaceFromFilesystem($file, $filesystemFile); + parent::replace($file, $filesystemFile); $this->invalidate($file); } @@ -64,4 +64,4 @@ class ImageService extends UploadedFileService $entityManager->remove($file); } } -}- \ No newline at end of file +} diff --git a/src/PartKeepr/UploadedFileBundle/Controller/FileController.php b/src/PartKeepr/UploadedFileBundle/Controller/FileController.php @@ -0,0 +1,29 @@ +<?php +namespace PartKeepr\UploadedFileBundle\Controller; + +use Dunglas\ApiBundle\Controller\ResourceController; +use PartKeepr\UploadedFileBundle\Entity\UploadedFile; + +abstract class FileController extends ResourceController +{ + /** + * Returns the full path for the file + * + * @param UploadedFile $file + * + * @return string + */ + public function getFilename(UploadedFile $file) + { + $storageDirectory = $this->get("partkeepr_uploadedfile_service")->getStorageDirectory($file); + + return $storageDirectory."/".$file->getFilename().".".$file->getExtension(); + } + + /** + * Returns the entity class (FQDN) for operation + * + * @return string + */ + abstract public function getEntityClass(); +} diff --git a/src/PartKeepr/UploadedFileBundle/Controller/TemporaryFileController.php b/src/PartKeepr/UploadedFileBundle/Controller/TemporaryFileController.php @@ -0,0 +1,67 @@ +<?php +namespace PartKeepr\UploadedFileBundle\Controller; + +use FOS\RestBundle\Controller\Annotations\RequestParam; +use FOS\RestBundle\Controller\Annotations\View; +use Nelmio\ApiDocBundle\Annotation\ApiDoc; +use PartKeepr\ImageBundle\Response\TemporaryImageUploadResponse; +use PartKeepr\UploadedFileBundle\Entity\TempUploadedFile; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; + +class TemporaryFileController extends FileController +{ + /** + * Handles a temporary file upload + * + * @RequestParam(name="url",description="An URL where the file is located") + * @ApiDoc(section="file",output="PartKeepr\UploadedFileBundleBundle\Response\TemporaryFileUploadResponse") + * @View() + * + * @param Request $request The request to process + * + * @return JsonResponse The JSON response from the temporary file upload + * @throws \Exception An exception if neither the userfile form parameter or an URL was given + */ + public function uploadAction(Request $request) + { + $uploadedFile = new TempUploadedFile(); + $fileService = $this->get("partkeepr_uploadedfile_service"); + + if ($request->files->has('userfile') && $request->files->get('userfile') != null) { + $file = $request->files->get('userfile'); + /** + * @var $file UploadedFile + */ + $fileService->replace($uploadedFile, new File($file->getPathname())); + $uploadedFile->setOriginalFilename($file->getClientOriginalName()); + } elseif ($request->request->has("url")) { + $fileService->replaceFromURL($uploadedFile, $request->request->get("url")); + } else { + throw new \Exception("Error: No valid file given"); + } + + $this->getDoctrine()->getManager()->persist($uploadedFile); + $this->getDoctrine()->getManager()->flush(); + + $resource = $this->getResource($request); + $serializedData = $this->get('serializer')->normalize( + $uploadedFile, + 'json-ld', + $resource->getNormalizationContext() + ); + + return new JsonResponse(new TemporaryImageUploadResponse($serializedData)); + } + + + /** + * @inheritdoc + */ + public function getEntityClass() + { + return "PartKeepr\\UploadedFileBunde\\Entity\\TempUploadedFile"; + } +} diff --git a/src/PartKeepr/UploadedFileBundle/Entity/TempUploadedFile.php b/src/PartKeepr/UploadedFileBundle/Entity/TempUploadedFile.php @@ -0,0 +1,19 @@ +<?php +namespace PartKeepr\UploadedFileBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; + +/** + * Represents a temporary file. Temporary files are used when + * a user uploaded a file, but not attached it to an entity. + * + * @ORM\Entity + */ +class TempUploadedFile extends UploadedFile +{ + public function __construct() + { + parent::__construct(); + $this->setType("tempfile"); + } +} diff --git a/src/PartKeepr/UploadedFileBundle/Services/UploadedFileService.php b/src/PartKeepr/UploadedFileBundle/Services/UploadedFileService.php @@ -26,6 +26,17 @@ class UploadedFileService extends ContainerAware * @param UploadedFile $file The target file * @param File $filesystemFile The source file */ + public function replace(UploadedFile $file, File $filesystemFile) + { + $this->replaceFromFilesystem($file, $filesystemFile); + } + + /** + * Replaces the current file with a new file. + * + * @param UploadedFile $file The target file + * @param File $filesystemFile The source file + */ public function replaceFromFilesystem(UploadedFile $file, File $filesystemFile) { $oldFile = $this->getFullPath($file); @@ -100,7 +111,8 @@ class UploadedFileService extends ContainerAware $header[] = "Accept-Language: en-us,en;q=0.5"; $header[] = "Pragma: "; - $browser = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3"; + $browser = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 "; + $browser .= "Ubuntu/8.04 (hardy) Firefox/3.0.3"; curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_USERAGENT, $browser); @@ -144,4 +156,4 @@ class UploadedFileService extends ContainerAware { return $this->container->getParameter("partkeepr.directories.".$file->getType()); } -}- \ No newline at end of file +} diff --git a/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentService.php b/src/backend/PartKeepr/FootprintAttachment/FootprintAttachmentService.php @@ -1,102 +0,0 @@ -<?php -namespace PartKeepr\FootprintAttachment; - -use \PartKeepr\FootprintBundle\Entity\FootprintAttachment, - PartKeepr\UploadedFile\TempUploadedFile, - PartKeepr\Service\RestfulService, - PartKeepr\Service\Service, - PartKeepr\PartKeepr, - \PartKeepr\FootprintBundle\Entity\Footprint, - PartKeepr\Session\SessionManager; - -class FootprintAttachmentService extends Service implements RestfulService { - /** - * (non-PHPdoc) - * @see PartKeepr\Service.RestfulService::get() - */ - public function get () { - if ($this->hasParameter("id")) { - return FootprintAttachmentManager::getInstance()->getFootprintAttachment($this->getParameter("id"))->serialize(); - } else { - if ($this->hasParameter("sort")) { - $tmp = json_decode($this->getParameter("sort"), true); - - $aSortParams = $tmp[0]; - } else { - $aSortParams = array( - "property" => "id", - "direction" => "ASC"); - } - - $filter = ""; - - if ($this->hasParameter("filter")) { - $tmp = json_decode($this->getParameter("filter"), true); - - foreach ($tmp as $item) { - if (array_key_exists("property", $item)) { - if ($item["property"] == "footprint_id") { - if (array_key_exists("value", $item)) { - $filter = $item["value"]; - } - } - } - } - } - return FootprintAttachmentManager::getInstance()->getFootprintAttachments( - $this->getParameter("start", $this->getParameter("start", 0)), - $this->getParameter("limit", $this->getParameter("limit", 25)), - $this->getParameter("sortby", $aSortParams["property"]), - $this->getParameter("dir", $aSortParams["direction"]), - $filter); - } - } - - /** - * (non-PHPdoc) - * @see PartKeepr\Service.RestfulService::create() - */ - public function create () { - $this->requireParameter("tmp_id"); - $this->requireParameter("footprint_id"); - - $tmpImage = TempUploadedFile::loadById($this->getParameter("tmp_id")); - - $file = new FootprintAttachment(); - - $footprint = Footprint::loadById($this->getParameter("footprint_id")); - - $file->setFootprint($footprint); - $file->replace($tmpImage->getFilename()); - $file->setOriginalFilename($tmpImage->getOriginalFilename()); - $file->setDescription($this->getParameter("description")); - PartKeepr::getEM()->persist($file); - PartKeepr::getEM()->flush(); - - return $file->serialize(); - } - - /** - * (non-PHPdoc) - * @see PartKeepr\Service.RestfulService::update() - */ - public function update () { - - } - - /** - * (non-PHPdoc) - * @see PartKeepr\Service.RestfulService::destroy() - */ - public function destroy () { - $this->requireParameter("id"); - - $file = FootprintAttachment::loadById($this->getParameter("id")); - - PartKeepr::getEM()->remove($file); - PartKeepr::getEM()->flush(); - - return array("data" => null); - } - -}- \ No newline at end of file diff --git a/src/backend/PartKeepr/Part/PartManager.php b/src/backend/PartKeepr/Part/PartManager.php @@ -3,7 +3,7 @@ namespace PartKeepr\Part; use PartKeepr\Logger\Logger; -use PartKeepr\UploadedFile\TempUploadedFile, +use PartKeepr\UploadedFileBundle\Entity\TempUploadedFile, PartKeepr\Manager\ManagerFilter, Doctrine\ORM\QueryBuilder, PartKeepr\PartParameter\PartParameter, diff --git a/src/backend/PartKeepr/PartKeepr.php b/src/backend/PartKeepr/PartKeepr.php @@ -189,7 +189,7 @@ class PartKeepr { 'PartKeepr\Image\CachedImage', 'PartKeepr\ImageBundle\Entity\TempImage', - 'PartKeepr\UploadedFile\TempUploadedFile', + 'PartKeepr\UploadedFileBundle\Entity\TempUploadedFile', 'PartKeepr\Statistic\StatisticSnapshot', 'PartKeepr\Statistic\StatisticSnapshotUnit', diff --git a/src/backend/PartKeepr/Printing/PrintingJob/PrintingJob.php b/src/backend/PartKeepr/Printing/PrintingJob/PrintingJob.php @@ -5,7 +5,7 @@ use Doctrine\ORM\Mapping as ORM; use PartKeepr\AuthBundle\Entity\User\User; use PartKeepr\EventNotification\EventManager; use PartKeepr\Session\SessionManager; -use PartKeepr\UploadedFile\TempUploadedFile; +use PartKeepr\UploadedFileBundle\Entity\TempUploadedFile; use PartKeepr\Util\BaseEntity; use PartKeepr\Util\Serializable; diff --git a/src/backend/PartKeepr/Printing/PrintingService.php b/src/backend/PartKeepr/Printing/PrintingService.php @@ -8,7 +8,7 @@ use PartKeepr\Printing\PDFLabelRenderer; use PartKeepr\Printing\PrintingJob\PrintingJob; use PartKeepr\Printing\PrintingJobConfiguration\PrintingJobConfigurationManager; use PartKeepr\Service\Service; -use PartKeepr\UploadedFile\TempUploadedFile; +use PartKeepr\UploadedFileBundle\Entity\TempUploadedFile; /** * This service is the entry point for our printing/exporting diff --git a/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentService.php b/src/backend/PartKeepr/ProjectAttachment/ProjectAttachmentService.php @@ -2,7 +2,7 @@ namespace PartKeepr\ProjectAttachment; use PartKeepr\Project\ProjectAttachment, - PartKeepr\UploadedFile\TempUploadedFile, + PartKeepr\UploadedFileBundle\Entity\TempUploadedFile, PartKeepr\Service\RestfulService, PartKeepr\Service\Service, PartKeepr\PartKeepr, diff --git a/src/backend/PartKeepr/TempFile/TempFileService.php b/src/backend/PartKeepr/TempFile/TempFileService.php @@ -1,105 +0,0 @@ -<?php -namespace PartKeepr\TempFile; - -use PartKeepr\Service\Service; -use PartKeepr\UploadedFile\TempUploadedFile; -use PartKeepr\PartKeepr; - -class TempFileService extends Service { - - /** - * Handles file uploads. - * - * This method can handle one upload per call; the file data needs to be in the "userfile" form variable - OR - be - * passed as "url" parameter, in which case this method will download the remote file. - * - * @return array An array containing the following information: - * - id: The id of the temporary file - * - extension: The extension of the temporary file - * - size: The size of the temporary file - * - originalFilename: The original file name - * @throws \Exception If something went wrong (yes, this needs refactoring!) - * - * @todo Refactoring this method needs to be done - it's bad, but mostly bad due to the bad handling of the $_FILES - * array. Probably some wrapper method would help? - */ - public function upload () { - $tmpFile = new TempUploadedFile(); - - if (array_key_exists("userfile", $_FILES) && array_key_exists("error", $_FILES["userfile"]) && - $_FILES["userfile"]["name"] != "") - { - switch ($_FILES["userfile"]["error"]) { - case 1: - case 2: - throw new \Exception("Uploaded file is too big"); - break; - case 3: - throw new \Exception("File was only partially uploaded. Report this as a bug."); - break; - default: - if (file_exists($_FILES["userfile"]["tmp_name"])) { - $file = $_FILES['userfile']['tmp_name']; - $filename = $_FILES['userfile']['name']; - - $tmpFile->replace($file); - $tmpFile->setOriginalFilename(basename($filename)); - } else { - throw new \Exception(sprintf("Unknown error occurred while uploading the file. Errno %d", $_FILES["userfile"]["error"])); - } - } - - } elseif (array_key_exists("url", $_REQUEST)) { - $tmpFile->replaceFromURL($_REQUEST["url"]); - } else { - throw new \Exception("Error: No valid file given"); - } - - PartKeepr::getEM()->persist($tmpFile); - PartKeepr::getEM()->flush(); - - return array("id" => $tmpFile->getId(), "extension" => $tmpFile->getExtension(), "size" => $tmpFile->getSize(), "originalFilename" => $tmpFile->getOriginalFilename()); - } - - /** - * Receives a file via the service call. - * - * Parameters: - * - filedata: needs to be base64-encoded. - * - filename: The filename - */ - public function jsonUpload () { - $data = base64_decode($this->getParameter("filedata")); - $filename = $this->getParameter("filename"); - - $tempFile = tempnam("/tmp", "PWC"); - file_put_contents($tempFile, $data); - - $tmpFile = new TempUploadedFile(); - $tmpFile->replace($tempFile); - $tmpFile->setOriginalFilename($filename); - - PartKeepr::getEM()->persist($tmpFile); - PartKeepr::getEM()->flush(); - - return $tmpFile->serialize(); - } - - /** - * Processes data via HTTP POST. Reads php://input and creates a temporary image out of it. - */ - public function uploadCam () { - $tempFile = tempnam("/tmp", "PWC") . ".jpg"; - $result = file_put_contents( $tempFile, file_get_contents('php://input') ); - - $image = new TempUploadedFile(); - $image->replace($tempFile); - $image->setOriginalFilename(sprintf(PartKeepr::i18n("Cam photo of %s"), date("Y-m-d H:i:s")).".jpg"); - - PartKeepr::getEM()->persist($image); - PartKeepr::getEM()->flush(); - - return array("id" => $image->getId(), "extension" => $image->getExtension(), "size" => $image->getSize(), "originalFilename" => $image->getOriginalFilename()); - } -} - - \ No newline at end of file diff --git a/src/backend/PartKeepr/UploadedFile/TempUploadedFile.php b/src/backend/PartKeepr/UploadedFile/TempUploadedFile.php @@ -1,18 +0,0 @@ -<?php -namespace PartKeepr\UploadedFile; - -use Doctrine\ORM\Mapping as ORM; -use PartKeepr\UploadedFileBundle\Entity\UploadedFile; - -/** - * Represents a temporary file. Temporary files are used when - * a user uploaded a file, but not attached it to an entity. - * - * @ORM\Entity - */ -class TempUploadedFile extends UploadedFile { - public function __construct () { - parent::__construct(); - $this->setType("Temporary"); - } -}