Skip to content

Commit

Permalink
Replace Flash upload with Uppy, refs #13319
Browse files Browse the repository at this point in the history
This commit removes the YAHOO.widget.Uploader SFW Flash library. The
mulitupload window now uses Uppy.io to achieve equivalent functionality.

- Uppy UI strings will be available for translation in Weblate.
- Uppy will respect AtoM's file size limits.
- Includes bulk title update screen.
  • Loading branch information
sbreker committed Mar 18, 2021
1 parent 2c4c700 commit 136f816
Show file tree
Hide file tree
Showing 18 changed files with 17,353 additions and 443 deletions.
6 changes: 6 additions & 0 deletions COPYRIGHT
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,9 @@ Parsedown Extra
Url: https://github.com/erusev/parsedown-extra
Copyright: Emanuil Rusev, erusev.com
License: MIT

Uppy
----
Url: https://github.com/transloadit/uppy
Copyright: 2019 Transloadit (https://transloadit.com)
License: MIT
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ public function execute($request)
// Set up display of video in mediaelement
if ($this->representation)
{
$this->showFlashPlayer = true;
$this->showMediaPlayer = true;

$this->response->addJavaScript('/vendor/mediaelement/mediaelement-and-player.min.js', 'last');
$this->response->addJavaScript('mediaelement', 'last');
$this->response->addStyleSheet('/vendor/mediaelement/mediaelementplayer.min.css');
}
else
{
$this->showFlashPlayer = false;
$this->showMediaPlayer = false;

$this->representation = QubitDigitalObject::getGenericRepresentation($this->resource->mimeType, $this->usageType);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function execute($request)

// If this is a reference movie, get the thumbnail representation for the
// place holder image
$this->showFlashPlayer = true;
$this->showMediaPlayer = true;
if (QubitTerm::REFERENCE_ID == $this->usageType)
{
$this->thumbnail = $this->resource->getRepresentationByUsage(QubitTerm::THUMBNAIL_ID);
Expand All @@ -66,7 +66,7 @@ public function execute($request)
// If representation is not a valid digital object, return a generic icon
else
{
$this->showFlashPlayer = false;
$this->showMediaPlayer = false;
$this->representation = QubitDigitalObject::getGenericRepresentation($this->resource->mimeType, $this->usageType);
}
}
Expand Down
37 changes: 1 addition & 36 deletions apps/qubit/modules/digitalobject/actions/uploadAction.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function execute($request)
$uploadFiles = array();
$warning = null;

$this->object = QubitObject::getById($request->objectId);
$this->object = QubitObject::getBySlug($request->parentSlug);

if (!isset($this->object))
{
Expand Down Expand Up @@ -91,45 +91,10 @@ public function execute($request)
$tmpFileName = basename($tmpFilePath);
$tmpFileMimeType = QubitDigitalObject::deriveMimeType($tmpFileName);

// Thumbnail name and path
$thumbName = pathinfo('THUMB'. $tmpFileName, PATHINFO_FILENAME) .".jpg";
$thumbPath = dirname($tmpFilePath) ."/". $thumbName;

if ($canThumbnail = QubitDigitalObject::canThumbnailMimeType($tmpFileMimeType) || QubitDigitalObject::isVideoFile($tmpFilePath))
{
if (QubitDigitalObject::isImageFile($tmpFilePath) || 'application/pdf' == $tmpFileMimeType)
{
$resizedObject = QubitDigitalObject::resizeImage($tmpFilePath, 150, 150);
}
else if (QubitDigitalObject::isVideoFile($tmpFilePath))
{
$resizedObject = QubitDigitalObject::createThumbnailFromVideo($tmpFilePath, 150, 150);
}

if (0 < strlen($resizedObject))
{
file_put_contents($thumbPath, $resizedObject);
chmod($thumbPath, 0644);
}

// Show a warning message if object couldn't be thumbnailed when it is
// supposed to be possible
if (!file_exists($thumbPath) && 0 >= filesize($thumbPath))
{
$warning = $this->context->i18n->__('File %1% could not be thumbnailed', array('%1%' => $file['name']));
}
}
else
{
$thumbName = '../../images/'.QubitDigitalObject::getGenericIconPath($tmpFileMimeType, QubitTerm::THUMBNAIL_ID);
}

$uploadFiles = array(
'canThumbnail' => $canThumbnail,
'name' => $file['name'],
'md5sum' => md5_file($tmpFilePath),
'size' => hr_filesize($file['size']),
'thumb' => $thumbName,
'tmpName' => $tmpFileName,
'warning' => $warning);

Expand Down
2 changes: 1 addition & 1 deletion apps/qubit/modules/digitalobject/templates/_showAudio.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<?php if (QubitTerm::REFERENCE_ID == $usageType): ?>

<?php if ($showFlashPlayer): ?>
<?php if ($showMediaPlayer): ?>
<audio class="mediaelement-player" src="<?php echo public_path($representation->getFullPath()) ?>"></audio>
<?php else: ?>
<div style="text-align: center">
Expand Down
2 changes: 1 addition & 1 deletion apps/qubit/modules/digitalobject/templates/_showVideo.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<?php elseif ($usageType == QubitTerm::REFERENCE_ID): ?>

<?php if ($showFlashPlayer): ?>
<?php if ($showMediaPlayer): ?>
<video preload="metadata" class="mediaelement-player" src="<?php echo public_path($representation->getFullPath()) ?>"></video>
<?php else: ?>
<div style="text-align: center">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

/*
* This file is part of the Access to Memory (AtoM) software.
*
* Access to Memory (AtoM) is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Access to Memory (AtoM) 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 Access to Memory (AtoM). If not, see <http://www.gnu.org/licenses/>.
*/

class InformationObjectMultiFileUpdateAction extends sfAction
{
protected $informationObjectList = array();
protected $informationObjectOrignalTitles = array();

public function execute($request)
{
$this->resource = $this->getRoute()->resource;

// Check user authorization
if (!QubitAcl::check($this->resource, 'update'))
{
QubitAcl::forwardUnauthorized();
}

// Check that object exists and that it is not the root
if (!isset($this->resource) || !isset($this->resource->parent))
{
$this->forward404();
}

if (isset($request->items))
{
if (false === $this->items = explode(",", $request->items))
{
$this->forward404();
}

foreach ($this->items as $slug)
{
if (null !== $io = QubitInformationObject::getBySlug($slug))
{
if (!QubitAcl::check($io, 'update'))
{
continue;
}

// Child IOs should not be root and should be direct descendants of resource.
if (!isset($io->parent) || $io->parentId !== $this->resource->id)
{
continue;
}

$this->informationObjectList[$slug] = $io;
$this->informationObjectOrignalTitles[$slug] = $io->title;
}
else
{
continue;
}
}
}

$this->digitalObjectTitleForm = new DigitalObjectTitleUpdateForm(array(),
array('informationObjects' => $this->informationObjectList));

// Handle POST data (form submit)
if ($request->isMethod('post'))
{
$this->digitalObjectTitleForm->bind($request->titles);

if ($this->digitalObjectTitleForm->isValid())
{
$this->updateDigitalObjectTitles();
$this->redirect(array($this->resource, 'module' => 'informationobject'));
}
}

$this->populateDigitalObjectTitleForm();
}

/**
* Populate the ui_label form with database values (localized)
*/
protected function populateDigitalObjectTitleForm()
{
foreach ($this->digitalObjectTitleForm->getInformationObjects() as $io)
{
$this->digitalObjectTitleForm->setDefault($io->id, $io->getTitle(array('cultureFallback' => true)));
}
}

/**
* Update ui_label db values with form values (localized)
*
* @return $this
*/
protected function updateDigitalObjectTitles()
{
foreach ($this->digitalObjectTitleForm->getInformationObjects() as $informationObject)
{
if (null !== $title = $this->digitalObjectTitleForm->getValue($informationObject->id))
{
// Test if title changed.
if ($this->informationObjectOrignalTitles[$informationObject->id] !== $title)
{
$informationObject->title = $title;
$informationObject->save();
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,11 @@ public function execute($request)
QubitAcl::forwardToSecureAction();
}

// Add javascript libraries
$this->response->addJavaScript('/vendor/yui/logger/logger', 'last');
$this->response->addJavaScript('/vendor/yui/uploader/uploader-min', 'last');
$this->response->addJavaScript('multiFileUpload', 'last');

// Get max upload size limits
$this->maxUploadSize = QubitDigitalObject::getMaxUploadSize();
$this->maxFileSize = QubitDigitalObject::getMaxUploadSize();
$this->maxPostSize = QubitDigitalObject::getMaxPostSize();

// Paths for uploader javascript
$this->uploadSwfPath = "{$this->request->getRelativeUrlRoot()}/vendor/yui/uploader/assets/uploader.swf";
$this->uploadResponsePath = "{$this->context->routing->generate(null, array('module' => 'digitalobject', 'action' => 'upload'))}?".http_build_query(array(session_name() => session_id()));
$this->uploadTmpDir = "{$this->request->getRelativeUrlRoot()}/uploads/tmp";

Expand Down Expand Up @@ -90,6 +85,7 @@ public function processForm()

// Upload files
$i = 0;
$informationObjectSlugList = array();

foreach ($this->form->getValue('files') as $file)
{
Expand Down Expand Up @@ -131,19 +127,15 @@ public function processForm()
$digitalObject->save();
}

$thumbnailIsGeneric = (bool) strstr($file['thumb'], 'generic-icons');
$informationObjectSlugList[] = $informationObject->slug;

// Clean up temp files
if (file_exists("$tmpPath/$file[tmpName]"))
{
unlink("$tmpPath/$file[tmpName]");
}
if (!$thumbnailIsGeneric && file_exists("$tmpPath/$file[thumb]"))
{
unlink("$tmpPath/$file[thumb]");
}
}

$this->redirect(array($this->resource, 'module' => 'informationobject'));
$this->redirect(array($this->resource, 'module' => 'informationobject', 'action' => 'multiFileUpdate', 'items' => implode(",", $informationObjectSlugList)));
}
}
9 changes: 9 additions & 0 deletions apps/qubit/modules/informationobject/config/view.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ physicalObjects:
/plugins/sfDrupalPlugin/vendor/drupal/misc/tableheader:

multiFileUploadSuccess:
stylesheets:
/vendor/uppy/uppy-bundle.css:
javascripts:
/vendor/uppy/uppy-bundle.js:
multiFileUpload:
/plugins/sfDrupalPlugin/vendor/drupal/misc/collapse:
/plugins/sfDrupalPlugin/vendor/drupal/misc/form:
description:
Expand All @@ -26,6 +30,11 @@ storageLocationsSuccess:
stylesheets:
print-reports: { media: screen, position: last }

multiFileUpdateSuccess:
javascripts:
/plugins/sfDrupalPlugin/vendor/drupal/misc/collapse:
/plugins/sfDrupalPlugin/vendor/drupal/misc/form:

renameSuccess:
javascripts:
/plugins/sfDrupalPlugin/vendor/drupal/misc/collapse:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php decorate_with('layout_1col.php') ?>

<?php slot('title') ?>
<h1 class="multiline">
<?php echo __('Update digital object titles') ?>
<span class="sub"><?php echo render_title(new sfIsadPlugin($resource)) ?> </span>
</h1>
<?php end_slot() ?>

<?php slot('content') ?>

<?php echo $digitalObjectTitleForm->renderGlobalErrors() ?>
<?php echo $digitalObjectTitleForm->renderFormTag(url_for(array($resource, 'module' => 'informationobject', 'action' => 'multiFileUpdate', 'items' => $sf_request->items)), array('method' => 'post', 'id' => 'bulk-title-update-form')) ?>
<?php echo $digitalObjectTitleForm->renderHiddenFields() ?>

<div id="content">

<table class="table sticky-enabled">
<thead>
<tr>
<th><?php echo __('Object')?></th>
<th><?php echo __('Title')?></th>
</tr>
</thead>
<tbody>
<?php foreach ($digitalObjectTitleForm->getInformationObjects() as $io): ?>
<tr>
<td class="thumbnail-container">
<?php foreach ($io->digitalObjectsRelatedByobjectId as $do): ?>
<?php if (
(null !== $thumbnail = $do->getRepresentationByUsage(QubitTerm::THUMBNAIL_ID))
&& QubitAcl::check($io, 'readThumbnail')
): ?>
<?php echo image_tag($thumbnail->getFullPath(), array('alt' => __($do->getDigitalObjectAltText() ?: 'Original %1% not accessible', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))) ?>
<?php else: ?>
<?php echo image_tag(QubitDigitalObject::getGenericIconPathByMediaTypeId($do->mediaTypeId), array('alt' => __($do->getDigitalObjectAltText() ?: 'Original %1% not accessible', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))) ?>
<?php endif; ?>
<?php endforeach; ?>
</td>
<td>
<?php if ($sf_user->getCulture() != $io->getSourceCulture() && !strlen($io->title)): ?>
<div class="default-translation">
<?php echo render_value($digitalObjectTitleForm[$io->id]->getValue(), $io) ?>
</div>
<?php endif; ?>

<?php echo $digitalObjectTitleForm[$io->id]
->label(__('Title')) ?>
<?php echo __($io->digitalObjectsRelatedByobjectId[0]->name) ?>
<?php echo render_show(__('Level of description'), render_value_inline($io->levelOfDescription)) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

<section class="actions">
<ul>
<li><input class="c-btn c-btn-submit" id="rename-form-submit" type="submit" value="<?php echo __('Save') ?>"/></li>
</ul>
</section>
</form>

<?php end_slot() ?>
Loading

0 comments on commit 136f816

Please sign in to comment.