diff --git a/classes/controllers/grid/issues/IssueGridHandler.php b/classes/controllers/grid/issues/IssueGridHandler.php index f62476713d1..8d94d6148f9 100644 --- a/classes/controllers/grid/issues/IssueGridHandler.php +++ b/classes/controllers/grid/issues/IssueGridHandler.php @@ -561,7 +561,11 @@ public function publishIssue($args, $request) } $issue->setPublished(1); - $issue->setDatePublished(Core::getCurrentDate()); + + // If no datePublished was given, use current date + if (!$issue->getData('datePublished')) { + $issue->setDatePublished(Core::getCurrentDate()); + } // If subscriptions with delayed open access are enabled then // update open access date according to open access delay policy diff --git a/classes/publication/Repository.php b/classes/publication/Repository.php index 4711ba55a9d..ae2aff6e760 100644 --- a/classes/publication/Repository.php +++ b/classes/publication/Repository.php @@ -152,19 +152,35 @@ public function version(Publication $publication): int return $newId; } - /** @copydoc \PKP\publication\Repository::setStatusOnPublish() */ + /** + * Set the status and date of publication + * + * A publication's status and date of publication will be set depending + * on the issue it is assigned to. Publications in future issues should + * be set to `STATUS_SCHEDULED`. Otherwise, they should be set to + * `STATUS_PUBLISHED` and should inherit the date of publication from the + * issue, unless a date of publication has already been set. + * + * Usually, the date of publication will be set when the issue is + * published. In some unusual cases, a publication may be published + * without an issue. This may happen in a continuous publishing model + * where articles are published right away. In these cases, the date of + * publication should be set to the current date, unless a date of + * publication has already been set. + */ protected function setStatusOnPublish(Publication $publication) { - // A publication may be scheduled in a future issue. In such cases, - // the `datePublished` should remain empty and the status should be set to - // scheduled. - // - // If there is no assigned issue, the journal may be using a continuous - // publishing model in which articles are published right away. $issue = Repo::issue()->get($publication->getData('issueId')); - if ($issue && !$issue->getData('published')) { - $publication->setData('datePublished', null); - $publication->setData('status', Submission::STATUS_SCHEDULED); + + if ($issue) { + if ($issue->getData('published')) { + $publication->setData('status', Submission::STATUS_PUBLISHED); + if (!$publication->getData('datePublished')) { + $publication->setData('datePublished', $issue->getData('datePublished')); + } + } else { + $publication->setData('status', Submission::STATUS_SCHEDULED); + } } else { $publication->setData('status', Submission::STATUS_PUBLISHED); if (!$publication->getData('datePublished')) { diff --git a/controllers/grid/issues/IssueGridRow.php b/controllers/grid/issues/IssueGridRow.php index 2e87da1dcf8..0f11f9f5edb 100644 --- a/controllers/grid/issues/IssueGridRow.php +++ b/controllers/grid/issues/IssueGridRow.php @@ -63,16 +63,16 @@ public function initialize($request, $template = null) $dispatcher = $request->getDispatcher(); $this->addAction( new LinkAction( - $issue->getDatePublished() ? 'viewIssue' : 'previewIssue', + $issue->getPublished() ? 'viewIssue' : 'previewIssue', new OpenWindowAction( $dispatcher->url($request, PKPApplication::ROUTE_PAGE, null, 'issue', 'view', [$issueId]) ), - __($issue->getDatePublished() ? 'grid.action.viewIssue' : 'grid.action.previewIssue'), + __($issue->getPublished() ? 'grid.action.viewIssue' : 'grid.action.previewIssue'), 'information' ) ); - if ($issue->getDatePublished()) { + if ($issue->getPublished()) { $this->addAction( new LinkAction( 'unpublish', @@ -111,7 +111,7 @@ public function initialize($request, $template = null) $currentIssue = Repo::issue()->getCurrent($issue->getJournalId()); $isCurrentIssue = $currentIssue != null && $issue->getId() == $currentIssue->getId(); - if ($issue->getDatePublished() && !$isCurrentIssue) { + if ($issue->getPublished() && !$isCurrentIssue) { $this->addAction( new LinkAction( 'setCurrentIssue', diff --git a/controllers/grid/issues/form/IssueForm.php b/controllers/grid/issues/form/IssueForm.php index 1ce4a07f9aa..f3718205c01 100644 --- a/controllers/grid/issues/form/IssueForm.php +++ b/controllers/grid/issues/form/IssueForm.php @@ -30,6 +30,7 @@ use PKP\linkAction\LinkAction; use PKP\linkAction\request\RemoteActionConfirmationModal; use PKP\plugins\Hook; +use PKP\validation\ValidatorFactory; class IssueForm extends Form { @@ -60,6 +61,7 @@ public function __construct($issue = null) return !$showTitle || implode('', $form->getData('title')) != '' ? true : false; })); $this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'urlPath', 'optional', 'validator.alpha_dash_period', '/^[a-zA-Z0-9]+([\\.\\-_][a-zA-Z0-9]+)*$/')); + $this->addCheck(new \PKP\form\validation\FormValidatorPost($this)); $this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this)); $this->issue = $issue; @@ -143,6 +145,29 @@ public function validate($callHooks = true) } } + // Note! The following datePublished validation is not triggered + // when JQuery DatePicker is enabled in the datePublished field. + // The datePicker will convert any invalid date into a valid yyyy-mm-dd + // date before the form data is submitted. + + if ($this->getData('datePublished')) { + $validator = ValidatorFactory::make( + ['value' => $this->getData('datePublished')], + ['value' => ['required', 'date_format:Y-m-d']] + ); + + if (!$validator->passes()) { + $this->addError('datePublished', __('editor.issues.datePublished.invalid')); + $this->addErrorField('datePublished'); + } + } + + // Published issue has to have datePublished set + if (!$this->getData('datePublished') && ($this->issue && $this->issue->getPublished())) { + $this->addError('datePublished', __('editor.issues.datePublished.requiredWhenPublished')); + $this->addErrorField('datePublished'); + } + return parent::validate($callHooks); } @@ -243,9 +268,16 @@ public function execute(...$functionArgs) $issue->setVolume(empty($volume) ? null : $volume); $issue->setNumber(empty($number) ? null : $number); $issue->setYear(empty($year) ? null : $year); - if (!$isNewIssue) { + + // If issue is not published, allow empty datePublished + if (!$this->getData('datePublished') && !$issue->getPublished()) { + $issue->setDatePublished(null); + } + + if ($this->getData('datePublished')) { $issue->setDatePublished($this->getData('datePublished')); } + $issue->setDescription($this->getData('description'), null); // Localized $issue->setShowVolume((int) $this->getData('showVolume')); $issue->setShowNumber((int) $this->getData('showNumber')); diff --git a/locale/en/editor.po b/locale/en/editor.po index 723b6b9ca4a..a0e0e1a0f9f 100644 --- a/locale/en/editor.po +++ b/locale/en/editor.po @@ -120,6 +120,15 @@ msgstr "Unpublished" msgid "editor.issues.datePublished" msgstr "Date Published" +msgid "editor.issues.datePublished.notPublished.description" +msgstr "Leave this empty and it will be set automatically when the issue is published." + +msgid "editor.issues.datePublished.invalid" +msgstr "Date Published is not valid. The date must be in the format YYYY-MM-DD." + +msgid "editor.issues.datePublished.requiredWhenPublished" +msgstr "Date Published is required when the issue is published." + msgid "editor.issues.volumeRequired" msgstr "Volume is required and must be a positive, numeric value." diff --git a/templates/controllers/grid/issues/form/issueForm.tpl b/templates/controllers/grid/issues/form/issueForm.tpl index a31cb58cd60..35b6d1ca6f9 100644 --- a/templates/controllers/grid/issues/form/issueForm.tpl +++ b/templates/controllers/grid/issues/form/issueForm.tpl @@ -43,16 +43,16 @@ {assign var=issuePublished value=false} {/if} - {if $issuePublished} {fbvFormArea id="datePublishedArea" title="editor.issues.datePublished"} {fbvFormSection} - {if $issuePublished} - {fbvElement type="text" id="datePublished" value=$datePublished size=$fbvStyles.size.SMALL class="datepicker"} - {/if} + {if !$issuePublished} + {assign var=notPublishedDescription value="editor.issues.datePublished.notPublished.description"} + {else} + {assign var=notPublishedDescription value=""} + {/if} + {fbvElement type="text" id="datePublished" value=$datePublished size=$fbvStyles.size.SMALL class="datepicker" autocomplete="off" label=$notPublishedDescription} {/fbvFormSection} {/fbvFormArea} - {/if} - {fbvFormArea id="identificationArea" title="editor.issues.identification"} {fbvFormSection}