Skip to content

Commit

Permalink
Add identifier mask for descriptions, refs #11162
Browse files Browse the repository at this point in the history
This PR implements a similar feature to our existing accession mask settings,
except for archival descriptions' identifiers instead.

Feature details:

- New admin->settings fields for identifier mask, identifier counter, and
  identifier mask enable / disable.

- If identifier mask is enabled, when creating new descriptions the identifier
  will automatically fill in an auto-generated identifier in the form for the
  user, based on the mask & counter.

- There will be a button underneath the identifier text box when editing that
  will use an XHR to manually generate an identifier from an end point and fill
  the box in.

- In the identifier mask (like accession mask), %<letter> indicates the
  identifier generation should interpret this with strftime. #i should be
  interpreted as the place to insert the current counter value.

- If the user edits the identifier either during the creation process if
  identifier mask is enabled, or after the user clicks generate identifier
  manually, the counter will not be incremented.
  • Loading branch information
Mike Gale committed May 18, 2017
1 parent 18f9a78 commit b1e82cd
Show file tree
Hide file tree
Showing 21 changed files with 322 additions and 9 deletions.
Expand Up @@ -138,7 +138,7 @@ protected function earlyExecute()
$this->parent = QubitInformationObject::getById(QubitInformationObject::ROOT_ID);
$this->form->setDefault('parent', $this->context->routing->generate(null, array($this->parent, 'module' => 'informationobject')));
}

if (isset($getParams['repository']))
{
$this->resource->repository = QubitRepository::getById($this->request->repository);
Expand All @@ -156,6 +156,9 @@ protected function earlyExecute()
{
$this->publicationStatusId = sfConfig::get('app_defaultPubStatus', QubitTerm::PUBLICATION_STATUS_DRAFT_ID);
}

// If creating new description and identifier mask is set to on, auto-generate next identifier.
$this->handleIdentifierFromMask();
}
}

Expand Down Expand Up @@ -597,6 +600,7 @@ protected function processForm()
$this->deleteNotes();
$this->updateChildLevels();
$this->removeDuplicateRepositoryAssociations();
$this->incrementMaskCounter();
}

public function execute($request)
Expand Down Expand Up @@ -783,4 +787,33 @@ protected function updateChildLevels()
}
}
}

/**
* If identifier mask is enabled, set our new info obj to an identifier generated
* from the mask.
*/
private function handleIdentifierFromMask()
{
// Pass if we're using mask or not to template, fill in identifier with generated
// identifier if so.
if ($this->mask = sfConfig::get('app_identifier_mask_enabled', 0))
{
$this->resource->identifier = QubitInformationObject::generateIdentiferFromMask();
}
}

/**
* If the user is using an identifier generated from the mask, increment the mask counter.
*/
private function incrementMaskCounter()
{
if (!filter_var($this->request->getPostParameter('usingMask'), FILTER_VALIDATE_BOOLEAN))
{
return;
}

$counter = QubitInformationObject::getIdentifierCounter();
$counter->value++;
$counter->save();
}
}
@@ -0,0 +1,29 @@
<?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 InformationObjectGenerateIdentifierAction extends sfAction
{
public function execute($request)
{
$identifier = QubitInformationObject::generateIdentiferFromMask();
$this->response->setHttpHeader('Content-Type', 'application/json; charset=utf-8');

return $this->renderText(json_encode(array('identifier' => $identifier)));
}
}
@@ -1,7 +1,3 @@
<div class="section">
<a href="#" id="alternative-identifiers">Add alternative identifier(s)</a>
</div>

<div class="section" id="alternative-identifiers-table"<?php echo 0 < count($alternativeIdentifiers) ? '' : 'style="display:none"' ?>>

<h3><?php echo __('Alternative identifier(s)') ?></h3>
Expand Down
@@ -0,0 +1,14 @@
<div class="section">
<?php if (!isset($hideAltIdButton)): // Some templates don't have alt id support yet ?>
<a href="#" class="identifier-action" id="alternative-identifiers">
<?php echo __('Add alternative identifier(s)') ?>
</a>
<?php endif; ?>

<a href="#" class="identifier-action" id="generate-identifier"
data-generate-identifier-url="<?php echo url_for(array('module' => 'informationobject', 'action' => 'generateIdentifier')) ?>">
<?php echo __('Generate identifier') ?>
</a>
</div>

<input name="usingMask" id="using-identifier-mask" type="hidden" value="<?php echo $mask ?>"/>
42 changes: 41 additions & 1 deletion apps/qubit/modules/settings/actions/globalAction.class.php
Expand Up @@ -77,6 +77,9 @@ protected function populateGlobalForm()
$accessionMaskEnabled = QubitSetting::getByName('accession_mask_enabled');
$accessionMask = QubitSetting::getByName('accession_mask');
$accessionCounter = QubitSetting::getByName('accession_counter');
$identifierMaskEnabled = QubitSetting::getByName('identifier_mask_enabled');
$identifierMask = QubitSetting::getByName('identifier_mask');
$identifierCounter = QubitSetting::getByName('identifier_counter');
$separatorCharacter = QubitSetting::getByName('separator_character');
$inheritCodeInformationObject = QubitSetting::getByName('inherit_code_informationobject');
$sortBrowserUser = QubitSetting::getByName('sort_browser_user');
Expand Down Expand Up @@ -105,6 +108,9 @@ protected function populateGlobalForm()
'accession_mask_enabled' => (isset($accessionMaskEnabled)) ? intval($accessionMaskEnabled->getValue(array('sourceCulture'=>true))) : 1,
'accession_mask' => (isset($accessionMask)) ? $accessionMask->getValue(array('sourceCulture'=>true)) : null,
'accession_counter' => (isset($accessionCounter)) ? intval($accessionCounter->getValue(array('sourceCulture'=>true))) : 1,
'identifier_mask_enabled' => (isset($identifierMaskEnabled)) ? intval($identifierMaskEnabled->getValue(array('sourceCulture'=>true))) : 1,
'identifier_mask' => (isset($identifierMask)) ? $identifierMask->getValue(array('sourceCulture'=>true)) : null,
'identifier_counter' => (isset($identifierCounter)) ? intval($identifierCounter->getValue(array('sourceCulture'=>true))) : 1,
'separator_character' => (isset($separatorCharacter)) ? $separatorCharacter->getValue(array('sourceCulture'=>true)) : null,
'inherit_code_informationobject' => (isset($inheritCodeInformationObject)) ? intval($inheritCodeInformationObject->getValue(array('sourceCulture'=>true))) : 1,
'sort_browser_user' => (isset($sortBrowserUser)) ? $sortBrowserUser->getValue(array('sourceCulture'=>true)) : 0,
Expand Down Expand Up @@ -203,7 +209,7 @@ protected function updateGlobalSettings()
// Accession counter
if (null !== $accessionCounter = $thisForm->getValue('accession_counter'))
{
if (ctype_digit($accessionCounter) && $accessionCounter > -1)
if (ctype_digit($accessionCounter))
{
$setting = QubitSetting::getByName('accession_counter');

Expand All @@ -213,6 +219,40 @@ protected function updateGlobalSettings()
}
}

// Identifier mask enabled
if (null !== $identifierMaskEnabled = $thisForm->getValue('identifier_mask_enabled'))
{
if (null !== $setting = QubitSetting::getByName('identifier_mask_enabled'))
{
// Force sourceCulture update to prevent discrepency in settings between cultures
$setting->setValue($identifierMaskEnabled, array('sourceCulture' => true));
$setting->save();
}
}

// Identifier mask
if (null !== $identifierMask = $thisForm->getValue('identifier_mask'))
{
$setting = QubitSetting::getByName('identifier_mask');

// Force sourceCulture update to prevent discrepency in settings between cultures
$setting->setValue($identifierMask, array('sourceCulture' => true));
$setting->save();
}

// Identifier counter
if (null !== $identifierCounter = $thisForm->getValue('identifier_counter'))
{
if (ctype_digit($identifierCounter))
{
$setting = QubitSetting::getByName('identifier_counter');

// Force sourceCulture update to prevent discrepency in settings between cultures
$setting->setValue($identifierCounter, array('sourceCulture' => true));
$setting->save();
}
}

// Separator character
if (null !== $separatorCharacter = $thisForm->getValue('separator_character'))
{
Expand Down
23 changes: 22 additions & 1 deletion data/fixtures/settings.yml
Expand Up @@ -3,7 +3,7 @@ QubitSetting:
name: version
editable: 0
deleteable: 0
value: 153
value: 154
milestone:
name: milestone
editable: 0
Expand Down Expand Up @@ -1089,3 +1089,24 @@ QubitSetting:
source_culture: en
value:
en: 0
Qubit_Settings_identifierMask:
name: identifier_mask
editable: 1
deleteable: 0
source_culture: en
value:
en: %Y-%m-%d/#i
Qubit_Settings_identifierCounter:
name: identifier_counter
editable: 1
deleteable: 0
source_culture: en
value:
en: 0
Qubit_Settings_identifierMaskEnabled:
name: identifier_mask_enabled
editable: 1
deleteable: 0
source_culture: en
value:
en: 0
55 changes: 55 additions & 0 deletions js/generateIdentifier.js
@@ -0,0 +1,55 @@
(function ($) {

'use strict';

var GenerateIdentifier = function ()
{
this.$generateIdentifierBtn = $('#generate-identifier');
this.$identifier = $('#identifier');
this.$maskEnabled = $('#using-identifier-mask');
this.init();
};

GenerateIdentifier.prototype = {

constructor: GenerateIdentifier,

init: function()
{
this.$generateIdentifierBtn.on('click', $.proxy(this.genIdentifier, this));
this.$identifier.on('input', $.proxy(this.identifierChanged, this));
},

genIdentifier: function(event)
{
var identifier = this.$identifier;
var maskEnabled = this.$maskEnabled;
event.preventDefault(); // Prevent page from jumping to top when clicking href="#"

// Return deferred object
return $.ajax({
url: this.$generateIdentifierBtn.data('generate-identifier-url'),
type: 'GET',
success: function (data)
{
identifier.val(data['identifier']);
// Freshly generated identifier, using mask!
maskEnabled.attr('value', '1');
}
});
},

// If user changes identifier manually, we're no longer using an auto-generated
// identifier from the mask, so do not increment counter. Using-mask will signal
// to the action whether or not to increment the counter.
identifierChanged: function(event)
{
this.$maskEnabled.attr('value', '0');
}
};

$(function ()
{
new GenerateIdentifier();
});
})(jQuery);
9 changes: 9 additions & 0 deletions lib/form/SettingsGlobalForm.class.php
Expand Up @@ -46,6 +46,9 @@ public function configure()
'accession_mask_enabled' => new sfWidgetFormSelectRadio(array('choices' => array(1 => 'yes', 0 => 'no')), array('class' => 'radio')),
'accession_mask' => new sfWidgetFormInput,
'accession_counter' => new sfWidgetFormInput,
'identifier_mask_enabled' => new sfWidgetFormSelectRadio(array('choices' => array(1 => 'yes', 0 => 'no')), array('class' => 'radio')),
'identifier_mask' => new sfWidgetFormInput,
'identifier_counter' => new sfWidgetFormInput,
'separator_character' => new sfWidgetFormInput(array(), array('maxlength' => 1)),
'inherit_code_informationobject' => new sfWidgetFormSelectRadio(array('choices' => array(1 => 'yes', 0 => 'no')), array('class' => 'radio')),
'sort_browser_user' => new sfWidgetFormSelectRadio(array('choices' => array('alphabetic' => 'alphabetic', 'lastUpdated' => 'last updated', 'identifier' => 'identifier', 'referenceCode' => $this->i18n->__('reference code'))), array('class' => 'radio')),
Expand Down Expand Up @@ -76,6 +79,9 @@ public function configure()
'accession_mask_enabled' => $this->i18n->__('Accession mask enabled'),
'accession_mask' => $this->i18n->__('Accession mask'),
'accession_counter' => $this->i18n->__('Accession counter'),
'identifier_mask_enabled' => $this->i18n->__('Identifier mask enabled'),
'identifier_mask' => $this->i18n->__('Identifier mask'),
'identifier_counter' => $this->i18n->__('Identifier counter'),
'separator_character' => $this->i18n->__('Reference code separator'),
'inherit_code_informationobject' => $this->i18n->__('Inherit reference code (information object)'),
'sort_browser_user' => $this->i18n->__('Sort browser (users)'),
Expand Down Expand Up @@ -163,6 +169,9 @@ public function configure()
$this->validatorSchema['default_repository_browse_view'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['default_archival_description_browse_view'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['slug_basis_informationobject'] = $this->getSlugBasisInformationObjectValidator();
$this->validatorSchema['identifier_mask_enabled'] = new sfValidatorInteger(array('required' => false));
$this->validatorSchema['identifier_mask'] = new sfValidatorString(array('required' => false));
$this->validatorSchema['identifier_counter'] = new sfValidatorString(array('required' => false));

$this->validatorSchema['repository_quota'] = new sfValidatorNumber(
array('required' => true, 'min' => -1),
Expand Down
42 changes: 42 additions & 0 deletions lib/model/QubitInformationObject.php
Expand Up @@ -3317,4 +3317,46 @@ public function deleteFullHierarchy()
$item->delete();
}
}

/**
* Get current identifier counter for identifier mask from database.
*
* @return QubitSetting The identifier counter setting (use ->value to get value).
*/
public static function getIdentifierCounter()
{
if (null === $counter = QubitSetting::getByName('identifier_counter'))
{
throw new sfException('identifier_counter setting not found--is your database upgraded?');
}

return $counter;
}

/**
* Generate identifier based on identifier mask and current counter.
*
* @return string The generated identifier.
*/
public static function generateIdentiferFromMask()
{
$counter = self::getIdentifierCounter();

return preg_replace_callback('/([#%])([A-z]+)/', function($match) use ($counter)
{
if ('%' == $match[1])
{
return strftime('%'.$match[2]);
}
else if ('#' == $match[1])
{
if (0 < preg_match('/^i+$/', $match[2], $matches))
{
return str_pad($counter->value, strlen($matches[0]), 0, STR_PAD_LEFT);
}

return $match[2];
}
}, sfConfig::get('app_identifier_mask', ''));
}
}

0 comments on commit b1e82cd

Please sign in to comment.