18 define(
'INSTALLER_DATA_DIR',
'dbscripts/xml');
21 define(
'INSTALLER_ERROR_GENERAL', 1);
22 define(
'INSTALLER_ERROR_DB', 2);
25 define(
'INSTALLER_DEFAULT_LOCALE',
'en_US');
27 import(
'lib.pkp.classes.db.DBDataXMLParser');
28 import(
'lib.pkp.classes.site.Version');
29 import(
'lib.pkp.classes.site.VersionDAO');
30 import(
'lib.pkp.classes.config.ConfigParser');
32 require_once
'./lib/pkp/lib/vendor/adodb/adodb-php/adodb-xmlschema.inc.php';
107 $this->actions = array();
108 $this->sql = array();
109 $this->notes = array();
118 die (
'ABSTRACT CLASS');
133 $this->
log(
'pre-install');
134 if (!isset($this->dbconn)) {
137 $this->dbconn = $conn->getDBConn();
139 if (!$conn->isConnected()) {
140 $this->
setError(INSTALLER_ERROR_DB, $this->dbconn->errorMsg());
145 if (!isset($this->currentVersion)) {
148 $this->currentVersion = $versionDao->getCurrentVersion();
151 if (!isset($this->locale)) {
155 if (!isset($this->installedLocales)) {
159 if (!isset($this->dataXMLParser)) {
161 $this->dataXMLParser->setDBConn($this->dbconn);
204 $this->
log(
'post-install');
215 function log($message) {
216 if (isset($this->logger)) {
217 call_user_func(array($this->logger,
'log'), $message);
232 $this->
log(sprintf(
'load: %s', $this->descriptor));
234 $installPath = $this->isPlugin ? $this->descriptor : INSTALLER_DATA_DIR . DIRECTORY_SEPARATOR .
$this->descriptor;
235 $installTree = $xmlParser->parse($installPath);
238 $this->
setError(INSTALLER_ERROR_GENERAL,
'installer.installFileError');
242 $versionString = $installTree->getAttribute(
'version');
243 if (isset($versionString)) {
263 $this->
log(sprintf(
'version: %s', $this->newVersion->getVersionString(
false)));
264 foreach ($this->actions as $action) {
281 if ($this->newVersion->compare($this->currentVersion) > 0) {
283 if (!$versionDao->insertVersion($this->newVersion)) {
304 foreach ($installTree->getChildren() as $node) {
305 switch ($node->getName()) {
314 $minVersion = $node->getAttribute(
'minversion');
315 $maxVersion = $node->getAttribute(
'maxversion');
316 if ((!isset($minVersion) || $this->currentVersion->compare($minVersion) >= 0) && (!isset($maxVersion) || $this->currentVersion->compare($maxVersion) <= 0)) {
329 $fileName = $node->getAttribute(
'file');
331 if (!isset($fileName)) {
332 $this->actions[] = array(
'type' => $node->getName(),
'file' =>
null,
'attr' => $node->getAttributes());
334 }
else if (strstr($fileName,
'{$installedLocale}')) {
336 foreach ($this->installedLocales as $thisLocale) {
337 $newFileName = str_replace(
'{$installedLocale}', $thisLocale, $fileName);
338 $this->actions[] = array(
'type' => $node->getName(),
'file' => $newFileName,
'attr' => $node->getAttributes());
342 $newFileName = str_replace(
'{$locale}', $this->locale, $fileName);
343 if (!file_exists($newFileName)) {
345 $newFileName = str_replace(
'{$locale}', INSTALLER_DEFAULT_LOCALE, $fileName);
348 $this->actions[] = array(
'type' => $node->getName(),
'file' => $newFileName,
'attr' => $node->getAttributes());
363 switch ($action[
'type']) {
365 $fileName = $action[
'file'];
366 $this->
log(sprintf(
'schema: %s', $action[
'file']));
368 $schemaXMLParser =
new adoSchema($this->dbconn);
369 $dict = $schemaXMLParser->dict;
370 $sql = $schemaXMLParser->parseSchema($fileName);
371 $schemaXMLParser->destroy();
376 $this->
setError(INSTALLER_ERROR_DB, str_replace(
'{$file}', $fileName, __(
'installer.installParseDBFileError')));
381 $fileName = $action[
'file'];
382 $condition = isset($action[
'attr'][
'condition'])?$action[
'attr'][
'condition']:
null;
383 $includeAction =
true;
386 $evalFunction =
function($installer, $action) use ($condition) {
387 return eval($condition);
389 $includeAction = $evalFunction($this, $action);
391 $this->
log(
'data: ' . $action[
'file'] . ($includeAction?
'':
' (skipped)'));
392 if (!$includeAction)
break;
394 $sql = $this->dataXMLParser->parseData($fileName);
402 assert(isset($action[
'attr'][
'class']));
403 $fullClassName = $action[
'attr'][
'class'];
404 import($fullClassName);
405 $shortClassName = substr($fullClassName, strrpos($fullClassName,
'.')+1);
406 $this->
log(sprintf(
'migration: %s', $shortClassName));
407 $migration =
new $shortClassName();
410 $this->migrations[] = $migration;
411 }
catch (Exception $e) {
413 $this->
setError(INSTALLER_ERROR_DB, $e->getMessage());
416 while ($previousMigration = array_pop($this->migrations)) {
418 $previousMigration->down();
419 }
catch (
PKP\install\DowngradeNotSupportedException $e) {
427 $condition = isset($action[
'attr'][
'condition'])?$action[
'attr'][
'condition']:
null;
428 $includeAction =
true;
431 $evalFunction =
function($installer, $action) use ($condition) {
432 return eval($condition);
434 $includeAction = $evalFunction($this, $action);
436 $this->
log(sprintf(
'code: %s %s::%s' . ($includeAction?
'':
' (skipped)'), isset($action[
'file']) ? $action[
'file'] :
'Installer', isset($action[
'attr'][
'class']) ? $action[
'attr'][
'class'] :
'Installer', $action[
'attr'][
'function']));
437 if (!$includeAction)
return true;
439 if (isset($action[
'file'])) {
440 require_once($action[
'file']);
442 if (isset($action[
'attr'][
'class'])) {
443 return call_user_func(array($action[
'attr'][
'class'], $action[
'attr'][
'function']), $this, $action[
'attr']);
445 return call_user_func(array($this, $action[
'attr'][
'function']), $this, $action[
'attr']);
449 $this->
log(sprintf(
'note: %s', $action[
'file']));
450 $this->notes[] = join(
'', file($action[
'file']));
463 if (is_array(
$sql)) {
464 foreach(
$sql as $stmt) {
470 $this->dbconn->execute(
$sql);
471 if ($this->dbconn->errorNo() != 0) {
472 $this->
setError(INSTALLER_ERROR_DB, $this->dbconn->errorMsg());
490 $this->
setError(INSTALLER_ERROR_GENERAL,
'installer.configFileError');
494 $this->configContents = $configParser->getFileContents();
513 return isset($this->params[$name]) ? $this->params[$name] :
null;
573 return isset($this->errorType) ? $this->errorType : 0;
592 case INSTALLER_ERROR_DB:
605 $this->errorType = $type;
606 $this->errorMsg = $msg;
634 $this->currentVersion = $version;
645 $locales = explode(
',', $attr[
'locales']);
648 $emailTemplateDao->installEmailTemplates($emailTemplateDao->getMainEmailTemplatesFilename(), $locales,
false, $attr[
'key']);
658 static $filterHelper =
false;
662 $tree = $xmlParser->parse($filterConfigFile);
665 if (!$tree)
return false;
668 if ($filterHelper ===
false) {
669 import(
'lib.pkp.classes.filter.FilterHelper');
674 $filterGroupsNode = $tree->getChildByName(
'filterGroups');
675 if (is_a($filterGroupsNode,
'XMLNode')) {
676 $filterHelper->installFilterGroups($filterGroupsNode);
680 $filtersNode = $tree->getChildByName(
'filters');
681 if (is_a($filtersNode,
'XMLNode')) {
682 foreach ($filtersNode->getChildren() as $filterNode) {
683 $filterHelper->configureFilter($filterNode);
699 $dataSource = $siteDao->getDataSource();
700 $dict = NewDataDictionary($dataSource);
703 $tables = $dict->MetaTables(
'TABLES',
false);
704 if (!in_array($tableName, $tables))
return false;
708 $columns = $dict->MetaColumns($tableName);
709 foreach ($columns as $column) {
710 if ($column->name == $columnName)
return true;
723 $dataSource = $siteDao->getDataSource();
724 $dict = NewDataDictionary($dataSource);
727 $tables = $dict->MetaTables(
'TABLES',
false);
728 return in_array($tableName, $tables);
738 import(
'lib.pkp.classes.site.VersionCheck');
741 foreach ($categories as $category) {
744 if (!empty($plugins)) {
745 foreach ($plugins as $plugin) {
746 $versionFile = $plugin->getPluginPath() .
'/version.xml';
748 if ($fileManager->fileExists($versionFile)) {
750 $pluginVersion = $versionInfo[
'version'];
756 'plugins.'.$category,
757 basename($plugin->getPluginPath()),
760 $plugin->isSitePlugin()
763 $versionDao->insertVersion($pluginVersion,
true);
777 function abort($installer, $attr) {
778 $installer->setError(INSTALLER_ERROR_GENERAL, $attr[
'message']);
790 $contexts = $contextDao->getAll();
791 while ($context = $contexts->next()) {
792 $navigationMenuDao->installSettings($context->getId(),
'registry/navigationMenus.xml');
795 $navigationMenuDao->installSettings(CONTEXT_ID_NONE,
'registry/navigationMenus.xml');
805 if (version_compare(PHP_REQUIRED_VERSION, PHP_VERSION) != 1)
return true;
807 $this->
setError(INSTALLER_ERROR_GENERAL,
'installer.unsupportedPhpError');
817 $result = $siteDao->retrieve(
'SELECT installed_locales, supported_locales FROM site');
820 $row = $result->GetRowAssoc(
false);
822 foreach ($row as $column => $value) {
823 if (!empty($value)) {
824 $set[] = $column .
' = ?';
825 $params[] = $siteDao->convertToDB(explode(
':', $value), $type);
828 $siteDao->update(
'UPDATE site SET ' . join(
',', $set),
$params);
843 $site = $siteDao->getSite();
846 if (empty($plugins)) {
851 $sanitizedPluginNames = array_map(
function($name) {
852 return "'" . preg_replace(
"/[^A-Za-z0-9]/",
'', $name) .
"'";
853 }, array_keys($plugins));
856 $result = $pluginSettingsDao->retrieve(
857 'SELECT plugin_name, context_id, setting_value FROM plugin_settings WHERE plugin_name IN (' . join(
',', $sanitizedPluginNames) .
') AND setting_name=\'context\';'
860 $sidebarSettings = [];
861 while (!$result->EOF) {
862 $row = $result->getRowAssoc(
false);
863 if ($row[
'setting_value'] != 1) {
866 $seq = $pluginSettingsDao->getSetting($row[
'context_id'], $row[
'plugin_name'],
'seq');
867 if (!isset($sidebarSettings[$row[
'context_id']])) {
868 $sidebarSettings[$row[
'context_id']] = [];
870 $sidebarSettings[$row[
'context_id']][(int) $seq] = $row[
'plugin_name'];
875 foreach ($sidebarSettings as $contextId => $contextSetting) {
877 ksort($contextSetting);
878 $contextSetting = array_values($contextSetting);
881 $context = $contextDao->getById($contextId);
882 $context->setData(
'sidebar', $contextSetting);
883 $contextDao->updateObject($context);
886 $site = $siteDao->getSite();
887 $site->setData(
'sidebar', $contextSetting);
888 $siteDao->updateObject($site);
892 $pluginSettingsDao->update(
'DELETE FROM plugin_settings WHERE plugin_name IN (' . join(
',', $sanitizedPluginNames ) .
') AND (setting_name=\'context\' OR setting_name=\'seq\');');
902 $contextDao = Application::getContextDao();
904 $metadataSettings = [
917 $result = $contextDao->retrieve(
'SELECT ' . $contextDao->primaryKeyColumn .
' from ' . $contextDao->tableName);
919 while (!$result->EOF) {
920 $row = $result->getRowAssoc(
false);
921 $contextIds[] = $row[$contextDao->primaryKeyColumn];
926 foreach ($metadataSettings as $metadataSetting) {
927 foreach ($contextIds as $contextId) {
928 $result = $contextDao->retrieve(
'
929 SELECT * FROM ' . $contextDao->settingsTableName .
' WHERE
930 ' . $contextDao->primaryKeyColumn .
' = ?
939 $metadataSetting .
'EnabledWorkflow',
940 $metadataSetting .
'EnabledSubmission',
941 $metadataSetting .
'Required',
944 $value = METADATA_DISABLE;
945 while (!$result->EOF) {
946 $row = $result->getRowAssoc(
false);
947 if ($row[
'setting_name'] === $metadataSetting .
'Required' && $row[
'setting_value']) {
948 $value = METADATA_REQUIRE;
949 } elseif ($row[
'setting_name'] === $metadataSetting .
'EnabledSubmission' && $row[
'setting_value'] && $value !== METADATA_REQUIRE) {
950 $value = METADATA_REQUEST;
951 } elseif ($row[
'setting_name'] === $metadataSetting .
'EnabledWorkflow' && $row[
'setting_value'] && $value !== METADATA_REQUEST && $value !== METADATA_REQUIRE) {
952 $value = METADATA_ENABLE;
958 if ($value !== METADATA_DISABLE) {
959 $contextDao->update(
'
960 INSERT INTO ' . $contextDao->settingsTableName .
' (
961 ' . $contextDao->primaryKeyColumn .
',
965 ) VALUES (?, ?, ?, ?)',
975 $contextDao->update(
'
976 DELETE FROM ' . $contextDao->settingsTableName .
' WHERE
977 ' . $contextDao->primaryKeyColumn .
' = ?
986 $metadataSetting .
'EnabledWorkflow',
987 $metadataSetting .
'EnabledSubmission',
988 $metadataSetting .
'Required',
1002 import(
'lib.pkp.classes.notification.PKPNotification');
1003 $roleIds = [ROLE_ID_MANAGER, ROLE_ID_SUB_EDITOR];
1006 $notificationSubscriptionSettingsDao =
DAORegistry::getDAO(
'NotificationSubscriptionSettingsDAO');
1007 for ($contexts =
Application::get()->getContextDAO()->getAll(
true); $context = $contexts->next(); ) {
1008 foreach ($roleIds as $roleId) {
1009 for ($userGroups = $userGroupDao->getByRoleId($context->getId(), $roleId); $userGroup = $userGroups->next(); ) {
1010 for ($users = $userGroupDao->getUsersById($userGroup->getId(), $context->getId()); $user = $users->next(); ) {
1011 $notificationSubscriptionSettingsDao->update(
1012 'INSERT INTO notification_subscription_settings
1013 (setting_name, setting_value, user_id, context, setting_type)
1017 'blocked_emailed_notification',
1018 NOTIFICATION_TYPE_EDITORIAL_REPORT,
1038 import(
'classes.file.LibraryFileManager');
1041 $result = $libraryFileDao->retrieve(
'SELECT * FROM library_files');
1042 $libraryFiles =
new DAOResultFactory($result, $libraryFileDao,
'_fromRow', array(
'id'));
1043 $wrongFiles = array();
1044 while ($libraryFile = $libraryFiles->next()) {
1046 $wrongFilePath = $libraryFileManager->getBasePath() . $libraryFile->getOriginalFileName();
1047 $rightFilePath = $libraryFile->getFilePath();
1049 if (isset($wrongFiles[$wrongFilePath])) {
1050 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.');
1052 $wrongFiles[$wrongFilePath] = $libraryFile;
1058 if (file_exists($wrongFilePath) && !file_exists($rightFilePath)) {
1059 $libraryFileManager->copyFile($wrongFilePath, $rightFilePath);