19 use \DAOResultFactory;
25 use \PKP\Services\interfaces\EntityPropertyInterface;
26 use \PKP\Services\interfaces\EntityReadInterface;
27 use \PKP\Services\interfaces\EntityWriteInterface;
28 use \PKP\Services\QueryBuilders\PKPPublicationQueryBuilder;
30 import(
'lib.pkp.classes.db.DBResultRange');
37 public function get($publicationId) {
39 return $publicationDao->getById($publicationId);
68 if (isset($args[
'count'])) {
69 $range =
new DBResultRange($args[
'count'],
null, isset($args[
'offset']) ? $args[
'offset'] : 0);
73 if (isset($args[
'count'])) unset($args[
'count']);
74 if (isset($args[
'offset'])) unset($args[
'offset']);
77 $result = $publicationDao->retrieveRange($publicationQO->toSql(), $publicationQO->getBindings(), $range);
80 return $queryResults->toIterator();
88 if (isset($args[
'count'])) unset($args[
'count']);
89 if (isset($args[
'offset'])) unset($args[
'offset']);
101 'submissionIds' => [],
104 $args = array_merge($defaultArgs, $args);
108 ->filterByContextIds($args[
'contextIds'])
109 ->filterBySubmissionIds($args[
'submissionIds']);
111 if (isset($args[
'count'])) {
112 $publicationQB->limitTo($args[
'count']);
115 if (isset($args[
'offset'])) {
116 $publicationQB->offsetBy($args[
'count']);
121 return $publicationQB;
128 $request = $args[
'request'];
129 $dispatcher = $request->getDispatcher();
132 $submission = !empty($args[
'submission'])
133 ? $args[
'submission']
134 : $args[
'submission'] =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
136 $submissionContext = !empty($args[
'context'])
138 : $args[
'context'] =
Services::get(
'context')->get($submission->getData(
'contextId'));
141 if (array_intersect([
'authors',
'authorsString',
'authorsStringShort',
'galleys'], $props)) {
142 $currentUserReviewAssignment = isset($args[
'currentUserReviewAssignment'])
143 ? $args[
'currentUserReviewAssignment']
145 ->getLastReviewRoundReviewAssignmentByReviewer(
146 $submission->getId(),
147 $request->getUser()->getId()
153 foreach ($props as $prop) {
156 $values[$prop] = $dispatcher->url(
159 $submissionContext->getData(
'urlPath'),
160 'submissions/' . $publication->getData(
'submissionId') .
'/publications/' . $publication->getId()
164 if ($currentUserReviewAssignment && $currentUserReviewAssignment->getReviewMethod() === SUBMISSION_REVIEW_METHOD_DOUBLEBLIND) {
167 $values[$prop] = array_map(
168 function($author) use ($request) {
169 return Services::get(
'author')->getSummaryProperties($author, [
'request' => $request]);
171 $publication->getData(
'authors')
175 case 'authorsString':
177 if ((!$currentUserReviewAssignment || $currentUserReviewAssignment->getReviewMethod() !== SUBMISSION_REVIEW_METHOD_DOUBLEBLIND)
178 && isset($args[
'userGroups'])) {
179 $values[$prop] = $publication->getAuthorString($args[
'userGroups']);
182 case 'authorsStringShort':
183 if ($currentUserReviewAssignment && $currentUserReviewAssignment->getReviewMethod() === SUBMISSION_REVIEW_METHOD_DOUBLEBLIND) {
186 $values[$prop] = $publication->getShortAuthorString();
191 $values[$prop] = array_map(
192 function($citation) {
193 return $citation->getCitationWithLinks();
195 $citationDao->getByPublicationId($publication->getId())->toArray()
199 $values[$prop] = $publication->getFullTitles();
202 if ($currentUserReviewAssignment && $currentUserReviewAssignment->getReviewMethod() === SUBMISSION_REVIEW_METHOD_DOUBLEBLIND) {
205 $galleyArgs = array_merge($args, [
'publication' => $publication]);
206 $values[$prop] = array_map(
207 function($galley) use ($request, $galleyArgs) {
208 return Services::get(
'galley')->getSummaryProperties($galley, $galleyArgs);
210 $publication->getData(
'galleys')
215 $values[$prop] = $publication->getData($prop);
222 HookRegistry::call(
'Publication::getProperties', [&$values, $publication, $props, $args]);
256 $result = $publicationDao->retrieve($publicationQO->toSql(), $publicationQO->getBindings());
257 if (!empty($result->fields)) {
258 return [$result->fields[0], $result->fields[1]];
260 import(
'classes.statistics.StatisticsHelper');
261 return [STATISTICS_EARLIEST_DATE, date(
'Y-m-d', strtotime(
'yesterday'))];
267 public function validate($action, $props, $allowedLocales, $primaryLocale) {
271 import(
'lib.pkp.classes.validation.ValidatorFactory');
276 'locale.regex' => __(
'validator.localeKey'),
277 'datePublished.date_format' => __(
'publication.datePublished.errorFormat'),
278 'urlPath.regex' => __(
'validator.alpha_dash'),
296 if (isset($props[
'submissionId'])) {
297 $validator->after(
function($validator) use ($props) {
298 if (!$validator->errors()->get(
'submissionId')) {
299 $submission = Services::get(
'submission')->get($props[
'submissionId']);
301 $validator->errors()->add(
'submissionId', __(
'publication.invalidSubmission'));
309 if (!empty($props[
'urlPath'])) {
310 $validator->after(
function($validator) use ($action, $props) {
311 if (!$validator->errors()->get(
'urlPath')) {
313 if (ctype_digit((string) $props[
'urlPath'])) {
314 $validator->errors()->add(
'urlPath', __(
'publication.urlPath.numberInvalid'));
319 if ($action === VALIDATE_ACTION_ADD && !empty($props[
'submissionId'])) {
320 $submission =
Services::get(
'submission')->get($props[
'submissionId']);
321 } elseif ($action === VALIDATE_ACTION_EDIT) {
322 $publication =
Services::get(
'publication')->get($props[
'id']);
323 $submission =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
334 if ($qb->isDuplicateUrlPath($props[
'urlPath'], $submission->getId(), $submission->getData(
'contextId'))) {
335 $validator->errors()->add(
'urlPath', __(
'publication.urlPath.duplicate'));
350 $user ? $user->getId() :
null
353 if ($validator->fails()) {
354 $errors = $schemaService->formatValidationErrors($validator->errors(), $schemaService->get(
SCHEMA_PUBLICATION), $allowedLocales);
357 HookRegistry::call(
'Publication::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
382 public function validatePublish($publication, $submission, $allowedLocales, $primaryLocale) {
387 if ($submission->getData(
'status') === STATUS_DECLINED) {
388 $errors[
'declined'] = __(
'publication.required.declined');
392 if ($submission->getData(
'stageId') < WORKFLOW_STAGE_ID_EXTERNAL_REVIEW) {
393 $errors[
'reviewStage'] = __(
'publication.required.reviewStage');
396 HookRegistry::call(
'Publication::validatePublish', [&$errors, $publication, $submission, $allowedLocales, $primaryLocale]);
404 public function add($publication, $request) {
405 $publication->stampModified();
407 $publicationId = $publicationDao->insertObject($publication);
408 $publication = $this->
get($publicationId);
409 $submission =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
412 if ($publication->getData(
'citationsRaw')) {
414 $citationDao->importCitations($publication->getId(), $publication->getData(
'citationsRaw'));
418 if ($publication->getData(
'coverImage')) {
419 $userId = $request->getUser() ? $request->getUser()->getId() :
null;
422 if ($submissionContext->getId() !== $submission->getData(
'contextId')) {
423 $submissionContext =
Services::get(
'context')->get($submission->getData(
'contextId'));
426 $supportedLocales = $submissionContext->getSupportedSubmissionLocales();
427 foreach ($supportedLocales as $localeKey) {
428 if (!array_key_exists($localeKey, $publication->getData(
'coverImage'))) {
431 $value[$localeKey] = $this->_saveFileParam($publication, $submission, $publication->getData(
'coverImage', $localeKey),
'coverImage', $userId, $localeKey,
true);
434 $publication = $this->edit($publication, [
'coverImage' => $value], $request);
440 $submission =
Services::get(
'submission')->updateStatus($submission);
455 public function version($publication, $request) {
456 $newPublication = clone $publication;
457 $newPublication->setData(
'id',
null);
458 $newPublication->setData(
'datePublished',
'');
459 $newPublication->setData(
'status', STATUS_QUEUED);
460 $newPublication->setData(
'version', $publication->getData(
'version') + 1);
461 $newPublication->stampModified();
462 $newPublication = $this->add($newPublication, $request);
464 $authors = $publication->getData(
'authors');
465 if (!empty($authors)) {
466 foreach ($authors as $author) {
467 $newAuthor = clone $author;
468 $newAuthor->setData(
'id',
null);
469 $newAuthor->setData(
'publicationId', $newPublication->getId());
470 $newAuthor =
Services::get(
'author')->add($newAuthor, $request);
472 if ($author->getId() === $publication->getData(
'primaryContactId')) {
473 $newPublication = $this->edit($newPublication, [
'primaryContactId' => $newAuthor->getId()], $request);
478 if (!empty($newPublication->getData(
'citationsRaw'))) {
480 $citationDao->importCitations($newPublication->getId(), $newPublication->getData(
'citationsRaw'));
483 $newPublication = $this->
get($newPublication->getId());
485 HookRegistry::call(
'Publication::version', [&$newPublication, $publication, $request]);
487 $submission =
Services::get(
'submission')->get($newPublication->getData(
'submissionId'));
488 import(
'lib.pkp.classes.log.SubmissionLog');
489 import(
'classes.log.SubmissionEventLogEntry');
492 return $newPublication;
498 public function edit($publication, $params, $request) {
499 $submission =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
502 if (array_key_exists(
'coverImage', $params)) {
503 $userId = $request->getUser() ? $request->getUser()->getId() :
null;
506 if ($submissionContext->getId() !== $submission->getData(
'contextId')) {
507 $submissionContext =
Services::get(
'context')->get($submission->getData(
'contextId'));
510 $supportedLocales = $submissionContext->getSupportedSubmissionLocales();
511 foreach ($supportedLocales as $localeKey) {
512 if (!array_key_exists($localeKey, $params[
'coverImage'])) {
515 $params[
'coverImage'][$localeKey] = $this->_saveFileParam($publication, $submission, $params[
'coverImage'][$localeKey],
'coverImage', $userId, $localeKey,
true);
520 $newPublication = $publicationDao->newDataObject();
521 $newPublication->_data = array_merge($publication->_data, $params);
522 $newPublication->stampModified();
524 HookRegistry::call(
'Publication::edit', [$newPublication, $publication, $params, $request]);
526 $publicationDao->updateObject($newPublication);
527 $newPublication = $this->
get($newPublication->getId());
530 if (array_key_exists(
'citationsRaw', $params)) {
532 $citationDao->importCitations($newPublication->getId(), $newPublication->getData(
'citationsRaw'));
536 import(
'lib.pkp.classes.log.SubmissionLog');
537 import(
'classes.log.SubmissionEventLogEntry');
538 SubmissionLog::logEvent($request, $submission, SUBMISSION_LOG_METADATA_UPDATE,
'submission.event.general.metadataUpdated');
540 return $newPublication;
551 $newPublication = clone $publication;
553 if (!$newPublication->getData(
'datePublished')) {
557 if (strtotime($newPublication->getData(
'datePublished')) <= strtotime(
Core::getCurrentDate())) {
558 $newPublication->setData(
'status', STATUS_PUBLISHED);
560 $newPublication->setData(
'status', STATUS_SCHEDULED);
563 $newPublication->stampModified();
566 $submission =
Services::get(
'submission')->get($newPublication->getData(
'submissionId'));
567 if ($newPublication->getData(
'status') === STATUS_PUBLISHED) {
568 if (!$newPublication->getData(
'copyrightHolder')) {
569 $newPublication->setData(
'copyrightHolder', $submission->_getContextLicenseFieldValue(
null, PERMISSIONS_FIELD_COPYRIGHT_HOLDER, $newPublication));
571 if (!$newPublication->getData(
'copyrightYear')) {
572 $newPublication->setData(
'copyrightYear', $submission->_getContextLicenseFieldValue(
null, PERMISSIONS_FIELD_COPYRIGHT_YEAR, $newPublication));
574 if (!$newPublication->getData(
'licenseUrl')) {
575 $newPublication->setData(
'licenseUrl', $submission->_getContextLicenseFieldValue(
null, PERMISSIONS_FIELD_LICENSE_URL, $newPublication));
582 $publicationDao->updateObject($newPublication);
584 $newPublication = $this->
get($newPublication->getId());
585 $submission =
Services::get(
'submission')->get($newPublication->getData(
'submissionId'));
588 if ($newPublication->getData(
'status') !== $publication->getData(
'status')) {
589 $submission =
Services::get(
'submission')->updateStatus($submission);
594 if (count($submission->getData(
'publications')) > 1) {
595 $msg = $newPublication->getData(
'status') === STATUS_SCHEDULED ?
'publication.event.versionScheduled' :
'publication.event.versionPublished';
597 $msg = $newPublication->getData(
'status') === STATUS_SCHEDULED ?
'publication.event.scheduled' :
'publication.event.published';
599 import(
'lib.pkp.classes.log.SubmissionLog');
600 import(
'classes.log.SubmissionEventLogEntry');
603 HookRegistry::call(
'Publication::publish', [$newPublication, $publication, $submission]);
606 if ($newPublication->getData(
'status') === STATUS_PUBLISHED) {
613 return $newPublication;
623 $newPublication = clone $publication;
624 $newPublication->setData(
'status', STATUS_QUEUED);
625 $newPublication->stampModified();
627 HookRegistry::call(
'Publication::unpublish::before', [$newPublication, $publication]);
630 $publicationDao->updateObject($newPublication);
631 $newPublication = $this->
get($newPublication->getId());
632 $submission =
Services::get(
'submission')->get($newPublication->getData(
'submissionId'));
635 if ($newPublication->getData(
'status') !== $publication->getData(
'status')) {
636 $submission =
Services::get(
'submission')->updateStatus($submission);
641 $msg = count($submission->getData(
'publications')) > 1 ?
'publication.event.versionUnpublished' :
'publication.event.unpublished';
642 import(
'lib.pkp.classes.log.SubmissionLog');
643 import(
'classes.log.SubmissionEventLogEntry');
646 HookRegistry::call(
'Publication::unpublish', [$newPublication, $publication, $submission]);
649 if ($submission->getData(
'status') !== STATUS_PUBLISHED) {
659 return $newPublication;
665 public function delete($publication) {
669 $publicationDao->deleteObject($publication);
672 $submission =
Services::get(
'submission')->get($publication->getData(
'submissionId'));
673 $submission = $submission =
Services::get(
'submission')->updateStatus($submission);
700 protected function _saveFileParam($publication, $submission, $value, $settingName, $userId, $localeKey =
'', $isImage =
false) {
703 if (is_null($value)) {
704 $oldPublication =
Services::get(
'publication')->get($publication->getId());
705 $oldValue = $oldPublication->getData($settingName, $localeKey);
706 $fileName = $oldValue[
'uploadName'];
710 foreach ((array) $submission->getData(
'publications') as $iPublication) {
711 if ($publication->getId() === $iPublication->getId()) {
714 $iValue = $iPublication->getData($settingName, $localeKey);
715 if (!empty($iValue[
'uploadName']) && $iValue[
'uploadName'] === $fileName) {
721 import(
'classes.file.PublicFileManager');
722 $publicFileManager = new \PublicFileManager();
723 $publicFileManager->removeContextFile($submission->getData(
'contextId'), $fileName);
730 if (empty($value[
'temporaryFileId'])) {
736 if ($submissionContext->getId() !== $submission->getData(
'contextId')) {
737 $submissionContext =
Services::get(
'context')->get($submission->getData(
'contextId'));
740 import(
'lib.pkp.classes.file.TemporaryFileManager');
741 $temporaryFileManager = new \TemporaryFileManager();
742 $temporaryFile = $temporaryFileManager->getFile((
int) $value[
'temporaryFileId'], $userId);
743 $fileNameBase = join(
'_', [
'submission', $submission->getId(), $publication->getId(), $settingName]);
744 $fileName =
Services::get(
'context')->moveTemporaryFile($submissionContext, $temporaryFile, $fileNameBase, $userId, $localeKey);
749 'altText' => !empty($value[
'altText']) ? $value[
'altText'] :
'',
751 'uploadName' => $fileName,
756 'uploadName' => $fileName,