diff --git a/classes/controllers/grid/issues/IssueGridHandler.php b/classes/controllers/grid/issues/IssueGridHandler.php index eaa10436445..0ab9232c43e 100644 --- a/classes/controllers/grid/issues/IssueGridHandler.php +++ b/classes/controllers/grid/issues/IssueGridHandler.php @@ -549,7 +549,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 00e72bc24a3..5e6eee3f3f6 100644 --- a/classes/publication/Repository.php +++ b/classes/publication/Repository.php @@ -154,19 +154,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 7111da852ad..0d18ef34227 100644 --- a/controllers/grid/issues/IssueGridRow.php +++ b/controllers/grid/issues/IssueGridRow.php @@ -61,16 +61,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', @@ -109,7 +109,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 fc51f41fd93..a5c32389b3d 100644 --- a/controllers/grid/issues/form/IssueForm.php +++ b/controllers/grid/issues/form/IssueForm.php @@ -27,6 +27,7 @@ use PKP\linkAction\LinkAction; use PKP\linkAction\request\RemoteActionConfirmationModal; use PKP\plugins\Hook; +use PKP\validation\ValidatorFactory; class IssueForm extends Form { @@ -57,6 +58,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; @@ -142,6 +144,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); } @@ -241,9 +266,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_US/editor.po b/locale/en_US/editor.po index 723b6b9ca4a..a0e0e1a0f9f 100644 --- a/locale/en_US/editor.po +++ b/locale/en_US/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 aa4d0f8c72f..45a6ef9b3ce 100644 --- a/templates/controllers/grid/issues/form/issueForm.tpl +++ b/templates/controllers/grid/issues/form/issueForm.tpl @@ -41,16 +41,15 @@ {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"} + {else} + {fbvElement type="text" id="datePublished" value=$datePublished size=$fbvStyles.size.SMALL class="datepicker" label="editor.issues.datePublished.notPublished.description"} {/if} {/fbvFormSection} {/fbvFormArea} - {/if} - {fbvFormArea id="identificationArea" title="editor.issues.identification"} {fbvFormSection}