Skip to content

Commit

Permalink
Change submission language
Browse files Browse the repository at this point in the history
  • Loading branch information
jyhein committed Sep 25, 2024
1 parent 97635b0 commit 80f1467
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
97 changes: 97 additions & 0 deletions api/v1/submissions/PKPSubmissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace PKP\API\v1\submissions;

use APP\author\Author;
use APP\core\Application;
use APP\facades\Repo;
use APP\mail\variables\ContextEmailVariable;
Expand Down Expand Up @@ -65,6 +66,7 @@
use PKP\submission\GenreDAO;
use PKP\submission\PKPSubmission;
use PKP\submission\reviewAssignment\ReviewAssignment;
use PKP\submissionFile\SubmissionFile;
use PKP\userGroup\UserGroup;

class PKPSubmissionController extends PKPBaseController
Expand All @@ -84,6 +86,7 @@ class PKPSubmissionController extends PKPBaseController
'saveForLater',
'submit',
'delete',
'changeLocale',
'getGalleys',
'getDecisions',
'getParticipants',
Expand Down Expand Up @@ -116,6 +119,7 @@ class PKPSubmissionController extends PKPBaseController
'deleteContributor',
'editContributor',
'saveContributorsOrder',
'changeLocale',
];

/** @var array Handlers that must be authorized to access a submission's production stage */
Expand Down Expand Up @@ -218,6 +222,10 @@ public function getGroupRoutes(): void
Route::delete('{submissionId}', $this->delete(...))
->name('submission.delete')
->whereNumber('submissionId');

Route::put('{submissionId}/publications/{publicationId}/changeLocale', $this->changeLocale(...))
->name('submission.publication.changeLocale')
->whereNumber(['submissionId', 'publicationId']);
});

Route::middleware([
Expand Down Expand Up @@ -867,6 +875,59 @@ public function delete(Request $illuminateRequest): JsonResponse
return response()->json($submissionProps, Response::HTTP_OK);
}

/**
* Change submission language
*/
public function changeLocale(Request $illuminateRequest): JsonResponse
{
$publication = Repo::publication()->get((int) $illuminateRequest->route('publicationId'));

if (!$publication) {
return response()->json([
'error' => __('api.404.resourceNotFound'),
], Response::HTTP_NOT_FOUND);
}

$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);

if ($submission->getId() !== $publication->getData('submissionId')) {
return response()->json([
'error' => __('api.publications.403.submissionsDidNotMatch'),
], Response::HTTP_FORBIDDEN);
}

$paramsSubmission = $this->convertStringsToSchema(PKPSchemaService::SCHEMA_SUBMISSION, $illuminateRequest->input());
$newLocale = $paramsSubmission['locale'] ?? null;

// Submission language can not be changed when there are more than one publication or a publication's status is published
if (!$newLocale || count($submission->getData('publications')) > 1 || $publication->getData('status') === PKPSubmission::STATUS_PUBLISHED) {
return response()->json(['error' => __('api.submission.403.cantChangeSubmissionLanguage')], Response::HTTP_FORBIDDEN);
}

// Convert a form field value to multilingual (if it is not) and merge rest values
collect(app()->get('schema')->getMultilingualProps(PKPSchemaService::SCHEMA_PUBLICATION))
->each(fn (string $prop) =>
$illuminateRequest->whenHas($prop, fn ($value) =>
$illuminateRequest->merge([
$prop => array_merge(
$publication->getData($prop) ?? [],
(is_array($value) && array_key_exists($newLocale, $value)) ? $value : [$newLocale => $value]
)
])
)
);

$responsePublication = $this->editPublication($illuminateRequest);

if ($responsePublication->status() !== 200) {
return $responsePublication;
}

$this->copyMultilingualData($submission, $newLocale);

return $this->edit($illuminateRequest);
}

/**
* Get the decisions recorded on a submission
*/
Expand Down Expand Up @@ -1986,4 +2047,40 @@ protected function getSubmissionAndPublicationData(Request $illuminateRequest):
];
}

/**
* Copy author, files, etc. multilingual fields from old to new changed language
*/
protected function copyMultilingualData(Submission $submission, string $newLocale): void {
$oldLocale = $submission->getData('locale');
$editProps = fn (Author|SubmissionFile $item, array $props): array => collect($props)
->mapWithKeys(fn (string $prop): array => [$prop => ($data = $item->getData($prop)[$oldLocale] ?? null) ? [$newLocale => $data] : null])
->filter()
->toArray();

// Submission files
$fileProps = [
'name',
];
Repo::submissionFile()
->getCollector()
->filterBySubmissionIds([$submission->getId()])
->getMany()
->each(fn (SubmissionFile $file) => Repo::submissionFile()->edit($file, $editProps($file, $fileProps)));

// Contributor
$contributorProps = [
'givenName',
'familyName',
'preferredPublicName',
];
Repo::author()
->getCollector()
->filterByPublicationIds([$submission->getLatestPublication()->getId()])
->getMany()
->each(function (Author $contributor) use ($contributorProps, $editProps, $newLocale) {
if (!($contributor->getData('givenName')[$newLocale] ?? null)) {
Repo::author()->edit($contributor, $editProps($contributor, $contributorProps));
}
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php
/**
* @file classes/components/form/submission/ChangeSubmissionLanguageMetadataForm.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class ChangeSubmissionLanguageMetadataForm
*
* @brief A form for changing submission's metadata before language change.
*/

namespace PKP\components\forms\submission;

use APP\facades\Repo;
use APP\publication\Publication;
use APP\submission\Submission;
use PKP\components\forms\Field;
use PKP\components\forms\FieldHTML;
use PKP\components\forms\FieldRadioInput;
use PKP\components\forms\FormComponent;
use PKP\components\forms\publication\TitleAbstractForm;
use PKP\context\Context;
use PKP\facades\Locale;

class ChangeSubmissionLanguageMetadataForm extends FormComponent
{
public const FORM_CHANGE_SUBMISSION_LANGUAGE_METADATA = 'changeSubmissionLanguageMetadata';
public $id = self::FORM_CHANGE_SUBMISSION_LANGUAGE_METADATA;
public $method = 'PUT';

public function __construct(string $action, Submission $submission, Publication $publication, Context $context)
{
$this->action = $action;

$this->addGroup([
'id' => 'language',
]);

$submissionLocale = $submission->getData('locale');
$supportedLocaleNames = collect($context->getSupportedSubmissionLocaleNames());
$submissionLocaleNames = collect(Locale::getSubmissionLocaleDisplayNames([$submissionLocale]));
$showWhen = ['locale', $supportedLocaleNames->diffKeys($submissionLocaleNames)->keys()->toArray()];

$this->addGroup([
'id' => 'metadata',
'showWhen' => $showWhen,
]);

// Language
$localeOptions = $supportedLocaleNames
->union($submissionLocaleNames)
->sortKeys()
->map(fn ($name, $key) => ['value' => $key, 'label' => $name])
->values()
->toArray();
$this->addField(new FieldRadioInput('locale', [
'label' => __('submission.submit.submissionLocale'),
'description' => __('submission.list.changeSubmissionLanguage.languageDescription'),
'groupId' => 'language',
'type' => 'radio',
'options' => $localeOptions,
'isRequired' => true,
'value' => $submissionLocale,
]));

// Metadata description
$this->addField(new FieldHTML('metadataDescription', [
'description' => __('submission.list.changeSubmissionLanguage.metadataDescription'),
'groupId' => 'metadata',
]));

$submissionLocaleName = $submissionLocaleNames->get($submissionLocale);

// Title and abstract
$titleAbstractForm = $this->getTitleAbstractForm(FormComponent::ACTION_EMIT, [$submissionLocale], $publication, $context);
$this->setField($titleAbstractForm->getField('title'), $submissionLocaleName, $submissionLocale);
$this->setField($titleAbstractForm->getField('abstract'), $submissionLocaleName, $submissionLocale);

// Add cancel button
$this->addCancel();
}

protected function addCancel() {
$this->addPage([
'id' => 'default',
'submitButton' => ['label' => __('common.confirm')],
'cancelButton' => ['label' => __('common.cancel')],
]);
collect($this->groups)->each(fn ($_, $i) => ($this->groups[$i]['pageId'] = 'default'));
}

protected function getTitleAbstractForm(string $publicationApiUrl, array $locales, Publication $publication, Context $context): TitleAbstractForm
{
$pubSecId = $publication->getData('sectionId');
$section = $pubSecId ? Repo::section()->get($pubSecId, $context->getId()) : null;
return new TitleAbstractForm(
$publicationApiUrl,
$locales,
$publication,
$section ? (int) $section->getData('wordCount') : 0,
$section && !$section->getData('abstractsNotRequired')
);
}

protected function setField(Field $field, string $submissionLocaleName, string $submissionLocale): void {
if ($field->isRequired) {
$field->groupId = 'metadata';
$field->description = __("submission.list.changeSubmissionLanguage.metadataDescription.{$field->name}", ['language' => $submissionLocaleName]);
if ($field->isMultilingual) {
$field->isMultilingual = false;
$field->value = $field->value[$submissionLocale];
}
$this->addField($field);
}
}
}
3 changes: 3 additions & 0 deletions locale/en/api.po
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ msgstr "The requested volume, number or year is not valid."
msgid "api.submissions.400.invalidSubmitAs"
msgstr "You are not allowed to submit in this user role."

msgid "api.submission.403.cantChangeSubmissionLanguage"
msgstr "You can not change language of this submission because it already has more than one publication version or a published publication."

msgid "api.submissions.403.csrfTokenFailure"
msgstr "Your request was denied. This may be because your login has expired. Try reloading the page and trying again."

Expand Down
24 changes: 24 additions & 0 deletions locale/en/submission.po
Original file line number Diff line number Diff line change
Expand Up @@ -2043,6 +2043,28 @@ msgstr "You must assign at least one participant to this submission before initi
msgid "submission.query.allowedEditTime"
msgstr "You can update this discussion for {$allowedEditTimeNoticeLimit} minutes."

msgid "submission.list.changeSubmissionLanguage.currentLanguage"
msgstr "Current Submission Language:"

msgid "submission.list.changeSubmissionLanguage.buttonLabel"
msgstr "Change"

msgid "submission.list.changeSubmissionLanguage.title"
msgstr "Change Submission Language For"

msgid "submission.list.changeSubmissionLanguage.languageDescription"
msgstr "This is the primary submission language. Changing this will have effects on the submission and the metadata entered"

msgid "submission.list.changeSubmissionLanguage.metadataDescription"
msgstr "<strong>Before changing the submission language, ensure you have filled out the following metadata fields to maintain system integrity. "
"Also, note that contributor information and file names will be copied from previously entered information.</strong>"

msgid "submission.list.changeSubmissionLanguage.metadataDescription.title"
msgstr "Enter submission title here in {$language}. You can format your title as needed"

msgid "submission.list.changeSubmissionLanguage.metadataDescription.abstract"
msgstr "Including the abstract in {$language} is recommended. This helps ensure that the content is accessible"

msgid "submission.list.infoCenter"
msgstr "Activity Log & Notes"

Expand Down Expand Up @@ -2430,3 +2452,5 @@ msgstr "Competing Interests"
msgid "author.competingInterests.description"
msgstr "Please disclose any competing interests this author may have with the research subject."

msgid "submission.localeNotSupported"
msgstr "The language of the submission ({$language}) is not one of the supported submission languages. You can still edit the submission details but new submissions are not currently accepted with this language."
2 changes: 2 additions & 0 deletions pages/authorDashboard/PKPAuthorDashboardHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use PKP\core\PKPApplication;
use PKP\core\PKPRequest;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\log\SubmissionEmailLogEventType;
use PKP\security\authorization\AuthorDashboardAccessPolicy;
use PKP\security\Role;
Expand Down Expand Up @@ -305,6 +306,7 @@ public function setupTemplate($request)

$state = [
'canEditPublication' => $canEditPublication,
'currentSubmissionLanguageLabel' => Locale::getSubmissionLocaleDisplayNames([$submissionLocale])[$submissionLocale],
'components' => [
$titleAbstractForm::FORM_TITLE_ABSTRACT => $this->getLocalizedForm($titleAbstractForm, $submissionLocale, $locales),
$citationsForm::FORM_CITATIONS => $this->getLocalizedForm($citationsForm, $submissionLocale, $locales),
Expand Down
10 changes: 10 additions & 0 deletions pages/workflow/PKPWorkflowHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use PKP\components\forms\publication\PKPMetadataForm;
use PKP\components\forms\publication\PKPPublicationLicenseForm;
use PKP\components\forms\publication\TitleAbstractForm;
use PKP\components\forms\submission\ChangeSubmissionLanguageMetadataForm;
use PKP\components\listPanels\ContributorsListPanel;
use PKP\components\PublicationSectionJats;
use PKP\context\Context;
Expand All @@ -40,6 +41,7 @@
use PKP\core\PKPRequest;
use PKP\db\DAORegistry;
use PKP\decision\Decision;
use PKP\facades\Locale;
use PKP\notification\Notification;
use PKP\plugins\PluginRegistry;
use PKP\security\authorization\internal\SubmissionCompletePolicy;
Expand Down Expand Up @@ -293,11 +295,15 @@ public function index($args, $request)
$canEditPublication
);

$changeSubmissionLanguageApiUrl = $request->getDispatcher()->url($request, Application::ROUTE_API, $submissionContext->getData('urlPath'), "submissions/{$submission->getId()}/publications/{$latestPublication->getId()}/changeLocale");
$changeSubmissionLanguageMetadataForm = new ChangeSubmissionLanguageMetadataForm($changeSubmissionLanguageApiUrl, $submission, $latestPublication, $submissionContext);

$templateMgr->setConstants([
'STATUS_QUEUED' => PKPSubmission::STATUS_QUEUED,
'STATUS_PUBLISHED' => PKPSubmission::STATUS_PUBLISHED,
'STATUS_DECLINED' => PKPSubmission::STATUS_DECLINED,
'STATUS_SCHEDULED' => PKPSubmission::STATUS_SCHEDULED,
'FORM_CHANGE_SUBMISSION_LANGUAGE_METADATA' => $changeSubmissionLanguageMetadataForm::FORM_CHANGE_SUBMISSION_LANGUAGE_METADATA,
'FORM_CITATIONS' => $citationsForm::FORM_CITATIONS,
'FORM_PUBLICATION_LICENSE' => $publicationLicenseForm::FORM_PUBLICATION_LICENSE,
'FORM_PUBLISH' => PublishForm::FORM_PUBLISH,
Expand Down Expand Up @@ -334,8 +340,11 @@ public function index($args, $request)
$state = [
'activityLogLabel' => __('submission.list.infoCenter'),
'canAccessPublication' => $canAccessPublication,
'canChangeSubmissionLanguage' => $canPublish || $canEditPublication,
'canEditPublication' => $canEditPublication,
'currentSubmissionLanguageLabel' => Locale::getSubmissionLocaleDisplayNames([$submissionLocale])[$submissionLocale],
'components' => [
$changeSubmissionLanguageMetadataForm->id => $this->getLocalizedForm($changeSubmissionLanguageMetadataForm, $submissionLocale, $locales),
$contributorsListPanel->id => $contributorsListPanel->getConfig(),
$citationsForm->id => $citationsForm->getConfig(),
$publicationLicenseForm->id => $this->getLocalizedForm($publicationLicenseForm, $submissionLocale, $locales),
Expand All @@ -362,6 +371,7 @@ public function index($args, $request)
'submissionApiUrl' => $submissionApiUrl,
'submissionLibraryLabel' => __('grid.libraryFiles.submission.title'),
'submissionLibraryUrl' => $submissionLibraryUrl,
'submissionSupportedLocales' => $submissionContext->getSupportedSubmissionLocales(),
'supportsReferences' => !!$submissionContext->getData('citations'),
'unpublishConfirmLabel' => __('publication.unpublish.confirm'),
'unpublishLabel' => __('publication.unpublish'),
Expand Down

0 comments on commit 80f1467

Please sign in to comment.