<?php
/**
* @file classes/context/Context.php
*
* Copyright (c) 2014-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 Context
*
* @ingroup core
*
* @brief Basic class describing a context.
*/
namespace PKP\context;
use APP\core\Application;
use APP\core\Services;
use APP\plugins\IDoiRegistrationAgency;
use APP\statistics\StatisticsHelper;
use Illuminate\Support\Arr;
use PKP\config\Config;
use PKP\facades\Locale;
use PKP\i18n\LocaleMetadata;
use PKP\plugins\Plugin;
use PKP\plugins\PluginRegistry;
use PKP\site\Site;
abstract class Context extends \PKP\core\DataObject
{
// Constants used to distinguish whether metadata is enabled and whether it should be requested or required during submission
public const METADATA_DISABLE = 0;
public const METADATA_ENABLE = 'enable';
public const METADATA_REQUEST = 'request';
public const METADATA_REQUIRE = 'require';
public const SETTING_ENABLE_DOIS = 'enableDois';
public const SETTING_ENABLED_DOI_TYPES = 'enabledDoiTypes';
public const SETTING_DOI_PREFIX = 'doiPrefix';
public const SETTING_DOI_SUFFIX_TYPE = 'doiSuffixType';
public const SETTING_CONFIGURED_REGISTRATION_AGENCY = 'registrationAgency';
public const SETTING_NO_REGISTRATION_AGENCY = null;
public const SETTING_DOI_CREATION_TIME = 'doiCreationTime';
public const SETTING_DOI_AUTOMATIC_DEPOSIT = 'automaticDoiDeposit';
public const SETTING_DOI_VERSIONING = 'doiVersioning';
public const SUBMISSION_ACKNOWLEDGEMENT_OFF = null;
public const SUBMISSION_ACKNOWLEDGEMENT_SUBMITTING_AUTHOR = 'submittingAuthor';
public const SUBMISSION_ACKNOWLEDGEMENT_ALL_AUTHORS = 'allAuthors';
/**
* Whether DOIs are enabled for this context
*
*/
public function areDoisEnabled(): bool
{
return (bool) $this->getData(Context::SETTING_ENABLE_DOIS);
}
/**
* Checks if DOIs of a given type are enabled for the current context
*
* @param string $doiType One of Repo::doi()::TYPE_*
*
*/
public function isDoiTypeEnabled(string $doiType): bool
{
if (!$this->areDoisEnabled()) {
return false;
}
return in_array($doiType, $this->getData(Context::SETTING_ENABLED_DOI_TYPES) ?? []);
}
/**
* Retrieves array of enabled DOI types (items are one of Repo::doi()::TYPE_*).
*/
public function getEnabledDoiTypes(): array
{
return $this->getData(Context::SETTING_ENABLED_DOI_TYPES) ?? [];
}
/**
* Retrieves configured DOI registration agency plugin, if any active
*
*/
public function getConfiguredDoiAgency(): IDoiRegistrationAgency|Plugin|null
{
$configuredPluginName = $this->getData(Context::SETTING_CONFIGURED_REGISTRATION_AGENCY);
if (empty($configuredPluginName) || $configuredPluginName == Context::SETTING_NO_REGISTRATION_AGENCY) {
return null;
}
$plugins = PluginRegistry::getAllPlugins();
foreach ($plugins as $name => $plugin) {
if ($configuredPluginName == $name) {
if ($plugin instanceof IDoiRegistrationAgency) {
return $plugin;
}
}
}
return null;
}
/**
* Get the localized name of the context
*
* @param string $preferredLocale
*
* @return string
*/
public function getLocalizedName($preferredLocale = null)
{
return $this->getLocalizedData('name', $preferredLocale);
}
/**
* Set the name of the context
*
* @param string $name
* @param null|mixed $locale
*/
public function setName($name, $locale = null)
{
$this->setData('name', $name, $locale);
}
/**
* get the name of the context
*
* @param null|mixed $locale
*/
public function getName($locale = null)
{
return $this->getData('name', $locale);
}
/**
* Get the contact name for this context
*
* @return string
*/
public function getContactName()
{
return $this->getData('contactName');
}
/**
* Set the contact name for this context
*
* @param string $contactName
*/
public function setContactName($contactName)
{
$this->setData('contactName', $contactName);
}
/**
* Get the contact email for this context
*
* @return string
*/
public function getContactEmail()
{
return $this->getData('contactEmail');
}
/**
* Set the contact email for this context
*
* @param string $contactEmail
*/
public function setContactEmail($contactEmail)
{
$this->setData('contactEmail', $contactEmail);
}
/**
* Get context description.
*
* @param null|mixed $locale
*
* @return string
*/
public function getDescription($locale = null)
{
return $this->getData('description', $locale);
}
/**
* Set context description.
*
* @param string $description
* @param string $locale optional
*/
public function setDescription($description, $locale = null)
{
$this->setData('description', $description, $locale);
}
/**
* Get path to context (in URL).
*
* @return string
*/
public function getPath()
{
return $this->getData('urlPath');
}
/**
* Set path to context (in URL).
*
* @param string $path
*/
public function setPath($path)
{
$this->setData('urlPath', $path);
}
/**
* Get enabled flag of context
*
* @return int
*/
public function getEnabled()
{
return $this->getData('enabled');
}
/**
* Set enabled flag of context
*
* @param int $enabled
*/
public function setEnabled($enabled)
{
$this->setData('enabled', $enabled);
}
/**
* Return the primary locale of this context.
*
* @return string
*/
public function getPrimaryLocale()
{
return $this->getData('primaryLocale');
}
/**
* Set the primary locale of this context.
*/
public function setPrimaryLocale($primaryLocale)
{
$this->setData('primaryLocale', $primaryLocale);
}
/**
* Get sequence of context in site-wide list.
*
* @return float
*/
public function getSequence()
{
return $this->getData('seq');
}
/**
* Set sequence of context in site table of contents.
*
* @param float $sequence
*/
public function setSequence($sequence)
{
$this->setData('seq', $sequence);
}
/**
* Get the localized description of the context.
*
* @return string
*/
public function getLocalizedDescription()
{
return $this->getLocalizedData('description');
}
/**
* Get localized acronym of context
*
* @return string
*/
public function getLocalizedAcronym()
{
return $this->getLocalizedData('acronym');
}
/**
* Get the acronym of the context.
*
* @param string $locale
*
* @return string
*/
public function getAcronym($locale)
{
return $this->getData('acronym', $locale);
}
/**
* Get localized favicon
*
* @return string
*/
public function getLocalizedFavicon()
{
$favicons = $this->getData('favicon');
$locale = Arr::first([Locale::getLocale(), Locale::getPrimaryLocale()], fn (string $locale) => isset($favicons[$locale]));
return $favicons[$locale] ?? null;
}
/**
* Get the supported form locales.
*
* @return array
*/
public function getSupportedFormLocales(): ?array
{
return $this->getData('supportedFormLocales');
}
/**
* Return associative array of all locales supported by forms on the site.
*
* @param int $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_*
*
* @return array
*/
public function getSupportedFormLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT)
{
return $this->getData('supportedFormLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedFormLocales(), null, $langLocaleStatus);
}
/**
* Get the supported submission locales.
*
* @return array
*/
public function getSupportedSubmissionLocales()
{
return $this->getData('supportedSubmissionLocales');
}
/**
* Return associative array of all locales supported by submissions on the
* context.
*
* @param int $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_*
*
* @return array
*/
public function getSupportedSubmissionLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT)
{
return $this->getData('supportedSubmissionLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedSubmissionLocales(), null, $langLocaleStatus);
}
/**
* Get the supported locales.
*
* @return array
*/
public function getSupportedLocales()
{
return $this->getData('supportedLocales');
}
/**
* Return associative array of all locales supported by the site.
* These locales are used to provide a language toggle on the main site pages.
*
* @param int $langLocaleStatus The const value of one of LocaleMetadata:LANGUAGE_LOCALE_*
*
* @return array
*/
public function getSupportedLocaleNames(int $langLocaleStatus = LocaleMetadata::LANGUAGE_LOCALE_WITHOUT)
{
return $this->getData('supportedLocaleNames') ?? Locale::getFormattedDisplayNames($this->getSupportedLocales(), null, $langLocaleStatus);
}
/**
* Return date or/and time formats available for forms, fallback to the default if not set
*
* @param string $format datetime property, e.g., dateFormatShort
*
* @return array
*/
public function getDateTimeFormats($format)
{
$data = $this->getData($format) ?? [];
$fallbackConfigVar = strtolower(preg_replace('/([A-Z])/', '_$1', $format));
foreach ($this->getSupportedFormLocales() as $supportedLocale) {
if (!array_key_exists($supportedLocale, $data)) {
$data[$supportedLocale] = Config::getVar('general', $fallbackConfigVar);
}
}
return $data;
}
/**
* Return localized short date format, fallback to the default if not set
*
* @param null|mixed $locale
*
* @return string, see DateTime::format
*/
public function getLocalizedDateFormatShort($locale = null)
{
return $this->getData('dateFormatShort', $locale ?? Locale::getLocale()) ?: Config::getVar('general', 'date_format_short');
}
/**
* Return localized long date format, fallback to the default if not set
*
* @param null|mixed $locale
*
* @return string, see DateTime::format
*/
public function getLocalizedDateFormatLong($locale = null)
{
return $this->getData('dateFormatLong', $locale ?? Locale::getLocale()) ?: Config::getVar('general', 'date_format_long');
}
/**
* Return localized time format, fallback to the default if not set
*
* @param null|mixed $locale
*
* @return string, see DateTime::format
*/
public function getLocalizedTimeFormat($locale = null)
{
return $this->getData('timeFormat', $locale ?? Locale::getLocale()) ?: Config::getVar('general', 'time_format');
}
/**
* Return localized short date & time format, fallback to the default if not set
*
* @param null|mixed $locale
*
* @return string, see see DateTime::format
*/
public function getLocalizedDateTimeFormatShort($locale = null)
{
return $this->getData('datetimeFormatShort', $locale ?? Locale::getLocale()) ?: Config::getVar('general', 'datetime_format_short');
}
/**
* Return localized long date & time format, fallback to the default if not set
*
* @param null|mixed $locale
*
* @return string, see see DateTime::format
*/
public function getLocalizedDateTimeFormatLong($locale = null)
{
return $this->getData('datetimeFormatLong', $locale ?? Locale::getLocale()) ?: Config::getVar('general', 'datetime_format_long');
}
/**
* Get the association type for this context.
*
* @return int
*/
abstract public function getAssocType();
/**
* @deprecated Most settings should be available from self::getData(). In other cases, use the context settings DAO directly.
* @param null|mixed $locale
*/
public function getSetting($name, $locale = null)
{
return $this->getData($name, $locale);
}
/**
* @deprecated Most settings should be available from self::getData(). In other cases, use the context settings DAO directly.
* @param null|mixed $locale
*/
public function getLocalizedSetting($name, $locale = null)
{
return $this->getLocalizedData($name, $locale);
}
/**
* Update a context setting value.
*
* @param string $name
* @param string $type optional
* @param bool $isLocalized optional
*
* @deprecated 3.3.0.0
*/
public function updateSetting($name, $value, $type = null, $isLocalized = false)
{
Services::get('context')->edit($this, [$name => $value], Application::get()->getRequest());
}
/**
* Get context main page views.
*
* @deprecated 3.4
*
* @return int
*/
public function getViews()
{
$filters = [
'dateStart' => StatisticsHelper::STATISTICS_EARLIEST_DATE,
'dateEnd' => date('Y-m-d', strtotime('yesterday')),
'contextIds' => [$this->getId()],
];
$metrics = Services::get('contextStats')
->getQueryBuilder($filters)
->getSum([])
->value('metric');
return $metrics ? $metrics : 0;
}
/**
* Whether to track usage statistics by institutions.
* Consider context setting only if the site setting is enabled and context setting disabled (= false).
*/
public function isInstitutionStatsEnabled(Site $site): bool
{
$enableInstitutionUsageStats = $site->getData('enableInstitutionUsageStats');
if ($enableInstitutionUsageStats &&
($this->getData('enableInstitutionUsageStats') !== null) && !$this->getData('enableInstitutionUsageStats')) {
$enableInstitutionUsageStats = $this->getData('enableInstitutionUsageStats');
}
return (bool) $enableInstitutionUsageStats;
}
/**
* What Geo data to track for usage statistics.
* Consider context setting only if the site setting is enabled and context setting considers less Geo data than site setting.
*
* @return ?string Possible return values: null, disabled, PKPStatisticsHelper::self::STATISTICS_SETTING_COUNTRY, PKPStatisticsHelper::self::STATISTICS_SETTING_REGION, PKPStatisticsHelper::self::STATISTICS_SETTING_CITY
*/
public function getEnableGeoUsageStats(Site $site): ?string
{
$siteSetting = $site->getData('enableGeoUsageStats');
if ($siteSetting == null || $siteSetting === 'disabled') {
return $siteSetting;
}
$contextSetting = $this->getData('enableGeoUsageStats');
if ($contextSetting != null && str_starts_with($siteSetting, $contextSetting)) {
return $contextSetting;
}
return $siteSetting;
}
/**
* Get the required metadata for this context
*
* @return array List of metadata property names. Example: ['keywords']
*/
public function getRequiredMetadata(): array
{
return collect([
'agencies',
'citations',
'coverage',
'dataAvailability',
'disciplines',
'keywords',
'languages',
'rights',
'source',
'subjects',
'type',
])->filter(fn ($prop) => $this->getData($prop) === self::METADATA_REQUIRE)->toArray();
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\context\Context', '\Context');
foreach ([
'METADATA_DISABLE',
'METADATA_ENABLE',
'METADATA_REQUEST',
'METADATA_REQUIRE',
] as $constantName) {
define($constantName, constant('\Context::' . $constantName));
}
}
|