<?php
/**
* @file classes/core/PKPApplication.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class PKPApplication
*
* @ingroup core
*
* @brief Class describing this application.
*
*/
namespace PKP\core;
use APP\core\Application;
use APP\core\Request;
use DateTime;
use DateTimeZone;
use Exception;
use GuzzleHttp\Client;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\MySqlConnection;
use Illuminate\Support\Facades\DB;
use PKP\config\Config;
use PKP\db\DAORegistry;
use PKP\facades\Locale;
use PKP\security\Role;
use PKP\session\SessionManager;
use PKP\site\VersionDAO;
use PKP\submission\RepresentationDAOInterface;
interface iPKPApplicationInfoProvider
{
/**
* Get the top-level context DAO.
*/
public static function getContextDAO();
/**
* Get the representation DAO.
*/
public static function getRepresentationDAO(): RepresentationDAOInterface;
/**
* Get a SubmissionSearchIndex instance.
*/
public static function getSubmissionSearchIndex();
/**
* Get a SubmissionSearchDAO instance.
*/
public static function getSubmissionSearchDAO();
/**
* Get the stages used by the application.
*/
public static function getApplicationStages();
/**
* Get the file directory array map used by the application.
* should return array('context' => ..., 'submission' => ...)
*/
public static function getFileDirectories();
/**
* Returns the context type for this application.
*/
public static function getContextAssocType();
}
abstract class PKPApplication implements iPKPApplicationInfoProvider
{
public const PHP_REQUIRED_VERSION = '8.0.2';
// Constant used to distinguish between editorial and author workflows
public const WORKFLOW_TYPE_EDITORIAL = 'editorial';
public const WORKFLOW_TYPE_AUTHOR = 'author';
public const API_VERSION = 'v1';
public const ROUTE_COMPONENT = 'component';
public const ROUTE_PAGE = 'page';
public const ROUTE_API = 'api';
public const CONTEXT_SITE = 0;
public const CONTEXT_ID_NONE = 0;
public const CONTEXT_ID_ALL = '_';
public const REVIEW_ROUND_NONE = 0;
public const ASSOC_TYPE_PRODUCTION_ASSIGNMENT = 0x0000202;
public const ASSOC_TYPE_SUBMISSION_FILE = 0x0000203;
public const ASSOC_TYPE_REVIEW_RESPONSE = 0x0000204;
public const ASSOC_TYPE_REVIEW_ASSIGNMENT = 0x0000205;
public const ASSOC_TYPE_SUBMISSION_EMAIL_LOG_ENTRY = 0x0000206;
public const ASSOC_TYPE_WORKFLOW_STAGE = 0x0000207;
public const ASSOC_TYPE_NOTE = 0x0000208;
public const ASSOC_TYPE_REPRESENTATION = 0x0000209;
public const ASSOC_TYPE_ANNOUNCEMENT = 0x000020A;
public const ASSOC_TYPE_REVIEW_ROUND = 0x000020B;
public const ASSOC_TYPE_SUBMISSION_FILES = 0x000020F;
public const ASSOC_TYPE_PLUGIN = 0x0000211;
public const ASSOC_TYPE_SECTION = 0x0000212;
public const ASSOC_TYPE_CATEGORY = 0x000020D;
public const ASSOC_TYPE_USER = 0x0001000; // This value used because of bug #6068
public const ASSOC_TYPE_USER_GROUP = 0x0100002;
public const ASSOC_TYPE_CITATION = 0x0100003;
public const ASSOC_TYPE_AUTHOR = 0x0100004;
public const ASSOC_TYPE_EDITOR = 0x0100005;
public const ASSOC_TYPE_USER_ROLES = 0x0100007;
public const ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES = 0x0100008;
public const ASSOC_TYPE_SUBMISSION = 0x0100009;
public const ASSOC_TYPE_QUERY = 0x010000a;
public const ASSOC_TYPE_QUEUED_PAYMENT = 0x010000b;
public const ASSOC_TYPE_PUBLICATION = 0x010000c;
public const ASSOC_TYPE_ACCESSIBLE_FILE_STAGES = 0x010000d;
public const ASSOC_TYPE_NONE = 0x010000e;
public const ASSOC_TYPE_DECISION_TYPE = 0x010000f;
// Constant used in UsageStats for submission files that are not full texts
public const ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER = 0x0000213;
public $enabledProducts = [];
public $allProducts;
/**
* Constructor
*/
public function __construct()
{
if (!defined('PKP_STRICT_MODE')) {
define('PKP_STRICT_MODE', (bool) Config::getVar('general', 'strict'));
class_alias('\PKP\config\Config', '\Config');
class_alias('\PKP\core\Registry', '\Registry');
class_alias('\PKP\core\Core', '\Core');
class_alias('\PKP\cache\CacheManager', '\CacheManager');
class_alias('\PKP\handler\PKPHandler', '\PKPHandler');
class_alias('\PKP\payment\QueuedPayment', '\QueuedPayment'); // QueuedPayment instances may be serialized
}
// If not in strict mode, globally expose constants on this class.
if (!PKP_STRICT_MODE) {
foreach ([
'WORKFLOW_TYPE_EDITORIAL', 'WORKFLOW_TYPE_AUTHOR', 'PHP_REQUIRED_VERSION',
'API_VERSION',
'ROUTE_COMPONENT', 'ROUTE_PAGE', 'ROUTE_API',
'CONTEXT_SITE', 'CONTEXT_ID_NONE', 'CONTEXT_ID_ALL', 'REVIEW_ROUND_NONE',
'ASSOC_TYPE_PRODUCTION_ASSIGNMENT',
'ASSOC_TYPE_SUBMISSION_FILE',
'ASSOC_TYPE_REVIEW_RESPONSE',
'ASSOC_TYPE_REVIEW_ASSIGNMENT',
'ASSOC_TYPE_SUBMISSION_EMAIL_LOG_ENTRY',
'ASSOC_TYPE_WORKFLOW_STAGE',
'ASSOC_TYPE_NOTE',
'ASSOC_TYPE_REPRESENTATION',
'ASSOC_TYPE_ANNOUNCEMENT',
'ASSOC_TYPE_REVIEW_ROUND',
'ASSOC_TYPE_SUBMISSION_FILES',
'ASSOC_TYPE_PLUGIN',
'ASSOC_TYPE_SECTION',
'ASSOC_TYPE_CATEGORY',
'ASSOC_TYPE_USER',
'ASSOC_TYPE_USER_GROUP',
'ASSOC_TYPE_CITATION',
'ASSOC_TYPE_AUTHOR',
'ASSOC_TYPE_EDITOR',
'ASSOC_TYPE_USER_ROLES',
'ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES',
'ASSOC_TYPE_SUBMISSION',
'ASSOC_TYPE_QUERY',
'ASSOC_TYPE_QUEUED_PAYMENT',
'ASSOC_TYPE_PUBLICATION',
'ASSOC_TYPE_ACCESSIBLE_FILE_STAGES',
'ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER',
] as $constantName) {
if (!defined($constantName)) {
define($constantName, constant('self::' . $constantName));
}
}
if (!class_exists('\PKPApplication')) {
class_alias('\PKP\core\PKPApplication', '\PKPApplication');
}
}
ini_set('display_errors', Config::getVar('debug', 'display_errors', ini_get('display_errors')));
if (!static::isInstalled()) {
SessionManager::disable();
}
Registry::set('application', $this);
$microTime = Core::microtime();
Registry::set('system.debug.startTime', $microTime);
$this->initializeLaravelContainer();
PKPString::initialize();
// Load default locale files
Locale::registerPath(BASE_SYS_DIR . '/lib/pkp/locale');
if (static::isInstalled() && !static::isUpgrading()) {
$versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */
$appVersion = $versionDao->getCurrentVersion()->getVersionString();
Registry::set('appVersion', $appVersion);
}
}
/**
* Initialize Laravel container and register service providers
*/
public function initializeLaravelContainer(): void
{
// Ensure multiple calls to this function don't cause trouble
static $containerInitialized = false;
if ($containerInitialized) {
return;
}
$containerInitialized = true;
// Initialize Laravel's container and set it globally
$laravelContainer = new PKPContainer();
$laravelContainer->registerConfiguredProviders();
$this->initializeTimeZone();
if (Config::getVar('database', 'debug')) {
DB::listen(fn (QueryExecuted $query) => error_log("Database query\n{$query->sql}\n" . json_encode($query->bindings)));
}
}
/**
* Setup the internal time zone for the database and PHP.
*/
protected function initializeTimeZone(): void
{
$timeZone = null;
// Loads the time zone from the configuration file
if ($setting = Config::getVar('general', 'time_zone')) {
try {
$timeZone = (new DateTimeZone($setting))->getName();
} catch (Exception $e) {
$setting = strtolower($setting);
foreach (DateTimeZone::listIdentifiers() as $identifier) {
// Backward compatibility identification
if ($setting == strtolower(preg_replace(['/^\w+\//', '/_/'], ['', ' '], $identifier))) {
$timeZone = $identifier;
break;
}
}
}
}
// Set the default timezone
date_default_timezone_set($timeZone ?: ini_get('date.timezone') ?: 'UTC');
// Synchronize the database time zone
if (Application::isInstalled()) {
// Retrieve the current offset
$offset = (new DateTime())->format('P');
$statement = DB::connection() instanceof MySqlConnection
? "SET time_zone = '{$offset}'"
: "SET TIME ZONE INTERVAL '{$offset}' HOUR TO MINUTE";
DB::statement($statement);
}
}
/**
* @copydoc PKPApplication::get()
*
* @deprecated Use PKPApplication::get() instead.
*/
public static function getApplication()
{
return self::get();
}
/**
* Get the current application object
*
* @return Application
*/
public static function get()
{
return Registry::get('application');
}
/**
* Get the unique site ID
*/
public function getUUID(): string
{
$site = $this->getRequest()->getSite();
$uniqueSiteId = $site->getUniqueSiteID();
if (!strlen((string) $uniqueSiteId)) {
$uniqueSiteId = PKPString::generateUUID();
$site->setUniqueSiteID($uniqueSiteId);
/** @var SiteDAO */
$siteDao = DAORegistry::getDAO('SiteDAO');
$siteDao->updateObject($site);
}
return $uniqueSiteId;
}
/**
* Return a HTTP client implementation.
*
* @return Client
*/
public function getHttpClient()
{
$application = Application::get();
$userAgent = $application->getName() . '/';
if (static::isInstalled() && !static::isUpgrading()) {
/** @var \PKP\site\VersionDAO */
$versionDao = DAORegistry::getDAO('VersionDAO');
$currentVersion = $versionDao->getCurrentVersion();
$userAgent .= $currentVersion->getVersionString();
} else {
$userAgent .= '?';
}
return new Client([
'proxy' => [
'http' => Config::getVar('proxy', 'http_proxy', null),
'https' => Config::getVar('proxy', 'https_proxy', null),
],
'headers' => [
'User-Agent' => $userAgent,
],
'allow_redirects' => ['strict' => true],
]);
}
/**
* Get the request implementation singleton
*
* @return Request
*/
public function getRequest()
{
$request = & Registry::get('request', true, null); // Ref req'd
if (is_null($request)) {
// Implicitly set request by ref in the registry
$request = new Request();
}
return $request;
}
/**
* Get the dispatcher implementation singleton
*
* @return Dispatcher
*/
public function getDispatcher()
{
$dispatcher = & Registry::get('dispatcher', true, null); // Ref req'd
if (is_null($dispatcher)) {
// Implicitly set dispatcher by ref in the registry
$dispatcher = new Dispatcher();
// Inject dependency
$dispatcher->setApplication(PKPApplication::get());
// Inject router configuration
$dispatcher->addRouterName('\PKP\core\APIRouter', self::ROUTE_API);
$dispatcher->addRouterName('\PKP\core\PKPComponentRouter', self::ROUTE_COMPONENT);
$dispatcher->addRouterName('\APP\core\PageRouter', self::ROUTE_PAGE);
}
return $dispatcher;
}
/**
* This executes the application by delegating the
* request to the dispatcher.
*/
public function execute()
{
// Dispatch the request to the correct handler
$dispatcher = $this->getDispatcher();
$dispatcher->dispatch($this->getRequest());
}
/**
* Get the symbolic name of this application
*
* @return string
*/
public static function getName()
{
return 'pkp-lib';
}
/**
* Get the locale key for the name of this application.
*
* @return string
*/
abstract public function getNameKey();
/**
* Get the name of the context for this application
*/
abstract public function getContextName(): string;
/**
* Get the URL to the XML descriptor for the current version of this
* application.
*
* @return string
*/
abstract public function getVersionDescriptorUrl();
/**
* This function retrieves all enabled product versions once
* from the database and caches the result for further
* access.
*
* @param string $category
* @param int $mainContextId Optional ID of the top-level context
* (e.g. Journal, Conference, Press) to query for enabled products
*
* @return array
*/
public function getEnabledProducts($category = null, $mainContextId = null)
{
if (is_null($mainContextId)) {
$request = $this->getRequest();
$router = $request->getRouter();
$mainContextId = $router->getContext($request)?->getId() ?? self::CONTEXT_SITE;
}
if (!isset($this->enabledProducts[$mainContextId])) {
$versionDao = DAORegistry::getDAO('VersionDAO'); /** @var \PKP\site\VersionDAO $versionDao */
$this->enabledProducts[$mainContextId] = $versionDao->getCurrentProducts($mainContextId);
}
if (is_null($category)) {
return $this->enabledProducts[$mainContextId];
} elseif (isset($this->enabledProducts[$mainContextId][$category])) {
return $this->enabledProducts[$mainContextId][$category];
} else {
return [];
}
}
/**
* Get the list of plugin categories for this application.
*
* @return array
*/
abstract public function getPluginCategories();
/**
* Return the current version of the application.
*
* @return \PKP\site\Version
*/
public function getCurrentVersion()
{
$currentVersion = $this->getEnabledProducts('core');
assert(count($currentVersion)) == 1;
return $currentVersion[$this->getName()];
}
/**
* Get the map of DAOName => full.class.Path for this application.
*
* @return array
*/
public function getDAOMap()
{
return [
'AccessKeyDAO' => 'PKP\security\AccessKeyDAO',
'AnnouncementDAO' => 'PKP\announcement\AnnouncementDAO',
'AnnouncementTypeDAO' => 'PKP\announcement\AnnouncementTypeDAO',
'CitationDAO' => 'PKP\citation\CitationDAO',
'ControlledVocabDAO' => 'PKP\controlledVocab\ControlledVocabDAO',
'ControlledVocabEntryDAO' => 'PKP\controlledVocab\ControlledVocabEntryDAO',
'DataObjectTombstoneDAO' => 'PKP\tombstone\DataObjectTombstoneDAO',
'DataObjectTombstoneSettingsDAO' => 'PKP\tombstone\DataObjectTombstoneSettingsDAO',
'FilterDAO' => 'PKP\filter\FilterDAO',
'FilterGroupDAO' => 'PKP\filter\FilterGroupDAO',
'GenreDAO' => 'PKP\submission\GenreDAO',
'InterestDAO' => 'PKP\user\InterestDAO',
'InterestEntryDAO' => 'PKP\user\InterestEntryDAO',
'LibraryFileDAO' => 'PKP\context\LibraryFileDAO',
'NavigationMenuDAO' => 'PKP\navigationMenu\NavigationMenuDAO',
'NavigationMenuItemDAO' => 'PKP\navigationMenu\NavigationMenuItemDAO',
'NavigationMenuItemAssignmentDAO' => 'PKP\navigationMenu\NavigationMenuItemAssignmentDAO',
'NoteDAO' => 'PKP\note\NoteDAO',
'NotificationDAO' => 'PKP\notification\NotificationDAO',
'NotificationSettingsDAO' => 'PKP\notification\NotificationSettingsDAO',
'NotificationSubscriptionSettingsDAO' => 'PKP\notification\NotificationSubscriptionSettingsDAO',
'PluginGalleryDAO' => 'PKP\plugins\PluginGalleryDAO',
'PluginSettingsDAO' => 'PKP\plugins\PluginSettingsDAO',
'PublicationDAO' => 'APP\publication\PublicationDAO',
'QueuedPaymentDAO' => 'PKP\payment\QueuedPaymentDAO',
'ReviewAssignmentDAO' => 'PKP\submission\reviewAssignment\ReviewAssignmentDAO',
'ReviewFilesDAO' => 'PKP\submission\ReviewFilesDAO',
'ReviewFormDAO' => 'PKP\reviewForm\ReviewFormDAO',
'ReviewFormElementDAO' => 'PKP\reviewForm\ReviewFormElementDAO',
'ReviewFormResponseDAO' => 'PKP\reviewForm\ReviewFormResponseDAO',
'ReviewRoundDAO' => 'PKP\submission\reviewRound\ReviewRoundDAO',
'RoleDAO' => 'PKP\security\RoleDAO',
'ScheduledTaskDAO' => 'PKP\scheduledTask\ScheduledTaskDAO',
'SessionDAO' => 'PKP\session\SessionDAO',
'SiteDAO' => 'PKP\site\SiteDAO',
'StageAssignmentDAO' => 'PKP\stageAssignment\StageAssignmentDAO',
'SubEditorsDAO' => 'PKP\context\SubEditorsDAO',
'SubmissionAgencyDAO' => 'PKP\submission\SubmissionAgencyDAO',
'SubmissionAgencyEntryDAO' => 'PKP\submission\SubmissionAgencyEntryDAO',
'SubmissionCommentDAO' => 'PKP\submission\SubmissionCommentDAO',
'SubmissionDisciplineDAO' => 'PKP\submission\SubmissionDisciplineDAO',
'SubmissionDisciplineEntryDAO' => 'PKP\submission\SubmissionDisciplineEntryDAO',
'SubmissionEmailLogDAO' => 'PKP\log\SubmissionEmailLogDAO',
'QueryDAO' => 'PKP\query\QueryDAO',
'SubmissionLanguageDAO' => 'PKP\submission\SubmissionLanguageDAO',
'SubmissionLanguageEntryDAO' => 'PKP\submission\SubmissionLanguageEntryDAO',
'SubmissionKeywordDAO' => 'PKP\submission\SubmissionKeywordDAO',
'SubmissionKeywordEntryDAO' => 'PKP\submission\SubmissionKeywordEntryDAO',
'SubmissionSubjectDAO' => 'PKP\submission\SubmissionSubjectDAO',
'SubmissionSubjectEntryDAO' => 'PKP\submission\SubmissionSubjectEntryDAO',
'TemporaryFileDAO' => 'PKP\file\TemporaryFileDAO',
'TemporaryInstitutionsDAO' => 'PKP\statistics\TemporaryInstitutionsDAO',
'UserStageAssignmentDAO' => 'PKP\user\UserStageAssignmentDAO',
'VersionDAO' => 'PKP\site\VersionDAO',
'WorkflowStageDAO' => 'PKP\workflow\WorkflowStageDAO',
'XMLDAO' => 'PKP\db\XMLDAO',
];
}
/**
* Return the fully-qualified (e.g. page.name.ClassNameDAO) name of the
* given DAO.
*
* @param string $name
*
* @return string
*/
public function getQualifiedDAOName($name)
{
$map = & Registry::get('daoMap', true, $this->getDAOMap()); // Ref req'd
if (isset($map[$name])) {
return $map[$name];
}
return null;
}
/**
* Get a mapping of license URL to license locale key for common
* creative commons licenses.
*
* @return array
*/
public static function getCCLicenseOptions()
{
return [
'https://creativecommons.org/licenses/by-nc-nd/4.0' => 'submission.license.cc.by-nc-nd4',
'https://creativecommons.org/licenses/by-nc/4.0' => 'submission.license.cc.by-nc4',
'https://creativecommons.org/licenses/by-nc-sa/4.0' => 'submission.license.cc.by-nc-sa4',
'https://creativecommons.org/licenses/by-nd/4.0' => 'submission.license.cc.by-nd4',
'https://creativecommons.org/licenses/by/4.0' => 'submission.license.cc.by4',
'https://creativecommons.org/licenses/by-sa/4.0' => 'submission.license.cc.by-sa4'
];
}
/**
* Get the Creative Commons license badge associated with a given
* license URL.
*
* @param ?string $ccLicenseURL URL to creative commons license
* @param ?string $locale Optional locale to return badge in
*
* @return ?string HTML code for CC license
*/
public function getCCLicenseBadge($ccLicenseURL, $locale = null)
{
if (!$ccLicenseURL) {
return null;
}
$licenseKeyMap = [
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc-nd/4.0[/]?|' => 'submission.license.cc.by-nc-nd4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc/4.0[/]?|' => 'submission.license.cc.by-nc4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc-sa/4.0[/]?|' => 'submission.license.cc.by-nc-sa4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nd/4.0[/]?|' => 'submission.license.cc.by-nd4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by/4.0[/]?|' => 'submission.license.cc.by4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-sa/4.0[/]?|' => 'submission.license.cc.by-sa4.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc-nd/3.0[/]?|' => 'submission.license.cc.by-nc-nd3.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc/3.0[/]?|' => 'submission.license.cc.by-nc3.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nc-sa/3.0[/]?|' => 'submission.license.cc.by-nc-sa3.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-nd/3.0[/]?|' => 'submission.license.cc.by-nd3.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by/3.0[/]?|' => 'submission.license.cc.by3.footer',
'|http[s]?://(www\.)?creativecommons.org/licenses/by-sa/3.0[/]?|' => 'submission.license.cc.by-sa3.footer'
];
$locale ??= Locale::getLocale();
foreach ($licenseKeyMap as $pattern => $key) {
if (preg_match($pattern, $ccLicenseURL)) {
return __($key, [], $locale);
}
}
return null;
}
/**
* Get a mapping of role keys and i18n key names.
*
* @param bool $contextOnly If false, also returns site-level roles (Site admin)
* @param array|null $roleIds Only return role names of these IDs
*
* @return array
*/
public static function getRoleNames($contextOnly = false, $roleIds = null)
{
$siteRoleNames = [Role::ROLE_ID_SITE_ADMIN => 'user.role.siteAdmin'];
$appRoleNames = [
Role::ROLE_ID_MANAGER => 'user.role.manager',
Role::ROLE_ID_SUB_EDITOR => 'user.role.subEditor',
Role::ROLE_ID_ASSISTANT => 'user.role.assistant',
Role::ROLE_ID_AUTHOR => 'user.role.author',
Role::ROLE_ID_REVIEWER => 'user.role.reviewer',
Role::ROLE_ID_READER => 'user.role.reader',
];
$roleNames = $contextOnly ? $appRoleNames : $siteRoleNames + $appRoleNames;
if (!empty($roleIds)) {
$roleNames = array_intersect_key($roleNames, array_flip($roleIds));
}
return $roleNames;
}
/**
* Get a mapping of roles allowed to access particular workflows
*
* @return array
*/
public static function getWorkflowTypeRoles()
{
return [
self::WORKFLOW_TYPE_EDITORIAL => [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT],
self::WORKFLOW_TYPE_AUTHOR => [Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_AUTHOR],
];
}
/**
* Get the name of a workflow stage
*
* @param int $stageId One of the WORKFLOW_STAGE_* constants
*/
public static function getWorkflowStageName(int $stageId): string
{
return match ($stageId) {
WORKFLOW_STAGE_ID_SUBMISSION => 'submission.submission',
WORKFLOW_STAGE_ID_INTERNAL_REVIEW => 'workflow.review.internalReview',
WORKFLOW_STAGE_ID_EXTERNAL_REVIEW => 'workflow.review.externalReview',
WORKFLOW_STAGE_ID_EDITING => 'submission.editorial',
WORKFLOW_STAGE_ID_PRODUCTION => 'submission.production',
default => new Exception('Name requested for an unrecognized stage id.')
};
}
/**
* Get the hex color (#000000) of a workflow stage
*
* @param int $stageId One of the WORKFLOW_STAGE_* constants
*
* @return string
*/
public static function getWorkflowStageColor($stageId)
{
switch ($stageId) {
case WORKFLOW_STAGE_ID_SUBMISSION: return '#d00a0a';
case WORKFLOW_STAGE_ID_INTERNAL_REVIEW: return '#e05c14';
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW: return '#e08914';
case WORKFLOW_STAGE_ID_EDITING: return '#006798';
case WORKFLOW_STAGE_ID_PRODUCTION: return '#00b28d';
}
throw new Exception('Color requested for an unrecognized stage id.');
}
/**
* Get a human-readable version of the max file upload size
*/
public static function getReadableMaxFileSize(): string
{
return strtoupper(UPLOAD_MAX_FILESIZE) . 'B';
}
/**
* Convert the max upload size to an integer in MBs
*/
public static function getIntMaxFileMBs(): int
{
$size = (int) UPLOAD_MAX_FILESIZE;
$unit = strtolower(substr(UPLOAD_MAX_FILESIZE, -1));
// No suffix fallbacks to "byte"
match (ctype_alpha($unit) ? $unit : 'b') {
'g' => $size <<= 10,
'm' => null,
'k' => $size >>= 10,
'b' => $size >>= 20,
default => error_log(sprintf('Invalid value for the PHP configuration upload_max_filesize "%s"', UPLOAD_MAX_FILESIZE))
};
return floor($size);
}
/**
* Get the supported metadata setting names for this application
*
* @return array
*/
public static function getMetadataFields()
{
return [
'coverage',
'languages',
'rights',
'source',
'subjects',
'type',
'disciplines',
'keywords',
'agencies',
'citations',
'dataAvailability',
];
}
/**
* Retrieves whether the application is installed
*/
public static function isInstalled(): bool
{
return !!Config::getVar('general', 'installed');
}
/**
* Retrieves whether the application is running an upgrade
*/
public static function isUpgrading(): bool
{
return defined('RUNNING_UPGRADE');
}
/**
* Retrieves whether the application is under maintenance (not installed or being upgraded)
*/
public static function isUnderMaintenance(): bool
{
return !static::isInstalled() || static::isUpgrading();
}
/**
* Signals the application is undergoing an upgrade
*/
public static function upgrade(): void
{
// Constant kept for backwards compatibility
if (!defined('RUNNING_UPGRADE')) {
define('RUNNING_UPGRADE', true);
}
}
/**
* Get the property name for a section id
*
* In OMP, the section is referred to as a series and the
* property name is different.
*/
public static function getSectionIdPropName(): string
{
return 'sectionId';
}
}
define('REALLY_BIG_NUMBER', 10000);
define('UPLOAD_MAX_FILESIZE', trim(ini_get('upload_max_filesize')));
define('WORKFLOW_STAGE_ID_PUBLISHED', 0); // FIXME? See bug #6463.
define('WORKFLOW_STAGE_ID_SUBMISSION', 1);
define('WORKFLOW_STAGE_ID_INTERNAL_REVIEW', 2);
define('WORKFLOW_STAGE_ID_EXTERNAL_REVIEW', 3);
define('WORKFLOW_STAGE_ID_EDITING', 4);
define('WORKFLOW_STAGE_ID_PRODUCTION', 5);
/* TextArea insert tag variable types used to change their display when selected */
define('INSERT_TAG_VARIABLE_TYPE_PLAIN_TEXT', 'PLAIN_TEXT');
|