Development Uploader

From Cloudrexx Development Wiki
Jump to: navigation, search

About the new uploader

The new uploader modal

Meet the new uploader: he's built with Angularjs and comes in a nice modal window with drag and drop support for uploading files. You can even specify how many files the user can upload and what size they should be.

This article deprecates the old documentation (Development_Uploader_pre_5.0) as from now on only this one should be used.


Getting started with the new uploader

To initialize the uploader create a new instance of \Cx\Core_Modules\Uploader\Model\Entity\Uploader in your code which gets called when the page is built. This should normally be the Frontend- or BackendController.

For our simple example we use the DefaultUploadCallback class which just uploads the files into the /image/content folder of your cloudrexx installation.

With the method getXHtml you can get the needed html code for the uploader button. You can then use this in combination with the Sigma template to add the button somewhere in your template, by calling the setVariable method like shown below.

For the example below to work you have to have a placeholder with the name UPLOADER_CODE in your template, else the uploader won't be visible.


Code for BackendController.class.php:parsePage

public function parsePage(\Cx\Core\Html\Sigma $template, array $cmd)
{
        $uploader = new \Cx\Core_Modules\Uploader\Model\Entity\Uploader();
        $uploader->setFinishedCallback(
            '\Cx\Core_Modules\Uploader\Model\DefaultUploadCallback'
        );
        $template->setVariable(
            'UPLOADER_CODE', $uploader->getXHtml('Open Uploader') //The first parameter is the name of the button
        );
 }

Code for View/Template/Backend/Default.html

{UPLOADER_CODE}

Advanced Usage

The description for all options is described below.

PHP callback

To specify a callback you can provide a class which implements the \Cx\Core_Modules\Uploader\Model\UploadCallbackInterface

$uploader->setFinishedCallback(
    '\Cx\Core_Modules\Uploader\Model\DefaultUploadCallback'
);

When the upload is finished the uploader will call the uploadFinished method of the class with the specified arguments in the UploadCallbackInterface class.

/**
 * @param $tempPath String Path to the temporary directory containing the files at this moment.
 * @param $tempWebPath String Points to the same folder as tempPath, but relative to the webroot.
 * @param $data String Data given to setData() when creating the uploader.
 * @param $uploadId integer Per-session unique id for the current upload.
 * @param $fileInfos array('originalFileNames' => array( 'theCurrentAndCleanedFilename.txt' => 'raw!Source#Filename.txt' ) )
 *
 * @return mixed The return value can be an array as shown in the example or null.
 *               When returning an array, all files left in the temporary directory are moved accordingly.
 *               When returning null, all left files are deleted.
 */
function uploadFinished($tempPath, $tempWebPath, $data, $uploadId, $fileInfos, $response);

You can find a example for a callback in the \Cx\Core_Modules\Uploader\Model\DefaultUploadCallback class. The uploader injects the \Cx\Core\Core\Controller\Cx instance as a first parameter in the contructor so we don't have to use singeltons or global objects.

The method uploadFinished should return an array with the location where the uploaded file should be moved.


Javascript callback

The uploader will call a specified javascript callback after the upload has finished and the user has closed the uploader modal. The function should be available from the global window context. This function will also be called with an empty array if the user hasn't uploaded anything.

$uploader->setCallback('gallery.afterUpload'); //Function attached to window which gets called when the upload window is closed after an successful upload.
window.gallery = {
    afterUpload: function(files){
         // The files array contains all uploaded files
    }
}

The first parameter is the array with the uploaded files.

["/images/content/Screenshot-from-2014-10-01-114138.png", 
"/images/content/Screenshot-from-2014-10-01-153505.png", 
"/images/content/Screenshot-from-2014-10-01-162041.png",
"/images/content/Screenshot-from-2014-10-03-134226.png"]

Add more html attributes

With the setOptions method you can set html attributes.

$uploader->setOptions( //Set html attributes for styling or javascript.
    array(
        'id' => 'page_target_browse',
        'type' => 'button'
    )
);

Specify how many files the user can upload

You can specify how many files the user can upload by using the method setUploadLimit.

$uploader->setUploadLimit(1);

Specify a maxmium file size limit

To set a maximum file size limit you can use the setMaxFileSize method. The method accepts numeric or formatted string values, e.g.: 204800 or "204800b" or "200kb".

$uploader->setMaxFileSize('10mb');

Create a inline uploader

To create a inline uploader you have to use the setType method.

$uploader->setType(\Cx\Core_Modules\Uploader\Model\Entity\Uploader::UPLOADER_TYPE_INLINE);

Add data for the callback to the uploader

If you need data like a id for the callback you can add this data with the setData method of the uploader.

$uploader->setData(array('foo' => 'bar');

The data is then available as the $data argument in the callback method.

function uploadFinished($tempPath, $tempWebPath, $data, $uploadId, $fileInfos, $response){
   var_dump($data) //=> array(1) { ["foor"]=> string(3) "bar" }
}

Add class to uploader button

If you need a additional class for the uploader button you can use the addClass method of the uploader.

$uploader->addClass('fancy-button');

Get the uploader code

Finally with the getXHtml method you can get the html necessary to create the uploader button. The first argument is the button name.

$template->setVariable(
    'UPLOADER_CODE', $uploader->getXHtml('Open Uploader') //The first parameter is the name of the button
);


Legacy callback

If you want to migrate an old module to the new uploader you can still use your old callback:

$uploader->setFinishedCallback(array('/Gallery/Controller/GalleryManager.class.php', '\Cx\Modules\Gallery\Controller\GalleryManager', 'uploadFinished')); Working legacy example


Example:

function uploadFinished(
       $tempPath, $tempWebPath, $data, $uploadId, $fileInfos
) {
    return array(
        $this->cx->getWebsiteImagesContentPath(),
        $this->cx->getWebsiteImagesContentWebPath()
    );
}


Migrating from the old uploader

First we have to remove all the calls to the old uploader:

/**
 * Name of the upload instance
 */
$uploaderInstanceName = 'exposed_combo_uploader';
$uploaderWidgetName = 'uploadWidget';
/**
 * jQuery selector of the HTML-element where the upload folder-widget shall be put in
 */
$uploaderFolderWidgetContainer = '#uploadFormField_uploadWidget';
$uploader = \Cx\Core_Modules\Upload\Controller\UploadFactory::getInstance()->newUploader('exposedCombo');

And replace them with the instance of the new uploader:

$uploader = new \Cx\Core_Modules\Uploader\Model\Entity\Uploader();

Then we can migrate the callback to the new uploader. The name of the method is the same for the new and old uploader, so if your new uploader instance is created with the same name ($uploader) you can leave it as it is.

$uploader->setFinishedCallback(array('/Gallery/Controller/GalleryManager.class.php', '\Cx\Modules\Gallery\Controller\GalleryManager', 'uploadFinished')); Working legacy example

Migrating a folder widget associated with the uploader

If you also have a folder widget displaying the files which the user has uploaded you have to migrate this too.

Replace the following code with the new folder widget instance.

$folderWidget = $f->newFolderWidget($tup[0].'/'.$tup[2]);

New code for folder widget instance.

$folderWidget = new \Cx\Core_Modules\MediaBrowser\Model\Entity\FolderWidget($pathToFolder);

To place the folder widget html in the template you can use the getXHtml method.

$template->setVariable(array(
    'FOLDER_WIDGET_CODE' => $folderWidget->getXHtml(),
));

Refresh the folder widget when uploading new files

If you need to refresh the folder widget after you've uploaded a new file you can use the following code:

$uploader->setCallback('JsCallback');
$javascript = "
<script type=\"text/javascript\">
function JsCallback(callback) {
        angular.element('#mediaBrowserfolderWidget_{$folderWidget->getId()}').scope().refreshBrowser();
}
</script>";