416 lines
16 KiB
PHP
416 lines
16 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file classes/plugins/PubIdPlugin.php
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2003-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class PubIdPlugin
|
|
*
|
|
* @ingroup plugins
|
|
*
|
|
* @brief Public identifiers plugins common functions
|
|
*/
|
|
|
|
namespace APP\plugins;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use APP\issue\Collector;
|
|
use APP\issue\Issue;
|
|
use APP\journal\Journal;
|
|
use APP\notification\NotificationManager;
|
|
use APP\submission\Submission;
|
|
use PKP\core\JSONMessage;
|
|
use PKP\core\PKPString;
|
|
use PKP\submission\Representation;
|
|
use PKP\submissionFile\SubmissionFile;
|
|
|
|
abstract class PubIdPlugin extends \PKP\plugins\PKPPubIdPlugin
|
|
{
|
|
/**
|
|
* @copydoc Plugin::manage()
|
|
*/
|
|
public function manage($args, $request)
|
|
{
|
|
$user = $request->getUser();
|
|
$router = $request->getRouter();
|
|
$context = $router->getContext($request);
|
|
|
|
$notificationManager = new NotificationManager();
|
|
switch ($request->getUserVar('verb')) {
|
|
case 'assignPubIds':
|
|
if (!$request->checkCSRF()) {
|
|
return new JSONMessage(false);
|
|
}
|
|
return $this->assignPubIds($request, $context);
|
|
default:
|
|
return parent::manage($args, $request);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles pubId assignment for any publication, galley, or issue pubIds
|
|
* (usen on the plugin setting page, called in the plugin manage function)
|
|
*/
|
|
protected function assignPubIds($request, $context): JSONMessage
|
|
{
|
|
$suffixFieldName = $this->getSuffixFieldName();
|
|
$suffixGenerationStrategy = $this->getSetting($context->getId(), $suffixFieldName);
|
|
if ($suffixGenerationStrategy != 'customId') {
|
|
$issueEnabled = $this->isObjectTypeEnabled('Issue', $context->getId());
|
|
$publicationEnabled = $this->isObjectTypeEnabled('Publication', $context->getId());
|
|
$representationEnabled = $this->isObjectTypeEnabled('Representation', $context->getId());
|
|
if ($issueEnabled) {
|
|
$issues = Repo::issue()->getCollector()
|
|
->filterByContextIds([$context->getId()])
|
|
->filterByPublished(true)
|
|
->orderBy(Collector::ORDERBY_PUBLISHED_ISSUES)
|
|
->getMany();
|
|
foreach ($issues as $issue) {
|
|
$issuePubId = $issue->getStoredPubId($this->getPubIdType());
|
|
if (empty($issuePubId)) {
|
|
$issuePubId = $this->getPubId($issue);
|
|
Repo::issue()->dao->changePubId($issue->getId(), $this->getPubIdType(), $issuePubId);
|
|
}
|
|
}
|
|
}
|
|
if ($publicationEnabled || $representationEnabled) {
|
|
$representationDao = Application::getRepresentationDAO();
|
|
$submissions = Repo::submission()->getCollector()
|
|
->filterByContextIds([$context->getId()])
|
|
->filterByStatus([Submission::STATUS_PUBLISHED])
|
|
->getMany();
|
|
|
|
foreach ($submissions as $submission) {
|
|
$publications = $submission->getData('publications');
|
|
if ($publicationEnabled) {
|
|
foreach ($publications as $publication) {
|
|
$publicationPubId = $publication->getStoredPubId($this->getPubIdType());
|
|
if (empty($publicationPubId)) {
|
|
$publicationPubId = $this->getPubId($publication);
|
|
Repo::publication()->dao->changePubId(
|
|
$publication->getId(),
|
|
$this->getPubIdType(),
|
|
$publicationPubId
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if ($representationEnabled) {
|
|
foreach ($publications as $publication) {
|
|
$representations = Repo::galley()->getCollector()
|
|
->filterByPublicationIds([$publication->getId()])
|
|
->getMany();
|
|
|
|
foreach ($representations as $representation) {
|
|
$representationPubId = $representation->getStoredPubId($this->getPubIdType());
|
|
if (empty($representationPubId)) {
|
|
$representationPubId = $this->getPubId($representation);
|
|
$representationDao->changePubId(
|
|
$representation->getId(),
|
|
$this->getPubIdType(),
|
|
$representationPubId
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new JSONMessage(true);
|
|
}
|
|
|
|
//
|
|
// Protected template methods from PKPPlubIdPlugin
|
|
//
|
|
/**
|
|
* @copydoc PKPPubIdPlugin::getPubObjectTypes()
|
|
*/
|
|
public function getPubObjectTypes()
|
|
{
|
|
$pubObjectTypes = parent::getPubObjectTypes();
|
|
$pubObjectTypes['Issue'] = 'APP\issue\Issue';
|
|
return $pubObjectTypes;
|
|
}
|
|
|
|
/**
|
|
* @copydoc PKPPubIdPlugin::checkDuplicate()
|
|
*/
|
|
public function checkDuplicate($pubId, $pubObjectType, $excludeId, $contextId)
|
|
{
|
|
foreach ($this->getPubObjectTypes() as $type => $fqcn) {
|
|
if ($type === 'Issue') {
|
|
$excludeTypeId = $type === $pubObjectType ? $excludeId : null;
|
|
if (Repo::issue()->dao->pubIdExists($this->getPubIdType(), $pubId, $excludeTypeId, $contextId)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return parent::checkDuplicate($pubId, $pubObjectType, $excludeId, $contextId);
|
|
}
|
|
|
|
/**
|
|
* Get the public identifier.
|
|
*
|
|
* @param object $pubObject
|
|
* Publication, Representation, SubmissionFile, Issue
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPubId($pubObject)
|
|
{
|
|
// Get the pub id type
|
|
$pubIdType = $this->getPubIdType();
|
|
|
|
// If we already have an assigned pub id, use it.
|
|
$storedPubId = $pubObject->getStoredPubId($pubIdType);
|
|
if ($storedPubId) {
|
|
return $storedPubId;
|
|
}
|
|
|
|
// Determine the type of the publishing object.
|
|
$pubObjectType = $this->getPubObjectType($pubObject);
|
|
|
|
// Initialize variables for publication objects.
|
|
$issue = ($pubObjectType == 'Issue' ? $pubObject : null);
|
|
$submission = null;
|
|
// Publication is actually handled differently now, but keep it here however for now.
|
|
$publication = ($pubObjectType == 'Publication' ? $pubObject : null);
|
|
$representation = ($pubObjectType == 'Representation' ? $pubObject : null);
|
|
$submissionFile = ($pubObjectType == 'SubmissionFile' ? $pubObject : null);
|
|
|
|
// Get the context id.
|
|
if ($pubObjectType === 'Issue') {
|
|
$contextId = $pubObject->getJournalId();
|
|
} elseif ($pubObjectType === 'Representation') {
|
|
$publication = Repo::publication()->get($pubObject->getData('publicationId'));
|
|
$submission = Repo::submission()->get($publication->getData('submissionId'));
|
|
$contextId = $submission->getData('contextId');
|
|
} elseif (in_array($pubObjectType, ['Publication', 'SubmissionFile'])) {
|
|
$submission = Repo::submission()->get($pubObject->getData('submissionId'));
|
|
$contextId = $submission->getData('contextId');
|
|
}
|
|
|
|
// Check the context
|
|
$context = $this->getContext($contextId);
|
|
if (!$context) {
|
|
return null;
|
|
}
|
|
$contextId = $context->getId();
|
|
|
|
// Check whether pub ids are enabled for the given object type.
|
|
$objectTypeEnabled = $this->isObjectTypeEnabled($pubObjectType, $contextId);
|
|
if (!$objectTypeEnabled) {
|
|
return null;
|
|
}
|
|
|
|
// Retrieve the issue.
|
|
if (!$pubObject instanceof Issue) {
|
|
assert(!is_null($submission));
|
|
$issue = Repo::issue()->getBySubmissionId($submission->getId());
|
|
$issue = $issue->getJournalId() == $contextId ? $issue : null;
|
|
}
|
|
if ($issue && $contextId != $issue->getJournalId()) {
|
|
return null;
|
|
}
|
|
|
|
// Retrieve the pub id prefix.
|
|
$pubIdPrefix = $this->getSetting($contextId, $this->getPrefixFieldName());
|
|
if (empty($pubIdPrefix)) {
|
|
return null;
|
|
}
|
|
|
|
// Generate the pub id suffix.
|
|
$suffixFieldName = $this->getSuffixFieldName();
|
|
$suffixGenerationStrategy = $this->getSetting($contextId, $suffixFieldName);
|
|
switch ($suffixGenerationStrategy) {
|
|
case 'customId':
|
|
$pubIdSuffix = $pubObject->getData($suffixFieldName);
|
|
break;
|
|
|
|
case 'pattern':
|
|
$suffixPatternsFieldNames = $this->getSuffixPatternsFieldNames();
|
|
$pubIdSuffix = $this->getSetting($contextId, $suffixPatternsFieldNames[$pubObjectType]);
|
|
|
|
$pubIdSuffix = $this->generateCustomPattern($context, $pubIdSuffix, $pubObject, $issue, $submission, $representation, $submissionFile);
|
|
|
|
break;
|
|
|
|
default:
|
|
$pubIdSuffix = $this::generateDefaultPattern($context, $issue, $submission, $representation, $submissionFile);
|
|
}
|
|
if (empty($pubIdSuffix)) {
|
|
return null;
|
|
}
|
|
|
|
// Construct the pub id from prefix and suffix.
|
|
$pubId = $this->constructPubId($pubIdPrefix, $pubIdSuffix, $contextId);
|
|
|
|
return $pubId;
|
|
}
|
|
|
|
/**
|
|
* Generate the default, semantic-based pub-id pattern suffix
|
|
*
|
|
* @param Journal $context
|
|
* @param ?Issue $issue
|
|
* @param Submission $submission
|
|
* @param Representation $representation
|
|
* @param SubmissionFile $submissionFile
|
|
*
|
|
*/
|
|
public static function generateDefaultPattern($context, $issue = null, $submission = null, $representation = null, $submissionFile = null): string
|
|
{
|
|
$pubIdSuffix = PKPString::regexp_replace('/[^-._;()\/A-Za-z0-9]/', '', PKPString::strtolower($context->getAcronym($context->getPrimaryLocale())));
|
|
|
|
if ($issue) {
|
|
$pubIdSuffix .= '.v' . $issue->getVolume() . 'i' . $issue->getNumber();
|
|
} else {
|
|
$pubIdSuffix .= '.v%vi%i';
|
|
}
|
|
|
|
if ($submission) {
|
|
$pubIdSuffix .= '.' . $submission->getId();
|
|
}
|
|
|
|
if ($representation) {
|
|
$pubIdSuffix .= '.g' . $representation->getId();
|
|
}
|
|
|
|
if ($submissionFile) {
|
|
$pubIdSuffix .= '.f' . $submissionFile->getId();
|
|
}
|
|
|
|
return $pubIdSuffix;
|
|
}
|
|
|
|
/**
|
|
* Generate the custom, user-defined pub-id pattern suffix
|
|
*
|
|
* @param Journal $context
|
|
* @param string $pubIdSuffix
|
|
* @param object $pubObject
|
|
* @param Issue $issue
|
|
* @param Submission $submission
|
|
* @param Representation $representation
|
|
* @param SubmissionFile $submissionFile
|
|
*
|
|
*/
|
|
public static function generateCustomPattern($context, $pubIdSuffix, $pubObject, $issue = null, $submission = null, $representation = null, $submissionFile = null): string
|
|
{
|
|
// %j - journal initials, remove special characters and uncapitalize
|
|
$pubIdSuffix = PKPString::regexp_replace('/%j/', PKPString::regexp_replace('/[^-._;()\/A-Za-z0-9]/', '', PKPString::strtolower($context->getAcronym($context->getPrimaryLocale()))), $pubIdSuffix);
|
|
|
|
// %x - custom identifier
|
|
if ($pubObject->getStoredPubId('publisher-id')) {
|
|
$pubIdSuffix = PKPString::regexp_replace('/%x/', $pubObject->getStoredPubId('publisher-id'), $pubIdSuffix);
|
|
}
|
|
|
|
if ($issue) {
|
|
// %v - volume number
|
|
$pubIdSuffix = PKPString::regexp_replace('/%v/', $issue->getVolume(), $pubIdSuffix);
|
|
// %i - issue number
|
|
$pubIdSuffix = PKPString::regexp_replace('/%i/', $issue->getNumber(), $pubIdSuffix);
|
|
// %Y - year
|
|
$pubIdSuffix = PKPString::regexp_replace('/%Y/', $issue->getYear(), $pubIdSuffix);
|
|
}
|
|
|
|
if ($submission) {
|
|
// %a - article id
|
|
$pubIdSuffix = PKPString::regexp_replace('/%a/', $submission->getId(), $pubIdSuffix);
|
|
// %p - page number
|
|
if ($submission->getPages()) {
|
|
$pubIdSuffix = PKPString::regexp_replace('/%p/', $submission->getPages(), $pubIdSuffix);
|
|
}
|
|
}
|
|
|
|
if ($representation) {
|
|
// %g - galley id
|
|
$pubIdSuffix = PKPString::regexp_replace('/%g/', $representation->getId(), $pubIdSuffix);
|
|
}
|
|
|
|
if ($submissionFile) {
|
|
// %f - file id
|
|
$pubIdSuffix = PKPString::regexp_replace('/%f/', $submissionFile->getId(), $pubIdSuffix);
|
|
}
|
|
|
|
return $pubIdSuffix;
|
|
}
|
|
|
|
//
|
|
// Public API
|
|
//
|
|
/**
|
|
* Clear pubIds of all issue objects.
|
|
*
|
|
* @param Issue $issue
|
|
*/
|
|
public function clearIssueObjectsPubIds($issue)
|
|
{
|
|
$publicationPubIdEnabled = $this->isObjectTypeEnabled('Publication', $issue->getJournalId());
|
|
$representationPubIdEnabled = $this->isObjectTypeEnabled('Representation', $issue->getJournalId());
|
|
$filePubIdEnabled = $this->isObjectTypeEnabled('SubmissionFile', $issue->getJournalId());
|
|
if (!$publicationPubIdEnabled && !$representationPubIdEnabled && !$filePubIdEnabled) {
|
|
return false;
|
|
}
|
|
|
|
$pubIdType = $this->getPubIdType();
|
|
|
|
$submissionIds = Repo::submission()
|
|
->getCollector()
|
|
->filterByContextIds([$issue->getJournalId()])
|
|
->filterByIssueIds([$issue->getId()])
|
|
->getIds();
|
|
|
|
foreach ($submissionIds as $submissionId) {
|
|
$submission = Repo::submission()->get($submissionId);
|
|
if ($publicationPubIdEnabled) { // Does this option have to be enabled here for?
|
|
foreach ($submission->getData('publications') as $publication) {
|
|
Repo::publication()->dao->deletePubId($publication->getId(), $pubIdType);
|
|
}
|
|
}
|
|
if ($representationPubIdEnabled || $filePubIdEnabled) { // Does this option have to be enabled here for?
|
|
foreach ($submission->getData('publications') as $publication) {
|
|
$representations = Application::getRepresentationDAO()->getByPublicationId($publication->getId());
|
|
foreach ($representations as $representation) {
|
|
if ($representationPubIdEnabled) { // Does this option have to be enabled here for?
|
|
Application::getRepresentationDAO()->deletePubId($representation->getId(), $pubIdType);
|
|
}
|
|
if ($filePubIdEnabled) { // Does this option have to be enabled here for?
|
|
$articleProofFileIds = Repo::submissionFile()
|
|
->getCollector()
|
|
->filterByAssoc(
|
|
Application::ASSOC_TYPE_REPRESENTATION,
|
|
[$representation->getId()]
|
|
)->filterByFileStages([SubmissionFile::SUBMISSION_FILE_PROOF])
|
|
->getIds();
|
|
|
|
foreach ($articleProofFileIds as $articleProofFileId) {
|
|
Repo::submissionFile()->dao->deletePubId($articleProofFileId, $pubIdType);
|
|
}
|
|
}
|
|
}
|
|
unset($representations);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @copydoc PKPPubIdPlugin::getDAOs()
|
|
*/
|
|
public function getDAOs()
|
|
{
|
|
return array_merge(parent::getDAOs(), [Repo::issue()->dao]);
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\APP\plugins\PubIdPlugin', '\PubIdPlugin');
|
|
}
|