[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
classes
/
install
/
[
Home
]
File: Installer.php
<?php /** * @file classes/install/Installer.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 Installer * * @ingroup install * * @brief Base class for install and upgrade scripts. */ namespace PKP\install; use adoSchema; use APP\core\Application; use APP\facades\Repo; use APP\file\LibraryFileManager; use Exception; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use PKP\cache\CacheManager; use PKP\config\Config; use PKP\context\Context; use PKP\context\LibraryFile; use PKP\core\Core; use PKP\core\PKPContainer; use PKP\core\PKPApplication; use PKP\db\DAORegistry; use PKP\db\DAOResultFactory; use PKP\db\DBDataXMLParser; use PKP\db\XMLDAO; use PKP\facades\Locale; use PKP\file\FileManager; use PKP\filter\FilterHelper; use PKP\navigationMenu\NavigationMenuDAO; use PKP\notification\PKPNotification; use PKP\plugins\Hook; use PKP\plugins\PluginRegistry; use PKP\security\Role; use PKP\site\SiteDAO; use PKP\site\Version; use PKP\site\VersionCheck; use PKP\site\VersionDAO; use PKP\xml\PKPXMLParser; use PKP\xml\XMLNode; class Installer { // Installer error codes public const INSTALLER_ERROR_GENERAL = 1; public const INSTALLER_ERROR_DB = 2; public const INSTALLER_DATA_DIR = 'dbscripts/xml'; public const INSTALLER_DEFAULT_LOCALE = 'en'; /** @var string descriptor path (relative to INSTALLER_DATA_DIR) */ public $descriptor; /** @var bool indicates if a plugin is being installed (thus modifying the descriptor path) */ public $isPlugin; /** @var array installation parameters */ public $params; /** @var Version currently installed version */ public $currentVersion; /** @var Version version after installation */ public $newVersion; /** @var string default locale */ public $locale; /** @var array available locales */ public $installedLocales; /** @var DBDataXMLParser database data parser */ public $dataXMLParser; /** @var array installer actions to be performed */ public $actions; /** @var array SQL statements for database installation */ public $sql; /** @var array installation notes */ public $notes; /** @var string contents of the updated config file */ public $configContents; /** @var bool indicating if config file was written or not */ public $wroteConfig; /** @var int error code (null | INSTALLER_ERROR_GENERAL | INSTALLER_ERROR_DB) */ public $errorType; /** @var string the error message, if an installation error has occurred */ public $errorMsg; /** @var object logging object */ public $logger; /** @var array List of migrations executed already */ public $migrations = []; /** @var array List of email template variables to rename. App-specific */ protected $appEmailTemplateVariableNames = []; /** * Constructor. * * @param string $descriptor descriptor path * @param array $params installer parameters * @param bool $isPlugin true iff a plugin is being installed */ public function __construct($descriptor, $params = [], $isPlugin = false) { // Load all plugins. If any of them use installer hooks, // they'll need to be loaded here. PluginRegistry::loadAllPlugins(); $this->isPlugin = $isPlugin; // Give the Hook registry the opportunity to override this // method or alter its parameters. if (!Hook::call('Installer::Installer', [$this, &$descriptor, &$params])) { $this->descriptor = $descriptor; $this->params = $params; $this->actions = []; $this->sql = []; $this->notes = []; $this->wroteConfig = true; } } /** * Returns true iff this is an upgrade process. */ public function isUpgrade() { exit('ABSTRACT CLASS'); } /** * Destroy / clean-up after the installer. */ public function destroy() { Hook::call('Installer::destroy', [$this]); } /** * Pre-installation. * * @return bool */ public function preInstall() { $this->log('pre-install'); if (!isset($this->currentVersion)) { // Retrieve the currently installed version $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */ $this->currentVersion = $versionDao->getCurrentVersion(); } if (!isset($this->locale)) { $this->locale = Locale::getLocale(); } if (!isset($this->installedLocales)) { $this->installedLocales = array_keys(Locale::getLocales()); } if (!isset($this->dataXMLParser)) { $this->dataXMLParser = new DBDataXMLParser(); } $result = true; Hook::call('Installer::preInstall', [$this, &$result]); return $result; } /** * Installation. * * @return bool */ public function execute() { // Ensure that the installation will not get interrupted if it takes // longer than max_execution_time (php.ini). Note that this does not // work under safe mode. @set_time_limit(0); if (!$this->preInstall()) { return false; } if (!$this->parseInstaller()) { return false; } if (!$this->executeInstaller()) { return false; } if (!$this->postInstall()) { return false; } return $this->updateVersion(); } /** * Post-installation. * * @return bool */ public function postInstall() { $this->log('post-install'); $result = true; Hook::call('Installer::postInstall', [$this, &$result]); return $result; } /** * Record message to installation log. * * @param string $message */ public function log($message) { if (isset($this->logger)) { call_user_func([$this->logger, 'log'], $message); } } // // Main actions // /** * Parse the installation descriptor XML file. * * @return bool */ public function parseInstaller() { // Read installation descriptor file $this->log(sprintf('load: %s', $this->descriptor)); $xmlParser = new PKPXMLParser(); $installPath = $this->isPlugin ? $this->descriptor : self::INSTALLER_DATA_DIR . "/{$this->descriptor}"; $installTree = $xmlParser->parse($installPath); if (!$installTree) { // Error reading installation file $this->setError(self::INSTALLER_ERROR_GENERAL, 'installer.installFileError'); return false; } $versionString = $installTree->getAttribute('version'); if (isset($versionString)) { $this->newVersion = Version::fromString($versionString); } else { $this->newVersion = $this->currentVersion; } // Parse descriptor $this->parseInstallNodes($installTree); $result = $this->getErrorType() == 0; Hook::call('Installer::parseInstaller', [$this, &$result]); return $result; } /** * Execute the installer actions. * * @return bool */ public function executeInstaller() { $this->log(sprintf('version: %s', $this->newVersion->getVersionString(false))); foreach ($this->actions as $action) { if (!$this->executeAction($action)) { return false; } } $result = true; Hook::call('Installer::executeInstaller', [$this, &$result]); return $result; } /** * Update the version number. * * @return bool */ public function updateVersion() { if ($this->newVersion->compare($this->currentVersion) > 0) { $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */ if (!$versionDao->insertVersion($this->newVersion)) { return false; } } $result = true; Hook::call('Installer::updateVersion', [$this, &$result]); return $result; } // // Installer Parsing // /** * Parse children nodes in the install descriptor. * * @param XMLNode $installTree */ public function parseInstallNodes($installTree) { foreach ($installTree->getChildren() as $node) { switch ($node->getName()) { case 'schema': case 'data': case 'code': case 'migration': case 'note': $this->addInstallAction($node); break; case 'upgrade': $minVersion = $node->getAttribute('minversion'); $maxVersion = $node->getAttribute('maxversion'); if ((!isset($minVersion) || $this->currentVersion->compare($minVersion) >= 0) && (!isset($maxVersion) || $this->currentVersion->compare($maxVersion) <= 0)) { $this->parseInstallNodes($node); } break; } } } /** * Add an installer action from the descriptor. * * @param XMLNode $node */ public function addInstallAction($node) { $fileName = $node->getAttribute('file'); if (!isset($fileName)) { $this->actions[] = ['type' => $node->getName(), 'file' => null, 'attr' => $node->getAttributes()]; } elseif (strstr($fileName, '{$installedLocale}')) { // Filename substitution for locales foreach ($this->installedLocales as $thisLocale) { $newFileName = str_replace('{$installedLocale}', $thisLocale, $fileName); $this->actions[] = ['type' => $node->getName(), 'file' => $newFileName, 'attr' => $node->getAttributes()]; } } else { $newFileName = str_replace('{$locale}', $this->locale, $fileName); if (!file_exists($newFileName)) { // Use version from default locale if data file is not available in the selected locale $newFileName = str_replace('{$locale}', self::INSTALLER_DEFAULT_LOCALE, $fileName); } $this->actions[] = ['type' => $node->getName(), 'file' => $newFileName, 'attr' => $node->getAttributes()]; } } // // Installer Execution // /** * Execute a single installer action. * * @param array $action * * @return bool */ public function executeAction($action) { switch ($action['type']) { case 'schema': $fileName = $action['file']; $this->log(sprintf('schema: %s', $action['file'])); require_once('lib/pkp/lib/vendor/adodb/adodb-php/adodb.inc.php'); require_once('./lib/pkp/lib/vendor/adodb/adodb-php/adodb-xmlschema.inc.php'); $dbconn = ADONewConnection(Config::getVar('database', 'driver')); $port = Config::getVar('database', 'port'); $dbconn->Connect( Config::getVar('database', 'host') . ($port ? ':' . $port : ''), Config::getVar('database', 'username'), Config::getVar('database', 'password'), Config::getVar('database', 'name') ); $schemaXMLParser = new adoSchema($dbconn); $dict = $schemaXMLParser->dict; $sql = $schemaXMLParser->parseSchema($fileName); $schemaXMLParser->destroy(); if ($sql) { return $this->executeSQL($sql); } $this->setError(self::INSTALLER_ERROR_DB, str_replace('{$file}', $fileName, __('installer.installParseDBFileError'))); return false; case 'data': $fileName = $action['file']; $condition = $action['attr']['condition'] ?? null; $includeAction = true; if ($condition) { // Create a new scope to evaluate the condition $evalFunction = function ($installer, $action) use ($condition) { return eval($condition); }; $includeAction = $evalFunction($this, $action); } $this->log('data: ' . $action['file'] . ($includeAction ? '' : ' (skipped)')); if (!$includeAction) { break; } $sql = $this->dataXMLParser->parseData($fileName); // We might get an empty SQL if the upgrade script has // been executed before. if ($sql) { return $this->executeSQL($sql); } break; case 'migration': assert(isset($action['attr']['class'])); $fullClassName = $action['attr']['class']; if (strpos($fullClassName, '\\') !== false) { // Migration is specified fully-qualified PHP class name; allow autoloading $this->log(sprintf('migration: %s', $fullClassName)); $migration = new $fullClassName($this, $action['attr']); } else { // Migration is specified using old-style class.name.like.this // This behaviour is DEPRECATED as of 3.4.0 import($fullClassName); $shortClassName = substr($fullClassName, strrpos($fullClassName, '.') + 1); $this->log(sprintf('migration: %s', $shortClassName)); $migration = new $shortClassName($this, $action['attr']); } try { $migration->up(); $this->migrations[] = $migration; } catch (Exception $e) { // Log an error message $this->setError( self::INSTALLER_ERROR_DB, Config::getVar('debug', 'show_stacktrace') ? (string) $e : $e->getMessage() ); // Back out already-executed migrations. while ($previousMigration = array_pop($this->migrations)) { try { $this->log(sprintf('revert migration: %s', get_class($previousMigration))); $previousMigration->down(); } catch (DowngradeNotSupportedException $e) { $this->log(sprintf('downgrade for "%s" unsupported: %s', get_class($previousMigration), $e->getMessage())); break; } catch (Exception $e) { $this->log(sprintf('error while downgrading "%s": %s', get_class($previousMigration), Config::getVar('debug', 'show_stacktrace') ? (string) $e : $e->getMessage())); break; } } return false; } return true; case 'code': $condition = $action['attr']['condition'] ?? null; $includeAction = true; if ($condition) { // Create a new scope to evaluate the condition $evalFunction = function ($installer, $action) use ($condition) { return eval($condition); }; $includeAction = $evalFunction($this, $action); } $this->log(sprintf('code: %s %s::%s' . ($includeAction ? '' : ' (skipped)'), $action['file'] ?? 'Installer', $action['attr']['class'] ?? 'Installer', $action['attr']['function'])); if (!$includeAction) { return true; } // Condition not met; skip the action. if (isset($action['file'])) { require_once($action['file']); } if (isset($action['attr']['class'])) { return call_user_func([$action['attr']['class'], $action['attr']['function']], $this, $action['attr']); } return call_user_func([$this, $action['attr']['function']], $this, $action['attr']); case 'note': $this->log(sprintf('note: %s', $action['file'])); $this->notes[] = join('', file($action['file'])); break; } return true; } /** * Execute an SQL statement. * * * @return bool */ public function executeSQL($sql) { if (is_array($sql)) { foreach ($sql as $stmt) { if (!$this->executeSQL($stmt)) { return false; } } } else { try { DB::affectingStatement($sql); } catch (Exception $e) { $this->setError(self::INSTALLER_ERROR_DB, $e->getMessage()); return false; } } return true; } /** * Update the specified configuration parameters. * * @param array $configParams * * @return bool */ public function updateConfig($configParams) { // Update config file $configParser = new \PKP\config\ConfigParser(); if (!$configParser->updateConfig(Config::getConfigFileName(), $configParams)) { // Error reading config file $this->setError(self::INSTALLER_ERROR_GENERAL, 'installer.configFileError'); return false; } $this->configContents = $configParser->getFileContents(); if (!$configParser->writeConfig(Config::getConfigFileName())) { $this->wroteConfig = false; } return true; } // // Accessors // /** * Get the value of an installation parameter. * * @param string $name */ public function getParam($name) { return $this->params[$name] ?? null; } /** * Return currently installed version. * * @return Version */ public function getCurrentVersion() { return $this->currentVersion; } /** * Return new version after installation. * * @return Version */ public function getNewVersion() { return $this->newVersion; } /** * Get the set of SQL statements required to perform the install. * * @return array */ public function getSQL() { return $this->sql; } /** * Get the set of installation notes. * * @return array */ public function getNotes() { return $this->notes; } /** * Get the contents of the updated configuration file. * * @return string */ public function getConfigContents() { return $this->configContents; } /** * Check if installer was able to write out new config file. * * @return bool */ public function wroteConfig() { return $this->wroteConfig; } /** * Return the error code. * Valid return values are: * - 0 = no error * - INSTALLER_ERROR_GENERAL = general installation error. * - INSTALLER_ERROR_DB = database installation error * * @return int */ public function getErrorType() { return $this->errorType ?? 0; } /** * The error message, if an error has occurred. * In the case of a database error, an unlocalized string containing the error message is returned. * For any other error, a localization key for the error message is returned. * * @return string */ public function getErrorMsg() { return $this->errorMsg; } /** * Return the error message as a localized string. * * @return string. */ public function getErrorString() { switch ($this->getErrorType()) { case self::INSTALLER_ERROR_DB: return 'DB: ' . $this->getErrorMsg(); default: return __($this->getErrorMsg()); } } /** * Set the error type and messgae. * * @param int $type * @param string $msg Text message (INSTALLER_ERROR_DB) or locale key (otherwise) */ public function setError($type, $msg) { $this->errorType = $type; $this->errorMsg = $msg; } /** * Set the logger for this installer. * * @param object $logger */ public function setLogger($logger) { $this->logger = $logger; } /** * Clear the data cache files (needed because of direct tinkering * with settings tables) * * @return bool */ public function clearDataCache() { // Clear the CacheManager's caches $cacheManager = CacheManager::getManager(); $cacheManager->flush(null, CACHE_TYPE_FILE); $cacheManager->flush(null, CACHE_TYPE_OBJECT); //clear laravel cache $cacheManager = PKPContainer::getInstance()['cache']; $cacheManager->store()->flush(); return true; } /** * Set the current version for this installer. * * @param Version $version */ public function setCurrentVersion($version) { $this->currentVersion = $version; } /** * For upgrade: install email templates and data * * @deprecated 3.4 Do not use <code function="installEmailTemplate" ...> * in upgrade scripts to 3.4 and later versions. This is no longer in * sync with the PKP\emailTemplates\DAO methods to install email templates. * * @param object $installer * @param array $attr Attributes: array containing * 'key' => 'EMAIL_KEY_HERE', * 'locales' => 'en,fr_CA,...' */ public function installEmailTemplate($installer, $attr) { $locales = explode(',', $attr['locales'] ?? ''); $emailKey = $attr['key'] ?? ''; if (!$emailKey) { throw new Exception('Tried to install email template but no template key provided.'); } $xmlDao = new XMLDAO(); $data = $xmlDao->parseStruct('registry/emailTemplates.xml', ['email']); if (!isset($data['email'])) { return false; } if (empty($locales)) { $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */ $site = $siteDao->getSite(); /** @var \PKP\site\Site $site */ $locales = $site->getInstalledLocales(); } // filter out any invalid locales that is not supported by site $allLocales = array_keys(Locale::getLocales()); if (!empty($invalidLocales = array_diff($locales, $allLocales))) { $locales = array_diff($locales, $invalidLocales); } foreach ($data['email'] as $entry) { $attrs = $entry['attributes']; if ($emailKey && $emailKey != $attrs['key']) { continue; } if (DB::table('email_templates_default_data')->where('email_key', $attrs['key'])->exists()) { continue; } $subject = $attrs['subject'] ?? null; $body = $attrs['body'] ?? null; if ($subject && $body) { foreach ($locales as $locale) { DB::table('email_templates_default_data') ->where('email_key', $attrs['key']) ->where('locale', $locale) ->delete(); $previous = Locale::getMissingKeyHandler(); Locale::setMissingKeyHandler(fn (string $key): string => ''); $translatedSubject = __($subject, [], $locale); $translatedBody = __($body, [], $locale); Locale::setMissingKeyHandler($previous); if ($translatedSubject !== null && $translatedBody !== null) { DB::table('email_templates_default_data')->insert([ 'email_key' => $attrs['key'], 'locale' => $locale, 'subject' => $this->renameEmailTemplateVariables($translatedSubject), 'body' => $this->renameEmailTemplateVariables($translatedBody), ]); } } } } return true; } /** * @deprecated 3.4 * @see self::installEmailTemplate() */ protected function renameEmailTemplateVariables($string): string { if (empty($this->appEmailTemplateVariableNames)) { return $string; } $variables = []; $replacements = []; foreach ($this->appEmailTemplateVariableNames as $key => $value) { $variables[] = '/\{\$' . $key . '\}/'; $replacements[] = '{$' . $value . '}'; } return preg_replace($variables, $replacements, $string); } /** * Install the given filter configuration file. * * @param string $filterConfigFile * * @return bool true when successful, otherwise false */ public function installFilterConfig($filterConfigFile) { static $filterHelper = false; // Parse the filter configuration. $xmlParser = new PKPXMLParser(); $tree = $xmlParser->parse($filterConfigFile); // Validate the filter configuration. if (!$tree) { return false; } // Get the filter helper. if ($filterHelper === false) { $filterHelper = new FilterHelper(); } // Are there any filter groups to be installed? $filterGroupsNode = $tree->getChildByName('filterGroups'); if ($filterGroupsNode instanceof XMLNode) { $filterHelper->installFilterGroups($filterGroupsNode); } // Are there any filters to be installed? $filtersNode = $tree->getChildByName('filters'); if ($filtersNode instanceof XMLNode) { foreach ($filtersNode->getChildren() as $filterNode) { /** @var XMLNode $filterNode */ $filterHelper->configureFilter($filterNode); } } return true; } /** * Check to see whether a column exists. * Used in installer XML in conditional checks on <data> nodes. * * @param string $tableName * @param string $columnName * * @return bool */ public function columnExists($tableName, $columnName) { $schema = DB::getDoctrineSchemaManager(); // Make sure the table exists $tables = $schema->listTableNames(); if (!in_array($tableName, $tables)) { return false; } return Schema::hasColumn($tableName, $columnName); } /** * Check to see whether a table exists. * Used in installer XML in conditional checks on <data> nodes. * * @param string $tableName * * @return bool */ public function tableExists($tableName) { $tables = DB::getDoctrineSchemaManager()->listTableNames(); return in_array($tableName, $tables); } /** * Insert or update plugin data in versions * and plugin_settings tables. * * @return bool */ public function addPluginVersions() { $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */ $fileManager = new FileManager(); $categories = PluginRegistry::getCategories(); foreach ($categories as $category) { PluginRegistry::loadCategory($category); $plugins = PluginRegistry::getPlugins($category); if (!empty($plugins)) { foreach ($plugins as $plugin) { $versionFile = $plugin->getPluginPath() . '/version.xml'; if ($fileManager->fileExists($versionFile)) { $versionInfo = VersionCheck::parseVersionXML($versionFile); $pluginVersion = $versionInfo['version']; } else { $pluginVersion = new Version( 1, 0, 0, 0, // Major, minor, revision, build Core::getCurrentDate(), // Date installed 1, // Current 'plugins.' . $category, // Type basename($plugin->getPluginPath()), // Product '', // Class name 0, // Lazy load $plugin->isSitePlugin() // Site wide ); } $versionDao->insertVersion($pluginVersion, true); } } } return true; } /** * Fail the upgrade. * * @param Installer $installer * @param array $attr Attributes * * @return bool */ public function abort($installer, $attr) { $installer->setError(self::INSTALLER_ERROR_GENERAL, $attr['message']); return false; } /** * For 3.1.0 upgrade. DefaultMenus Defaults * * @return bool Success/failure */ public function installDefaultNavigationMenus() { $contextDao = Application::getContextDAO(); $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /** @var NavigationMenuDAO $navigationMenuDao */ $contexts = $contextDao->getAll(); while ($context = $contexts->next()) { $navigationMenuDao->installSettings($context->getId(), 'registry/navigationMenus.xml'); } $navigationMenuDao->installSettings(PKPApplication::CONTEXT_ID_NONE, 'registry/navigationMenus.xml'); return true; } /** * Check that the environment meets minimum PHP requirements. * * @return bool Success/failure */ public function checkPhpVersion() { if (version_compare(PKPApplication::PHP_REQUIRED_VERSION, PHP_VERSION) != 1) { return true; } $this->setError(self::INSTALLER_ERROR_GENERAL, 'installer.unsupportedPhpError'); return false; } /** * Migrate site locale settings to a serialized array in the database */ public function migrateSiteLocales() { $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */ $result = $siteDao->retrieve('SELECT installed_locales, supported_locales FROM site'); $set = $params = []; $row = (array) $result->current(); $type = 'array'; foreach ($row as $column => $value) { if (!empty($value)) { $set[] = $column . ' = ?'; $params[] = $siteDao->convertToDB(explode(':', $value), $type); } } $siteDao->update('UPDATE site SET ' . join(',', $set), $params); return true; } /** * Migrate active sidebar blocks from plugin_settings to journal_settings * * @return bool */ public function migrateSidebarBlocks() { $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */ $site = $siteDao->getSite(); $plugins = PluginRegistry::loadCategory('blocks'); if (empty($plugins)) { return true; } // Sanitize plugin names for use in sql IN(). $sanitizedPluginNames = array_map(function ($name) { return "'" . preg_replace('/[^A-Za-z0-9]/', '', $name) . "'"; }, array_keys($plugins)); $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var \PKP\plugins\PluginSettingsDAO $pluginSettingsDao */ $result = $pluginSettingsDao->retrieve( 'SELECT plugin_name, context_id, setting_value FROM plugin_settings WHERE plugin_name IN (' . join(',', $sanitizedPluginNames) . ') AND setting_name=\'context\';' ); $sidebarSettings = []; foreach ($result as $row) { if ($row->setting_value != 1) { continue; } // BLOCK_CONTEXT_SIDEBAR $seq = $pluginSettingsDao->getSetting($row->context_id, $row->plugin_name, 'seq'); if (!isset($sidebarSettings[$row->context_id])) { $sidebarSettings[$row->context_id] = []; } $sidebarSettings[$row->context_id][(int) $seq] = $row->plugin_name; } foreach ($sidebarSettings as $contextId => $contextSetting) { // Order by sequence ksort($contextSetting); $contextSetting = array_values($contextSetting); if ($contextId) { $contextDao = Application::getContextDAO(); $context = $contextDao->getById($contextId); $context->setData('sidebar', $contextSetting); $contextDao->updateObject($context); } else { $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */ $site = $siteDao->getSite(); $site->setData('sidebar', $contextSetting); $siteDao->updateObject($site); } } $pluginSettingsDao->update('DELETE FROM plugin_settings WHERE plugin_name IN (' . join(',', $sanitizedPluginNames) . ') AND (setting_name=\'context\' OR setting_name=\'seq\');'); return true; } /** * Migrate the metadata settings in the database to use a single row with one * of the new constants */ public function migrateMetadataSettings() { $contextDao = Application::getContextDao(); $metadataSettings = [ 'coverage', 'languages', 'rights', 'source', 'subjects', 'type', 'disciplines', 'keywords', 'agencies', 'citations', ]; $result = $contextDao->retrieve('SELECT ' . $contextDao->primaryKeyColumn . ' from ' . $contextDao->tableName); $contextIds = []; foreach ($result as $row) { $row = (array) $row; $contextIds[] = $row[$contextDao->primaryKeyColumn]; } foreach ($metadataSettings as $metadataSetting) { foreach ($contextIds as $contextId) { $result = $contextDao->retrieve( 'SELECT * FROM ' . $contextDao->settingsTableName . ' WHERE ' . $contextDao->primaryKeyColumn . ' = ? AND ( setting_name = ? OR setting_name = ? OR setting_name = ? ) ', [ $contextId, $metadataSetting . 'EnabledWorkflow', $metadataSetting . 'EnabledSubmission', $metadataSetting . 'Required', ] ); $value = Context::METADATA_DISABLE; foreach ($result as $row) { if ($row->setting_name === $metadataSetting . 'Required' && $row->setting_value) { $value = Context::METADATA_REQUIRE; } elseif ($row->setting_name === $metadataSetting . 'EnabledSubmission' && $row->setting_value && $value !== Context::METADATA_REQUIRE) { $value = Context::METADATA_REQUEST; } elseif ($row->setting_name === $metadataSetting . 'EnabledWorkflow' && $row->setting_value && $value !== Context::METADATA_REQUEST && $value !== Context::METADATA_REQUIRE) { $value = Context::METADATA_ENABLE; } } if ($value !== Context::METADATA_DISABLE) { $contextDao->update( 'INSERT INTO ' . $contextDao->settingsTableName . ' ( ' . $contextDao->primaryKeyColumn . ', locale, setting_name, setting_value ) VALUES (?, ?, ?, ?)', [ $contextId, '', $metadataSetting, $value, ] ); } $contextDao->update( 'DELETE FROM ' . $contextDao->settingsTableName . ' WHERE ' . $contextDao->primaryKeyColumn . ' = ? AND ( setting_name = ? OR setting_name = ? OR setting_name = ? ) ', [ $contextId, $metadataSetting . 'EnabledWorkflow', $metadataSetting . 'EnabledSubmission', $metadataSetting . 'Required', ] ); } } return true; } /** * Set the notification settings for journal managers and subeditors so * that they are opted out of the monthly stats email. */ public function setStatsEmailSettings() { $roleIds = [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR]; $notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var \PKP\notification\NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */ for ($contexts = Application::get()->getContextDAO()->getAll(true); $context = $contexts->next();) { $users = Repo::user()->getCollector() ->filterByContextIds([$context->getId()]) ->filterByRoleIds($roleIds) ->getMany(); foreach ($users as $user) { $notificationSubscriptionSettingsDao->update( 'INSERT INTO notification_subscription_settings (setting_name, setting_value, user_id, context, setting_type) VALUES (?, ?, ?, ?, ?)', [ 'blocked_emailed_notification', PKPNotification::NOTIFICATION_TYPE_EDITORIAL_REPORT, $user->getId(), $context->getId(), 'int' ] ); } } return true; } /** * Fix library files, which were mistakenly named server-side using source filenames. * See https://github.com/pkp/pkp-lib/issues/5471 * * @return bool */ public function fixLibraryFiles() { // Fetch all library files (no method currently in LibraryFileDAO for this) $libraryFileDao = DAORegistry::getDAO('LibraryFileDAO'); /** @var \PKP\context\LibraryFileDAO $libraryFileDao */ $result = $libraryFileDao->retrieve('SELECT * FROM library_files'); /** @var DAOResultFactory<LibraryFile> */ $libraryFiles = new DAOResultFactory($result, $libraryFileDao, '_fromRow', ['id']); $wrongFiles = []; while ($libraryFile = $libraryFiles->next()) { $libraryFileManager = new LibraryFileManager($libraryFile->getContextId()); $wrongFilePath = $libraryFileManager->getBasePath() . $libraryFile->getOriginalFileName(); $rightFilePath = $libraryFile->getFilePath(); if (isset($wrongFiles[$wrongFilePath])) { error_log('A potential collision was found between library files ' . $libraryFile->getId() . ' and ' . $wrongFiles[$wrongFilePath]->getId() . '. Please review the database entries and ensure that the associated files are correct.'); } else { $wrongFiles[$wrongFilePath] = $libraryFile; } // For all files for which the "wrong" filename exists and the "right" filename doesn't, // copy the "wrong" file over to the "right" one. This will leave the "wrong" file in // place, and won't disambiguate cases for which files were clobbered. if (file_exists($wrongFilePath) && !file_exists($rightFilePath)) { $libraryFileManager->copyFile($wrongFilePath, $rightFilePath); } } return true; } } if (!PKP_STRICT_MODE) { class_alias('\PKP\install\Installer', '\Installer'); define('INSTALLER_ERROR_GENERAL', Installer::INSTALLER_ERROR_GENERAL); define('INSTALLER_ERROR_DB', Installer::INSTALLER_ERROR_DB); define('INSTALLER_DATA_DIR', Installer::INSTALLER_DATA_DIR); define('INSTALLER_DEFAULT_LOCALE', Installer::INSTALLER_DEFAULT_LOCALE); }