Skip to content

Commit

Permalink
Authority record digital obj linking, refs #12650
Browse files Browse the repository at this point in the history
Allow authority records to link a single digital object. This
functionality matches the current "Link Digital Object" functionality
currently available for descriptions. This feature includes the ability
to set the alt text for the digital object - the alt text field can be
set on the digital object edit page.

Access control behaves differently from information objects. There are
no PREMIS rules for authorities. Access to these digital objects is
controlled via the existing authority record ACL controls. Editing the
digital object requires authority update permissions etc.

- Must have read privileges to view
- PDF master is always accessible to view as with Descriptions
- Create permission is needed to create an actor
- Update privileges are needed to add or update an actor linked digital object as this is technically updating the actor
- Delete privileges are needed to delete
  • Loading branch information
sbreker committed Feb 15, 2019
1 parent d27c148 commit 77f91b2
Show file tree
Hide file tree
Showing 37 changed files with 556 additions and 105 deletions.
6 changes: 5 additions & 1 deletion apps/qubit/config/routing.yml
Expand Up @@ -46,12 +46,16 @@ add:

# -------------------------------------------------------- </QubitMetadataRoute>

slug/default:
url: /:slug/:module/:action
class: QubitResourceRoute

informationobject/action:
url: /:slug/:action
class: QubitResourceRoute
param:
module: informationobject
action: { pattern: 'addDigitalObject|fileList|multiFileUpload|rename|reports|slugPreview|modifications|calculateDates' }
action: { pattern: 'fileList|multiFileUpload|rename|reports|slugPreview|modifications|calculateDates' }

oai:
url: /;oai
Expand Down
2 changes: 2 additions & 0 deletions apps/qubit/modules/actor/actions/indexAction.class.php
Expand Up @@ -42,5 +42,7 @@ public function execute($request)
$criteria->addJoin(QubitRelation::SUBJECT_ID, QubitFunction::ID);

$this->functions = QubitFunction::get($criteria);

$this->digitalObjectLink = $this->resource->getDigitalObjectLink();
}
}
25 changes: 24 additions & 1 deletion apps/qubit/modules/actor/templates/_searchResult.php
@@ -1,6 +1,26 @@
<?php use_helper('Text') ?>

<article class="search-result">
<?php if (!empty($doc['hasDigitalObject'])): ?>
<article class="search-result has-preview">
<?php else: ?>
<article class="search-result">
<?php endif; ?>

<?php if (!empty($doc['hasDigitalObject'])): ?>
<div class="search-result-preview">
<a href="<?php echo url_for(array('module' => 'actor', 'slug' => $doc['slug'])) ?>">
<div class="preview-container">
<?php if (isset($doc['digitalObject']['thumbnailPath'])): ?>
<?php echo image_tag($doc['digitalObject']['thumbnailPath'],
array('alt' => isset($doc['digitalObject']['digitalObjectAltText']) ? $doc['digitalObject']['digitalObjectAltText'] : truncate_text(strip_markdown(get_search_i18n($doc, 'authorizedFormOfName', array('allowEmpty' => false, 'culture' => $culture))), 100))) ?>
<?php else: ?>
<?php echo image_tag(QubitDigitalObject::getGenericIconPathByMediaTypeId($doc['digitalObject']['mediaTypeId']),
array('alt' => isset($doc['digitalObject']['digitalObjectAltText']) ? $doc['digitalObject']['digitalObjectAltText'] : truncate_text(strip_markdown(get_search_i18n($doc, 'authorizedFormOfName', array('allowEmpty' => false, 'culture' => $culture))), 100))) ?>
<?php endif; ?>
</div>
</a>
</div>
<?php endif; ?>

<div class="search-result-description">

Expand All @@ -24,6 +44,9 @@

</ul>

<?php if (null !== $history = get_search_i18n($doc, 'history', array('culture' => $culture))): ?>
<div class="history"><?php echo render_value($history) ?></div>
<?php endif; ?>
</div>

</article>
20 changes: 15 additions & 5 deletions apps/qubit/modules/digitalobject/actions/deleteAction.class.php
Expand Up @@ -32,8 +32,7 @@ public function execute($request)

$this->resource = $this->getRoute()->resource;

// Get related information object by first grabbing top-level digital
// object
// Get related object by first grabbing top-level digital object
$parent = $this->resource->parent;
if (isset($parent))
{
Expand All @@ -59,16 +58,27 @@ public function execute($request)
// Delete the digital object record from the database
$this->resource->delete();
QubitSearch::getInstance()->update($this->object);
$this->object->updateXmlExports();

// Redirect to edit page for parent Info Object
if ($this->object instanceOf QubitInformationObject)
{
$this->object->updateXmlExports();
}

// Redirect to edit page for parent Object
if (isset($parent))
{
$this->redirect(array($parent, 'module' => 'digitalobject', 'action' => 'edit'));
}
else
{
$this->redirect(array($this->object, 'module' => 'informationobject'));
if ($this->object instanceOf QubitInformationObject)
{
$this->redirect(array($this->object, 'module' => 'informationobject'));
}
else if ($this->object instanceOf QubitActor)
{
$this->redirect(array($this->object, 'module' => 'actor'));
}
}
}
}
Expand Down
29 changes: 23 additions & 6 deletions apps/qubit/modules/digitalobject/actions/editAction.class.php
Expand Up @@ -46,13 +46,16 @@ protected function addFormFields()
// Only display "compound digital object" toggle if we have a child with a
// digital object
$this->showCompoundObjectToggle = false;
foreach ($this->object->getChildren() as $item)
if ($this->object instanceof QubitInformationObject)
{
if (null !== $item->getDigitalObjectRelatedByobjectId())
foreach ($this->object->getChildren() as $item)
{
$this->showCompoundObjectToggle = true;
if (null !== $item->getDigitalObjectRelatedByobjectId())
{
$this->showCompoundObjectToggle = true;

break;
break;
}
}
}

Expand All @@ -75,6 +78,13 @@ protected function addFormFields()
}
}

$this->form->setValidator('digitalObjectAltText', new sfValidatorString);
$this->form->setWidget('digitalObjectAltText', new sfWidgetFormTextarea);
if (null !== $this->digitalObjectAltText = $this->resource->getDigitalObjectAltText())
{
$this->form->setDefault('digitalObjectAltText', $this->digitalObjectAltText);
}

$maxUploadSize = QubitDigitalObject::getMaxUploadSize();

ProjectConfiguration::getActive()->loadHelpers('Qubit');
Expand Down Expand Up @@ -135,7 +145,8 @@ public function execute($request)
$this->object = $this->resource->object;

// Check user authorization
if (!QubitAcl::check($this->object, 'update') && !$this->getUser()->hasGroup(QubitAclGroup::EDITOR_ID))
if (!QubitAcl::check($this->object, 'update') &&
!$this->getUser()->hasGroup(QubitAclGroup::EDITOR_ID))
{
QubitAcl::forwardUnauthorized();
}
Expand All @@ -162,7 +173,11 @@ public function execute($request)
$this->processForm();

$this->resource->save();
$this->object->updateXmlExports();

if ($this->object instanceOf QubitInformationObject)
{
$this->object->updateXmlExports();
}

$this->redirect(array($this->object, 'module' => 'informationobject'));
}
Expand All @@ -179,6 +194,8 @@ public function processForm()
// Set property 'displayAsCompound'
$this->resource->setDisplayAsCompoundObject($this->form->getValue('displayAsCompound'));

$this->resource->setDigitalObjectAltText($this->form->getValue('digitalObjectAltText'));

// Update media type
$this->resource->mediaTypeId = $this->form->getValue('mediaType');

Expand Down
Expand Up @@ -28,15 +28,17 @@ class DigitalObjectMetadataComponent extends sfComponent
{
public function execute($request)
{
$id = $this->infoObj->id;
$id = $this->object->id;
$this->denyFileNameByPremis = false;

// Special case: If all digital object representations are
// denied by premis, we will hide the filename when displaying
// the digital object metadata for security reasons.
// the digital object metadata for security reasons. Only check
// rights for info obj linked digital objects.
if (!QubitGrantedRight::checkPremis($id, 'readThumb') &&
!QubitGrantedRight::checkPremis($id, 'readReference') &&
!QubitGrantedRight::checkPremis($id, 'readMaster'))
!QubitGrantedRight::checkPremis($id, 'readMaster') &&
$this->object instanceOf QubitInformationObject)
{
$this->denyFileNameByPremis = true;
}
Expand All @@ -45,11 +47,11 @@ public function execute($request)
$this->googleMapsApiKey = sfConfig::get('app_google_maps_api_key');

// Provide latitude to template
$latitudeProperty = $this->infoObj->digitalObjectsRelatedByobjectId[0]->getPropertyByName('latitude');
$latitudeProperty = $this->object->digitalObjectsRelatedByobjectId[0]->getPropertyByName('latitude');
$this->latitude = $latitudeProperty->value;

// Provide longitude to template
$longitudeProperty = $this->infoObj->digitalObjectsRelatedByobjectId[0]->getPropertyByName('longitude');
$longitudeProperty = $this->object->digitalObjectsRelatedByobjectId[0]->getPropertyByName('longitude');
$this->longitude = $longitudeProperty->value;
}
}
30 changes: 22 additions & 8 deletions apps/qubit/modules/digitalobject/actions/showComponent.class.php
Expand Up @@ -41,7 +41,11 @@ public function execute($request)
$this->usageType = QubitTerm::THUMBNAIL_ID;
}

if (QubitTerm::MASTER_ID == $this->usageType && !QubitAcl::check($this->resource->object, 'readMaster'))
if ((QubitTerm::MASTER_ID == $this->usageType &&
!QubitAcl::check($this->resource->object, 'readMaster') &&
$this->resource->object instanceOf QubitInformationObject) ||
$this->resource->object instanceOf QubitActor &&
!QubitAcl::check($this->resource->object, 'read'))
{
return sfView::NONE;
}
Expand Down Expand Up @@ -77,15 +81,20 @@ public function execute($request)
private function checkShowGenericIcon()
{
$curUser = sfContext::getInstance()->getUser();
$curInfoObjectId = $this->resource->object->id;
$curObjectId = $this->resource->object->id;

if ($this->resource->object instanceOf QubitActor)
{
return !QubitAcl::check($this->resource->object, 'read');
}

switch ($this->usageType)
{
case QubitTerm::REFERENCE_ID:
// Non-authenticated user: check against PREMIS rules.
if (!$curUser->isAuthenticated() && QubitGrantedRight::hasGrantedRights($curInfoObjectId))
if (!$curUser->isAuthenticated() && QubitGrantedRight::hasGrantedRights($curObjectId))
{
return !QubitGrantedRight::checkPremis($curInfoObjectId, 'readReference');
return !QubitGrantedRight::checkPremis($curObjectId, 'readReference');
}

// Authenticated, check regular ACL rules...
Expand All @@ -102,10 +111,15 @@ private function checkShowGenericIcon()
*/
private function getAccessWarning()
{
$curInfoObjectId = $this->resource->object->id;
$curObjectId = $this->resource->object->id;
$denyReason = '';

if (!QubitGrantedRight::checkPremis($curInfoObjectId, 'readReference', $denyReason) ||
if ($this->resource->object instanceOf QubitActor)
{
return false;
}

if (!QubitGrantedRight::checkPremis($curObjectId, 'readReference', $denyReason) ||
!QubitAcl::check($this->resource->object, 'readReference'))
{
return $denyReason;
Expand All @@ -121,7 +135,7 @@ private function setComponentType()
{
case QubitTerm::IMAGE_ID:

if ($this->resource->showAsCompoundDigitalObject())
if ($this->resource->showAsCompoundDigitalObject() && $this->resource->object instanceOf QubitInformationObject)
{
$this->showComponent = 'showCompound';
}
Expand All @@ -148,7 +162,7 @@ private function setComponentType()

case QubitTerm::TEXT_ID:

if ($this->resource->showAsCompoundDigitalObject())
if ($this->resource->showAsCompoundDigitalObject() && $this->resource->object instanceOf QubitInformationObject)
{
$this->showComponent = 'showCompound';
}
Expand Down
Expand Up @@ -35,6 +35,15 @@ class DigitalObjectShowGenericIconComponent extends sfComponent
public function execute($request)
{
$this->representation = QubitDigitalObject::getGenericRepresentation($this->resource->mimeType, $this->resource->usageId);
$this->canReadMaster = QubitAcl::check($this->resource->object, 'readMaster');

if ($this->resource->object instanceOf QubitInformationObject)
{
$this->canReadMaster = QubitAcl::check($this->resource->object, 'readMaster');
}
else if ($this->resource->object instanceOf QubitActor &&
$this->context->user->isAuthenticated())
{
$this->canReadMaster = QubitAcl::check($this->resource->object, 'read');;
}
}
}
Expand Up @@ -28,7 +28,7 @@ public function execute($request)
$uploadFiles = array();
$warning = null;

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

if (!isset($this->object))
{
Expand Down
Expand Up @@ -45,8 +45,10 @@ public function execute($request)
list($obj, $action) = $this->getObjAndAction();

// Do appropriate ACL check(s). Master copy of text objects are always allowed for reading
// QubitActor does not have a ACL check for readmaster.
if ((!QubitAcl::check($obj, $action) || !QubitGrantedRight::checkPremis($obj->id, $action))
&& !($action == 'readMaster' && $this->resource->mediaTypeId == QubitTerm::TEXT_ID))
&& !($action == 'readMaster' && $this->resource->mediaTypeId == QubitTerm::TEXT_ID)
&& $obj instanceOf QubitInformationObject)
{
$this->forward404();
}
Expand Down
8 changes: 6 additions & 2 deletions apps/qubit/modules/digitalobject/templates/_metadata.php
Expand Up @@ -2,7 +2,11 @@

<section>

<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationObject'), '<h2>'.__('%1% metadata', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))).'</h2>', array($resource, 'module' => 'digitalobject', 'action' => 'edit'), array('title' => __('Edit %1%', array('%1%' => mb_strtolower(sfConfig::get('app_ui_label_digitalobject')))))) ?>
<?php if ($resource->object instanceOf QubitInformationObject): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationobject'), '<h2>'.__('%1% metadata', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))).'</h2>', array($resource, 'module' => 'digitalobject', 'action' => 'edit'), array('title' => __('Edit %1%', array('%1%' => mb_strtolower(sfConfig::get('app_ui_label_digitalobject')))))) ?>
<?php elseif ($resource->object instanceOf QubitActor): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'actor'), '<h2>'.__('%1% metadata', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))).'</h2>', array($resource, 'module' => 'digitalobject', 'action' => 'edit'), array('title' => __('Edit %1%', array('%1%' => mb_strtolower(sfConfig::get('app_ui_label_digitalobject')))))) ?>
<?php endif; ?>

<?php if (sfConfig::get('app_toggleDigitalObjectMap') && is_numeric($latitude) && is_numeric($longitude) && $googleMapsApiKey): ?>
<div id="front-map" class="simple-map" data-key="<?php echo $googleMapsApiKey ?>" data-latitude="<?php echo $latitude ?>" data-longitude="<?php echo $longitude ?>"></div>
Expand Down Expand Up @@ -43,7 +47,7 @@
<?php echo render_show(__('Uploaded'), format_date($resource->createdAt, 'f'), array('fieldLabel' => 'uploaded')) ?>
<?php endif; ?>

<?php if ($sf_user->isAuthenticated()): ?>
<?php if ($sf_user->isAuthenticated() && $resource->object instanceOf QubitInformationObject): ?>
<?php echo render_show(__('Object UUID'), render_value($resource->object->objectUUID), array('fieldLabel' => 'objectUUID')) ?>
<?php echo render_show(__('AIP UUID'), render_value($resource->object->aipUUID), array('fieldLabel' => 'aipUUID')) ?>
<?php echo render_show(__('Format name'), render_value($resource->object->formatName), array('fieldLabel' => 'formatName')) ?>
Expand Down
6 changes: 3 additions & 3 deletions apps/qubit/modules/digitalobject/templates/_showAudio.php
Expand Up @@ -18,14 +18,14 @@

<?php if ($iconOnly): ?>

<?php echo link_to(image_tag('play', array('alt' => __('Open original %1%', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))), $link) ?>
<?php echo link_to(image_tag('play', array('alt' => __($resource->getDigitalObjectAltText() ?: 'Open original %1%', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))), $link) ?>

<?php else: ?>

<div class="resource">

<div class="resourceRep">
<?php echo link_to(image_tag('play', array('alt' => __('Open original %1%', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))), $link) ?>
<?php echo link_to(image_tag('play', array('alt' => __($resource->getDigitalObjectAltText() ?: 'Open original %1%', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))), $link) ?>
</div>

<div class="resourceDesc">
Expand All @@ -40,7 +40,7 @@

<div class="resource">

<?php echo image_tag('play', array('alt' => __('Original %1% not accessible', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))) ?>
<?php echo image_tag('play', array('alt' => __($resource->getDigitalObjectAltText() ?: 'Original %1% not accessible', array('%1%' => sfConfig::get('app_ui_label_digitalobject'))))) ?>

</div>

Expand Down
14 changes: 11 additions & 3 deletions apps/qubit/modules/digitalobject/templates/_showCompound.php
Expand Up @@ -4,16 +4,24 @@
<tr>
<td>
<?php if (null !== $representation = $leftObject->getCompoundRepresentation()): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationObject') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($leftObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php if ($resource->object instanceOf QubitInformationObject): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationObject') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($leftObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php elseif ($resource->object instanceOf QubitActor): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'actor') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($leftObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php endif; ?>
<?php endif; ?>
</td><td>
<?php if (null !== $rightObject && null !== $representation = $rightObject->getCompoundRepresentation()): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationObject') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($rightObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php if ($resource->object instanceOf QubitInformationObject): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'informationObject') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($rightObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php elseif ($resource->object instanceOf QubitActor): ?>
<?php echo link_to_if(SecurityPrivileges::editCredentials($sf_user, 'actor') || QubitTerm::TEXT_ID == $resource->mediaType->id, image_tag($representation->getFullPath(), array('alt' => '')), public_path($rightObject->getFullPath(), array('title' => __('View full size')))) ?>
<?php endif; ?>
<?php endif; ?>
</td>
</tr>

<?php if (SecurityPrivileges::editCredentials($sf_user, 'informationObject')): ?>
<?php if (($resource->object instanceOf QubitInformationObject && SecurityPrivileges::editCredentials($sf_user, 'informationObject')) || ($resource->object instanceOf QubitActor && SecurityPrivileges::editCredentials($sf_user, 'actor'))): ?>
<tr>
<td colspan="2" class="download_link">
<?php echo link_to(__('Download %1%', array('%1%' => $resource)), public_path($resource->getFullPath()), array('class' => 'download')) ?>
Expand Down

0 comments on commit 77f91b2

Please sign in to comment.