first commit
This commit is contained in:
@@ -0,0 +1,438 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/publication/PKPPublication.php
|
||||
*
|
||||
* Copyright (c) 2016-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 PKPPublication
|
||||
*
|
||||
* @ingroup publication
|
||||
*
|
||||
* @see DAO
|
||||
*
|
||||
* @brief Base class for Publication.
|
||||
*/
|
||||
|
||||
namespace PKP\publication;
|
||||
|
||||
use APP\author\Author;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\Core;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\userGroup\UserGroup;
|
||||
|
||||
class PKPPublication extends \PKP\core\DataObject
|
||||
{
|
||||
/**
|
||||
* Get the default/fall back locale the values should exist for
|
||||
*/
|
||||
public function getDefaultLocale(): ?string
|
||||
{
|
||||
return $this->getData('locale');
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the localized title, prefix and subtitle
|
||||
*
|
||||
* @param string $preferredLocale Override the publication's default locale and return the title in a specified locale.
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedFullTitle($preferredLocale = null, string $format = 'text')
|
||||
{
|
||||
$fullTitle = $this->getLocalizedTitle($preferredLocale, $format);
|
||||
$subtitle = $this->getLocalizedSubTitle($preferredLocale, $format);
|
||||
|
||||
if ($subtitle) {
|
||||
return PKPString::concatTitleFields([$fullTitle, $subtitle]);
|
||||
}
|
||||
|
||||
return $fullTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the combined prefix, title and subtitle for all locales
|
||||
*
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFullTitles(string $format = 'text')
|
||||
{
|
||||
$allTitles = (array) $this->getData('title');
|
||||
$return = [];
|
||||
foreach ($allTitles as $locale => $title) {
|
||||
if (!$title) {
|
||||
continue;
|
||||
}
|
||||
$return[$locale] = $this->getLocalizedFullTitle($locale, $format);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the localized title and prefix
|
||||
*
|
||||
* @param string $preferredLocale Override the publication's default locale and return the title in a specified locale.
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedTitle($preferredLocale = null, string $format = 'text')
|
||||
{
|
||||
$usedLocale = null;
|
||||
$title = $this->getLocalizedData('title', $preferredLocale, $usedLocale);
|
||||
$prefix = $this->getData('prefix', $usedLocale);
|
||||
|
||||
switch (strtolower($format)) {
|
||||
case 'html':
|
||||
// Title is already in HTML, prefix is in text. Convert prefix.
|
||||
if ($prefix) {
|
||||
$prefix = htmlspecialchars($prefix);
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
// Title is in HTML, prefix is already in text. Convert title.
|
||||
$title = strip_tags($title);
|
||||
break;
|
||||
default: throw new \Exception('Invalid format!');
|
||||
}
|
||||
|
||||
if ($prefix) {
|
||||
$title = $prefix . ' ' . $title;
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the localized sub title
|
||||
*
|
||||
* @param string $preferredLocale Override the publication's default locale and return the title in a specified locale.
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalizedSubTitle($preferredLocale = null, string $format = 'text')
|
||||
{
|
||||
$subTitle = $this->getLocalizedData('subtitle', $preferredLocale);
|
||||
|
||||
if ($subTitle) {
|
||||
return strtolower($format) === 'text' ? strip_tags($subTitle) : $subTitle;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the combined title and prefix for all locales
|
||||
*
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTitles(string $format = 'text')
|
||||
{
|
||||
$allTitles = $this->getData('title');
|
||||
$return = [];
|
||||
foreach ($allTitles as $locale => $title) {
|
||||
if (!$title) {
|
||||
continue;
|
||||
}
|
||||
$return[$locale] = $this->getLocalizedTitle($locale, $format);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the sub titles
|
||||
*
|
||||
* @param string $format Define the return data format as text or html
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSubTitles(string $format = 'text')
|
||||
{
|
||||
$allSubTitles = $this->getData('subtitle');
|
||||
$return = [];
|
||||
foreach ($allSubTitles ?? [] as $locale => $subTitle) {
|
||||
if (!$subTitle) {
|
||||
continue;
|
||||
}
|
||||
$return[$locale] = $this->getLocalizedSubTitle($locale, $format);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine author names and roles into a string
|
||||
*
|
||||
* Eg - Daniel Barnes, Carlo Corino (Author); Alan Mwandenga (Translator)
|
||||
*
|
||||
* @param \Traversable<UserGroup> $userGroups List of UserGroup objects
|
||||
* @param bool $includeInBrowseOnly true if only the includeInBrowse Authors will be contained
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthorString(\Traversable $userGroups, $includeInBrowseOnly = false)
|
||||
{
|
||||
$authors = $this->getData('authors');
|
||||
|
||||
if (empty($authors)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($includeInBrowseOnly) {
|
||||
$authors = $authors->filter(function ($author, $key) {
|
||||
return $author->getData('includeInBrowse');
|
||||
});
|
||||
}
|
||||
|
||||
$str = '';
|
||||
$lastUserGroupId = null;
|
||||
foreach ($authors as $author) {
|
||||
if (!empty($str)) {
|
||||
if ($lastUserGroupId != $author->getData('userGroupId')) {
|
||||
foreach ($userGroups as $userGroup) {
|
||||
if ($lastUserGroupId === $userGroup->getId()) {
|
||||
if ($userGroup->getData('showTitle')) {
|
||||
$str .= ' (' . $userGroup->getLocalizedData('name') . ')';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
$str .= __('common.semicolonListSeparator');
|
||||
} else {
|
||||
$str .= __('common.commaListSeparator');
|
||||
}
|
||||
}
|
||||
$str .= $author->getFullName();
|
||||
$lastUserGroupId = $author->getUserGroupId();
|
||||
}
|
||||
|
||||
// If there needs to be a trailing user group title, add it
|
||||
if (isset($author)) {
|
||||
foreach ($userGroups as $userGroup) {
|
||||
if ($author->getData('userGroupId') === $userGroup->getId()) {
|
||||
if ($userGroup->getData('showTitle')) {
|
||||
$str .= ' (' . $userGroup->getLocalizedData('name') . ')';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the author names into a shortened string
|
||||
*
|
||||
* Eg - Barnes, et al.
|
||||
*
|
||||
* @param string|null $defaultLocale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getShortAuthorString($defaultLocale = null)
|
||||
{
|
||||
$authors = $this->getData('authors');
|
||||
|
||||
if (!$authors->count()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$firstAuthor = $authors->first();
|
||||
|
||||
$str = $firstAuthor->getLocalizedData('familyName', $defaultLocale);
|
||||
if (!$str) {
|
||||
$str = $firstAuthor->getLocalizedData('givenName', $defaultLocale);
|
||||
}
|
||||
|
||||
if ($authors->count() > 1) {
|
||||
return __('submission.shortAuthor', ['author' => $str], $defaultLocale);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary contact
|
||||
*
|
||||
* @return Author|null
|
||||
*/
|
||||
public function getPrimaryAuthor()
|
||||
{
|
||||
if (empty($this->getData('authors'))) {
|
||||
return null;
|
||||
}
|
||||
foreach ($this->getData('authors') as $author) {
|
||||
if ($author->getId() === $this->getData('primaryContactId')) {
|
||||
return $author;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stamp the date of the last modification to the current time.
|
||||
*/
|
||||
public function stampModified()
|
||||
{
|
||||
return $this->setData('lastModified', Core::getCurrentDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the starting page of this publication
|
||||
*
|
||||
* Note the return type of string - this is not to be used for
|
||||
* page counting.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStartingPage()
|
||||
{
|
||||
$ranges = $this->getPageArray();
|
||||
$firstRange = array_shift($ranges);
|
||||
if (is_array($firstRange)) {
|
||||
return array_shift($firstRange);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ending page of a this publication
|
||||
*
|
||||
* Note the return type of string - this is not to be used for
|
||||
* page counting.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEndingPage()
|
||||
{
|
||||
$ranges = $this->getPageArray();
|
||||
$lastRange = array_pop($ranges);
|
||||
$lastPage = is_array($lastRange) ? array_pop($lastRange) : '';
|
||||
return $lastPage ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pages converted to a nested array of page ranges
|
||||
*
|
||||
* For example, pages of "pp. ii-ix, 9,15-18,a2,b2-b6" will return:
|
||||
*
|
||||
* [
|
||||
* ['ii', 'ix'],
|
||||
* ['9'],
|
||||
* ['15', '18'],
|
||||
* ['a2'],
|
||||
* ['b2', 'b6'],
|
||||
* ]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPageArray()
|
||||
{
|
||||
$pages = $this->getData('pages') ?? '';
|
||||
// Strip any leading word
|
||||
if (preg_match('/^[[:alpha:]]+\W/', $pages)) {
|
||||
// but don't strip a leading roman numeral
|
||||
if (!preg_match('/^[MDCLXVUI]+\W/i', $pages)) {
|
||||
// strip the word or abbreviation, including the period or colon
|
||||
$pages = preg_replace('/^[[:alpha:]]+[:.]?/', '', $pages);
|
||||
}
|
||||
}
|
||||
// strip leading and trailing space
|
||||
$pages = trim($pages);
|
||||
// shortcut the explode/foreach if the remainder is an empty value
|
||||
if ($pages === '') {
|
||||
return [];
|
||||
}
|
||||
// commas indicate distinct ranges
|
||||
$ranges = explode(',', $pages);
|
||||
$pageArray = [];
|
||||
foreach ($ranges as $range) {
|
||||
// hyphens (or double-hyphens) indicate range spans
|
||||
$pageArray[] = array_map('trim', explode('-', str_replace(['--', '–'], '-', $range), 2));
|
||||
}
|
||||
return $pageArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the license for copyright on this publication a Creative Commons license?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCCLicense()
|
||||
{
|
||||
return preg_match('/creativecommons\.org/i', $this->getData('licenseUrl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to fetch current DOI
|
||||
*
|
||||
*/
|
||||
public function getDoi(): ?string
|
||||
{
|
||||
$doiObject = $this->getData('doiObject');
|
||||
|
||||
if (empty($doiObject)) {
|
||||
return null;
|
||||
} else {
|
||||
return $doiObject->getData('doi');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stored public ID of the publication
|
||||
*
|
||||
* This helper function is required by PKPPubIdPlugins.
|
||||
* NB: To maintain backwards compatability, getDoi() is called from here
|
||||
*
|
||||
* @see Submission::getStoredPubId()
|
||||
*/
|
||||
public function getStoredPubId($pubIdType)
|
||||
{
|
||||
if ($pubIdType === 'doi') {
|
||||
return $this->getDoi();
|
||||
} else {
|
||||
return $this->getData('pub-id::' . $pubIdType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stored public issue id.
|
||||
*
|
||||
* @param string $pubIdType One of the NLM pub-id-type values or
|
||||
* 'other::something' if not part of the official NLM list
|
||||
* (see <http://dtd.nlm.nih.gov/publishing/tag-library/n-4zh0.html>).
|
||||
* @param string $pubId
|
||||
*/
|
||||
public function setStoredPubId($pubIdType, $pubId)
|
||||
{
|
||||
if ($pubIdType == 'doi') {
|
||||
if ($doiObject = $this->getData('doiObject')) {
|
||||
Repo::doi()->edit($doiObject, ['doi' => $pubId]);
|
||||
} else {
|
||||
$newDoiObject = Repo::doi()->newDataObject(
|
||||
[
|
||||
'doi' => $pubId,
|
||||
'contextId' => Repo::submission()->get($this->getData('submissionId'))->getData('contextId')
|
||||
]
|
||||
);
|
||||
$doiId = Repo::doi()->add($newDoiObject);
|
||||
|
||||
$this->setData('doiId', $doiId);
|
||||
}
|
||||
} else {
|
||||
$this->setData('pub-id::' . $pubIdType, $pubId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\publication\PKPPublication', '\PKPPublication');
|
||||
}
|
||||
Reference in New Issue
Block a user