first commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/OJSv3_3_0UpgradeMigration.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 OJSv3_3_0UpgradeMigration
|
||||
*
|
||||
* @brief Describe database table structures.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class OJSv3_3_0UpgradeMigration extends \PKP\migration\upgrade\PKPv3_3_0UpgradeMigration
|
||||
{
|
||||
protected function getSubmissionPath(): string
|
||||
{
|
||||
return 'articles';
|
||||
}
|
||||
|
||||
protected function getContextPath(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextKeyField(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
protected function getSectionTable(): string
|
||||
{
|
||||
return 'sections';
|
||||
}
|
||||
|
||||
protected function getSerializedSettings(): array
|
||||
{
|
||||
return [
|
||||
'site_settings' => [
|
||||
'enableBulkEmails',
|
||||
'installedLocales',
|
||||
'pageHeaderTitleImage',
|
||||
'sidebar',
|
||||
'styleSheet',
|
||||
'supportedLocales',
|
||||
],
|
||||
'journal_settings' => [
|
||||
'disableBulkEmailUserGroups',
|
||||
'favicon',
|
||||
'homepageImage',
|
||||
'pageHeaderLogoImage',
|
||||
'sidebar',
|
||||
'styleSheet',
|
||||
'submissionChecklist',
|
||||
'supportedFormLocales',
|
||||
'supportedLocales',
|
||||
'supportedSubmissionLocales',
|
||||
'enablePublisherId',
|
||||
'journalThumbnail',
|
||||
],
|
||||
'publication_settings' => [
|
||||
'categoryIds',
|
||||
'coverImage',
|
||||
'disciplines',
|
||||
'keywords',
|
||||
'languages',
|
||||
'subjects',
|
||||
'supportingAgencies',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
// pkp/pkp-lib#6807 Make sure all submission/issue last modification dates are set
|
||||
DB::statement('UPDATE issues SET last_modified = date_published WHERE last_modified IS NULL');
|
||||
|
||||
// Delete the old MODS34 filters
|
||||
DB::statement("DELETE FROM filters WHERE class_name='plugins.metadata.mods34.filter.Mods34SchemaArticleAdapter'");
|
||||
DB::statement("DELETE FROM filter_groups WHERE symbolic IN ('article=>mods34', 'mods34=>article')");
|
||||
// Delete mEDRA dependencies
|
||||
DB::statement("DELETE FROM filters WHERE class_name IN ('plugins.importexport.medra.filter.IssueMedraXmlFilter', 'plugins.importexport.medra.filter.ArticleMedraXmlFilter', 'plugins.importexport.medra.filter.GalleyMedraXmlFilter')");
|
||||
DB::statement("DELETE FROM filter_groups WHERE symbolic IN ('issue=>medra-xml', 'article=>medra-xml', 'galley=>medra-xml')");
|
||||
DB::statement("DELETE FROM scheduled_tasks WHERE class_name='plugins.importexport.medra.MedraInfoSender'");
|
||||
DB::statement("DELETE FROM versions WHERE product_type='plugins.importexport' AND product='medra'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete specific submission file migrations
|
||||
*
|
||||
* The main submission file migration is done in
|
||||
* PKPv3_3_0UpgradeMigration and that migration must
|
||||
* be run before this one.
|
||||
*/
|
||||
protected function migrateSubmissionFiles()
|
||||
{
|
||||
parent::migrateSubmissionFiles();
|
||||
|
||||
Schema::table('publication_galleys', function (Blueprint $table) {
|
||||
$table->renameColumn('file_id', 'submission_file_id');
|
||||
});
|
||||
DB::statement('UPDATE publication_galleys SET submission_file_id = NULL WHERE submission_file_id = 0');
|
||||
|
||||
// pkp/pkp-lib#6616 Delete publication_galleys entries that correspond to nonexistent submission_files
|
||||
$orphanedIds = DB::table('publication_galleys AS pg')
|
||||
->leftJoin('submission_files AS sf', 'pg.submission_file_id', '=', 'sf.submission_file_id')
|
||||
->whereNull('sf.submission_file_id')
|
||||
->whereNotNull('pg.submission_file_id')
|
||||
->pluck('pg.submission_file_id', 'pg.galley_id');
|
||||
foreach ($orphanedIds as $galleyId => $submissionFileId) {
|
||||
error_log("Removing orphaned publication_galleys entry ID {$galleyId} with submission_file_id {$submissionFileId}");
|
||||
DB::table('publication_galleys')->where('galley_id', '=', $galleyId)->delete();
|
||||
}
|
||||
|
||||
Schema::table('publication_galleys', function (Blueprint $table) {
|
||||
$table->bigInteger('submission_file_id')->nullable()->unsigned()->change();
|
||||
$table->foreign('submission_file_id')->references('submission_file_id')->on('submission_files');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I3573_AddPrimaryKeys.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I3573_AddPrimaryKeys.php
|
||||
*
|
||||
* @brief Add primary keys to tables that do not have them, to better support database replication.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I3573_AddPrimaryKeys extends \PKP\migration\upgrade\v3_4_0\I3573_AddPrimaryKeys
|
||||
{
|
||||
public static function getKeyNames(): array
|
||||
{
|
||||
return array_merge(parent::getKeyNames(), [
|
||||
'issue_galley_settings' => 'issue_galley_setting_id',
|
||||
'issue_settings' => 'issue_setting_id',
|
||||
'journal_settings' => 'journal_setting_id',
|
||||
'publication_galley_settings' => 'publication_galley_setting_id',
|
||||
'section_settings' => 'section_setting_id',
|
||||
'subscription_type_settings' => 'subscription_type_setting_id',
|
||||
'usage_stats_unique_item_requests_temporary_records' => 'usage_stats_temp_item_id',
|
||||
'metrics_context' => 'metrics_context_id',
|
||||
'metrics_counter_submission_institution_daily' => 'metrics_counter_submission_institution_daily_id',
|
||||
'metrics_counter_submission_daily' => 'metrics_counter_submission_daily_id',
|
||||
'metrics_submission' => 'metrics_submission_id',
|
||||
'usage_stats_unique_item_investigations_temporary_records' => 'usage_stats_temp_unique_item_id',
|
||||
'metrics_counter_submission_monthly' => 'metrics_counter_submission_monthly_id',
|
||||
'usage_stats_total_temporary_records' => 'usage_stats_temp_total_id',
|
||||
'usage_stats_institution_temporary_records' => 'usage_stats_temp_institution_id',
|
||||
'metrics_submission_geo_daily' => 'metrics_submission_geo_daily_id',
|
||||
'metrics_counter_submission_institution_monthly' => 'metrics_counter_submission_institution_monthly_id',
|
||||
'metrics_issue' => 'metrics_issue_id',
|
||||
'metrics_submission_geo_monthly' => 'metrics_submission_geo_monthly_id',
|
||||
'custom_section_orders' => 'custom_section_order_id',
|
||||
'custom_issue_orders' => 'custom_issue_order_id',
|
||||
'funder_settings' => 'funder_setting_id', // PLUGIN
|
||||
'funder_award_settings' => 'funder_award_setting_id', // PLUGIN
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getIndexData(): array
|
||||
{
|
||||
return array_merge(parent::getIndexData(), [
|
||||
'journal_settings' => ['journal_settings_pkey', ['journal_id', 'locale', 'setting_name'], 'journal_settings_unique', true],
|
||||
'section_settings' => ['section_settings_pkey', ['section_id', 'locale', 'setting_name'], 'section_settings_unique', true],
|
||||
'issue_settings' => ['issue_settings_pkey', ['issue_id', 'locale', 'setting_name'], 'issue_settings_unique', true],
|
||||
'issue_galley_settings' => ['issue_galley_settings_pkey', ['galley_id', 'locale', 'setting_name'], 'issue_galley_settings_unique', true],
|
||||
'custom_issue_orders' => ['custom_issue_orders_pkey', ['issue_id'], 'custom_issue_orders_unique', true],
|
||||
'custom_section_orders' => ['custom_section_orders_pkey', ['issue_id', 'section_id'], 'custom_section_orders_unique', true],
|
||||
'publication_galley_settings' => ['publication_galley_settings_pkey', ['galley_id', 'locale', 'setting_name'], 'publication_galley_settings_unique', true],
|
||||
'subscription_type_settings' => ['subscription_type_settings_pkey', ['type_id', 'locale', 'setting_name'], 'subscription_type_settings_unique', true],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I4235_OAISetSpec.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 I4235_OAISetSpec
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\oai\OAIUtils;
|
||||
|
||||
class I4235_OAISetSpec extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// pkp/pkp-lib/issues/4235 Improve OAI-PMH set spec compliance
|
||||
// Convert stored setSpec strings to valid format
|
||||
$setSpecs = DB::table('data_object_tombstones')->select('set_spec')->distinct()->get()->toArray();
|
||||
foreach ($setSpecs as $row) {
|
||||
$a = preg_split('/:/', $row->set_spec);
|
||||
if (count($a) == 2) {
|
||||
[$journalSpec, $sectionSpec] = $a;
|
||||
$new = OAIUtils::toValidSetSpec(urldecode($journalSpec)) . ':' . OAIUtils::toValidSetSpec(urldecode($sectionSpec));
|
||||
DB::table('data_object_tombstones')->where('set_spec', $row->set_spec)->update(['set_spec' => $new]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// The old format is not recoverable since some characters might have been stripped
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I5716_EmailTemplateAssignments.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I5716_EmailTemplateAssignments
|
||||
*
|
||||
* @brief Refactors relationship between Mailables and Email Templates
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use PKP\mail\mailables\DiscussionCopyediting;
|
||||
use PKP\mail\mailables\DiscussionProduction;
|
||||
use PKP\mail\mailables\DiscussionReview;
|
||||
use PKP\mail\mailables\DiscussionSubmission;
|
||||
|
||||
class I5716_EmailTemplateAssignments extends \PKP\migration\upgrade\v3_4_0\I5716_EmailTemplateAssignments
|
||||
{
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
protected function getContextIdColumn(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
protected function getDiscussionTemplates(): Collection
|
||||
{
|
||||
return collect([
|
||||
DiscussionSubmission::getEmailTemplateKey(),
|
||||
DiscussionReview::getEmailTemplateKey(),
|
||||
DiscussionCopyediting::getEmailTemplateKey(),
|
||||
DiscussionProduction::getEmailTemplateKey(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6091_AddFilterNamespaces.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 I6091_AddFilterNamespaces
|
||||
*
|
||||
* @brief Describe upgrade/downgrade operations for introducing namespaces to the built-in set of filters.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I6091_AddFilterNamespaces extends \PKP\migration\Migration
|
||||
{
|
||||
public const FILTER_RENAME_MAP = [
|
||||
// Application filters
|
||||
'plugins.importexport.doaj.filter.DOAJXmlFilter' => 'APP\plugins\importexport\doaj\filter\DOAJXmlFilter',
|
||||
'plugins.generic.datacite.filter.DataciteXmlFilter' => 'APP\plugins\generic\datacite\filter\DataciteXmlFilter',
|
||||
'plugins.importexport.native.filter.ArticleNativeXmlFilter' => 'APP\plugins\importexport\native\filter\ArticleNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlArticleFilter' => 'APP\plugins\importexport\native\filter\NativeXmlArticleFilter',
|
||||
'plugins.importexport.native.filter.IssueNativeXmlFilter' => 'APP\plugins\importexport\native\filter\IssueNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlIssueFilter' => 'APP\plugins\importexport\native\filter\NativeXmlIssueFilter',
|
||||
'plugins.importexport.native.filter.IssueGalleyNativeXmlFilter' => 'APP\plugins\importexport\native\filter\IssueGalleyNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlIssueGalleyFilter' => 'APP\plugins\importexport\native\filter\NativeXmlIssueGalleyFilter',
|
||||
'plugins.importexport.native.filter.AuthorNativeXmlFilter' => 'APP\plugins\importexport\native\filter\AuthorNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlAuthorFilter' => 'APP\plugins\importexport\native\filter\NativeXmlAuthorFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlArticleFileFilter' => 'APP\plugins\importexport\native\filter\NativeXmlArticleFileFilter',
|
||||
'plugins.importexport.native.filter.ArticleGalleyNativeXmlFilter' => 'APP\plugins\importexport\native\filter\ArticleGalleyNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlArticleGalleyFilter' => 'APP\plugins\importexport\native\filter\NativeXmlArticleGalleyFilter',
|
||||
'plugins.importexport.native.filter.PublicationNativeXmlFilter' => 'APP\plugins\importexport\native\filter\PublicationNativeXmlFilter',
|
||||
'plugins.importexport.native.filter.NativeXmlPublicationFilter' => 'APP\plugins\importexport\native\filter\NativeXmlPublicationFilter',
|
||||
'plugins.importexport.doaj.filter.DOAJJsonFilter' => 'APP\plugins\importexport\doaj\filter\DOAJJsonFilter',
|
||||
'plugins.importexport.pubmed.filter.ArticlePubMedXmlFilter' => 'APP\plugins\importexport\pubmed\filter\ArticlePubMedXmlFilter',
|
||||
'plugins.metadata.dc11.filter.Dc11SchemaArticleAdapter' => 'APP\plugins\metadata\dc11\filter\Dc11SchemaArticleAdapter',
|
||||
'plugins.generic.crossref.filter.IssueCrossrefXmlFilter' => 'APP\plugins\generic\crossref\filter\IssueCrossrefXmlFilter',
|
||||
'plugins.generic.crossref.filter.ArticleCrossrefXmlFilter' => 'APP\plugins\generic\crossref\filter\ArticleCrossrefXmlFilter',
|
||||
|
||||
// pkp-lib filters
|
||||
'lib.pkp.plugins.importexport.users.filter.PKPUserUserXmlFilter' => 'PKP\plugins\importexport\users\filter\PKPUserUserXmlFilter',
|
||||
'lib.pkp.plugins.importexport.users.filter.UserXmlPKPUserFilter' => 'PKP\plugins\importexport\users\filter\UserXmlPKPUserFilter',
|
||||
'lib.pkp.plugins.importexport.users.filter.UserGroupNativeXmlFilter' => 'PKP\plugins\importexport\users\filter\UserGroupNativeXmlFilter',
|
||||
'lib.pkp.plugins.importexport.users.filter.NativeXmlUserGroupFilter' => 'PKP\plugins\importexport\users\filter\NativeXmlUserGroupFilter',
|
||||
'lib.pkp.plugins.importexport.native.filter.SubmissionFileNativeXmlFilter' => 'PKP\plugins\importexport\native\filter\SubmissionFileNativeXmlFilter',
|
||||
];
|
||||
|
||||
public const TASK_RENAME_MAP = [
|
||||
'lib.pkp.classes.task.ReviewReminder' => 'PKP\task\ReviewReminder',
|
||||
'lib.pkp.classes.task.StatisticsReport' => 'PKP\task\StatisticsReport',
|
||||
'classes.tasks.SubscriptionExpiryReminder' => 'APP\tasks\SubscriptionExpiryReminder',
|
||||
'lib.pkp.classes.task.DepositDois' => 'PKP\task\DepositDois',
|
||||
'lib.pkp.classes.task.RemoveUnvalidatedExpiredUsers' => 'PKP\task\RemoveUnvalidatedExpiredUsers',
|
||||
'lib.pkp.classes.task.EditorialReminders' => 'PKP\task\EditorialReminders',
|
||||
'lib.pkp.classes.task.UpdateIPGeoDB' => 'PKP\task\UpdateIPGeoDB',
|
||||
'classes.tasks.UsageStatsLoader' => 'APP\tasks\UsageStatsLoader',
|
||||
'plugins.importexport.doaj.DOAJInfoSender' => 'APP\plugins\importexport\doaj\DOAJInfoSender',
|
||||
];
|
||||
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
foreach (self::FILTER_RENAME_MAP as $oldName => $newName) {
|
||||
DB::statement('UPDATE filters SET class_name = ? WHERE class_name = ?', [$newName, $oldName]);
|
||||
}
|
||||
foreach (self::TASK_RENAME_MAP as $oldName => $newName) {
|
||||
DB::statement('UPDATE scheduled_tasks SET class_name = ? WHERE class_name = ?', [$newName, $oldName]);
|
||||
}
|
||||
DB::statement('UPDATE filter_groups SET output_type=? WHERE output_type = ?', ['metadata::APP\plugins\metadata\dc11\schema\Dc11Schema(ARTICLE)', 'metadata::plugins.metadata.dc11.schema.Dc11Schema(ARTICLE)']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
foreach (self::FILTER_RENAME_MAP as $oldName => $newName) {
|
||||
DB::statement('UPDATE filters SET class_name = ? WHERE class_name = ?', [$oldName, $newName]);
|
||||
}
|
||||
foreach (self::TASK_RENAME_MAP as $oldName => $newName) {
|
||||
DB::statement('UPDATE scheduled_tasks SET class_name = ? WHERE class_name = ?', [$oldName, $newName]);
|
||||
}
|
||||
DB::statement('UPDATE filter_groups SET output_type=? WHERE output_type = ?', ['metadata::plugins.metadata.dc11.schema.Dc11Schema(ARTICLE)', 'metadata::APP\plugins\metadata\dc11\schema\Dc11Schema(ARTICLE)']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6093_AddForeignKeys.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 I6093_AddForeignKeys
|
||||
*
|
||||
* @brief Describe upgrade/downgrade operations for introducing foreign key definitions to existing database relationships.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I6093_AddForeignKeys extends \PKP\migration\upgrade\v3_4_0\I6093_AddForeignKeys
|
||||
{
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextKeyField(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
Schema::table('sections', function (Blueprint $table) {
|
||||
$table->foreign('review_form_id', 'sections_review_form_id')->references('review_form_id')->on('review_forms')->onDelete('set null');
|
||||
$table->index(['review_form_id'], 'sections_review_form_id');
|
||||
|
||||
$table->foreign('journal_id', 'sections_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('section_settings', function (Blueprint $table) {
|
||||
$table->foreign('section_id', 'section_settings_section_id')->references('section_id')->on('sections')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('issues', function (Blueprint $table) {
|
||||
$table->foreign('journal_id', 'issues_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('issue_settings', function (Blueprint $table) {
|
||||
$table->foreign('issue_id', 'issue_settings_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('issue_files', function (Blueprint $table) {
|
||||
$table->foreign('issue_id', 'issue_files_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('issue_galleys', function (Blueprint $table) {
|
||||
$table->foreign('issue_id', 'issue_galleys_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->foreign('file_id', 'issue_galleys_file_id')->references('file_id')->on('issue_files')->onDelete('cascade');
|
||||
$table->index(['file_id'], 'issue_galleys_file_id');
|
||||
});
|
||||
|
||||
Schema::table('issue_galley_settings', function (Blueprint $table) {
|
||||
$table->foreign('galley_id', 'issue_galleys_settings_galley_id')->references('galley_id')->on('issue_galleys')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('custom_issue_orders', function (Blueprint $table) {
|
||||
$table->foreign('issue_id', 'custom_issue_orders_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'custom_issue_orders_issue_id');
|
||||
$table->foreign('journal_id', 'custom_issue_orders_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'custom_issue_orders_journal_id');
|
||||
});
|
||||
|
||||
Schema::table('custom_section_orders', function (Blueprint $table) {
|
||||
$table->foreign('issue_id', 'custom_section_orders_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'custom_section_orders_issue_id');
|
||||
$table->foreign('section_id', 'custom_section_orders_section_id')->references('section_id')->on('sections')->onDelete('cascade');
|
||||
$table->index(['section_id'], 'custom_section_orders_section_id');
|
||||
});
|
||||
|
||||
Schema::table('publications', function (Blueprint $table) {
|
||||
$table->foreign('section_id', 'publications_section_id')->references('section_id')->on('sections')->onDelete('set null');
|
||||
$table->foreign('submission_id', 'publications_submission_id')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->foreign('primary_contact_id', 'publications_primary_contact_id')->references('author_id')->on('authors')->onDelete('set null');
|
||||
$table->index(['primary_contact_id'], 'publications_primary_contact_id');
|
||||
});
|
||||
|
||||
// Attempt to drop the previous foreign key, which doesn't have the cascade rule
|
||||
if (DB::getDoctrineSchemaManager()->introspectTable('publication_galleys')->hasForeignKey('publication_galleys_submission_file_id_foreign')) {
|
||||
Schema::table('publication_galleys', fn (Blueprint $table) => $table->dropForeign('publication_galleys_submission_file_id_foreign'));
|
||||
}
|
||||
|
||||
Schema::table('publication_galleys', function (Blueprint $table) {
|
||||
$table->foreign('publication_id', 'publication_galleys_publication_id')->references('publication_id')->on('publications')->onDelete('cascade');
|
||||
$table->index(['submission_file_id'], 'publication_galleys_submission_file_id');
|
||||
});
|
||||
|
||||
Schema::table('publication_galley_settings', function (Blueprint $table) {
|
||||
$table->foreign('galley_id', 'publication_galley_settings_galley_id')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('subscription_types', function (Blueprint $table) {
|
||||
$table->foreign('journal_id', 'subscription_types_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'subscription_types_journal_id');
|
||||
});
|
||||
|
||||
Schema::table('subscription_type_settings', function (Blueprint $table) {
|
||||
$table->foreign('type_id', 'subscription_type_settings_type_id')->references('type_id')->on('subscription_types')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('subscriptions', function (Blueprint $table) {
|
||||
$table->foreign('journal_id', 'subscriptions_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'subscriptions_journal_id');
|
||||
$table->foreign('user_id', 'subscriptions_user_id')->references('user_id')->on('users')->onDelete('cascade');
|
||||
$table->index(['user_id'], 'subscriptions_user_id');
|
||||
$table->foreign('type_id', 'subscriptions_type_id')->references('type_id')->on('subscription_types')->onDelete('cascade');
|
||||
$table->index(['type_id'], 'subscriptions_type_id');
|
||||
});
|
||||
|
||||
Schema::table('institutional_subscriptions', function (Blueprint $table) {
|
||||
$table->foreign('subscription_id', 'institutional_subscriptions_subscription_id')->references('subscription_id')->on('subscriptions')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('completed_payments', function (Blueprint $table) {
|
||||
$table->foreign('context_id', 'completed_payments_context_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'completed_payments_context_id');
|
||||
|
||||
$table->foreign('user_id', 'completed_payments_user_id')->references('user_id')->on('users')->onDelete('set null');
|
||||
$table->index(['user_id'], 'completed_payments_user_id');
|
||||
});
|
||||
|
||||
Schema::table('journals', function (Blueprint $table) {
|
||||
$table->index(['current_issue_id'], 'journals_issue_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6241_RequiredGenres.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6241_RequiredGenres
|
||||
*
|
||||
* @brief Set a required file genre for this app.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I6241_RequiredGenres extends \PKP\migration\upgrade\v3_4_0\I6241_RequiredGenres
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
DB::table('genres')
|
||||
->where('entry_key', 'SUBMISSION') // "Article Text" from genres.xml
|
||||
->update(['required' => 1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6306_EnableCategories.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6306_EnableCategories
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I6306_EnableCategories extends \PKP\migration\upgrade\v3_4_0\I6306_EnableCategories
|
||||
{
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
protected function getContextIdColumn(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_CleanOldMetrics.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_CleanOldMetrics
|
||||
*
|
||||
* @brief Clean the old metrics:
|
||||
* delete migrated entries with the metric type ojs::counter from the DB table metrics,
|
||||
* move back the orphaned metrics from the temporary metrics_tmp,
|
||||
* rename or delete the DB table metrics,
|
||||
* delete DB table usage_stats_temporary_records.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I6782_CleanOldMetrics extends \PKP\migration\upgrade\v3_4_0\I6782_CleanOldMetrics
|
||||
{
|
||||
protected function getMetricType(): string
|
||||
{
|
||||
return 'ojs::counter';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_CreateNewMetricsTables.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_CreateNewMetricsTables
|
||||
*
|
||||
* @brief Describe database table structures.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema as Schema;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I6782_CreateNewMetricsTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('metrics_context', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_context_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'metrics_context_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_context_context_id');
|
||||
|
||||
$table->date('date');
|
||||
$table->integer('metric');
|
||||
});
|
||||
|
||||
Schema::create('metrics_submission', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_submission_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'ms_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_submission_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_submission_submission_id');
|
||||
|
||||
$table->bigInteger('representation_id')->nullable();
|
||||
$table->foreign('representation_id')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
$table->index(['representation_id'], 'metrics_submission_representation_id');
|
||||
|
||||
$table->bigInteger('submission_file_id')->unsigned()->nullable();
|
||||
$table->foreign('submission_file_id')->references('submission_file_id')->on('submission_files')->onDelete('cascade');
|
||||
$table->index(['submission_file_id'], 'metrics_submission_submission_file_id');
|
||||
|
||||
$table->bigInteger('file_type')->nullable();
|
||||
$table->bigInteger('assoc_type');
|
||||
$table->date('date');
|
||||
$table->integer('metric');
|
||||
|
||||
$table->index(['context_id', 'submission_id', 'assoc_type', 'file_type'], 'ms_context_id_submission_id_assoc_type_file_type');
|
||||
});
|
||||
|
||||
Schema::create('metrics_issue', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_issue_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'metrics_issue_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_issue_context_id');
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$table->foreign('issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'metrics_issue_issue_id');
|
||||
|
||||
$table->bigInteger('issue_galley_id')->nullable();
|
||||
$table->foreign('issue_galley_id')->references('galley_id')->on('issue_galleys')->onDelete('cascade');
|
||||
$table->index(['issue_galley_id'], 'metrics_issue_issue_galley_id');
|
||||
|
||||
$table->date('date');
|
||||
$table->integer('metric');
|
||||
|
||||
$table->index(['context_id', 'issue_id'], 'metrics_issue_context_id_issue_id');
|
||||
});
|
||||
|
||||
Schema::create('metrics_counter_submission_daily', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_counter_submission_daily_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'msd_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msd_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_counter_submission_daily_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msd_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_counter_submission_daily_submission_id');
|
||||
|
||||
$table->date('date');
|
||||
$table->integer('metric_investigations');
|
||||
$table->integer('metric_investigations_unique');
|
||||
$table->integer('metric_requests');
|
||||
$table->integer('metric_requests_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msd_context_id_submission_id');
|
||||
$table->unique(['load_id', 'context_id', 'submission_id', 'date'], 'msd_uc_load_id_context_id_submission_id_date');
|
||||
});
|
||||
|
||||
Schema::create('metrics_counter_submission_monthly', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_counter_submission_monthly_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msm_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_counter_submission_monthly_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msm_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_counter_submission_monthly_submission_id');
|
||||
|
||||
$table->integer('month');
|
||||
$table->integer('metric_investigations');
|
||||
$table->integer('metric_investigations_unique');
|
||||
$table->integer('metric_requests');
|
||||
$table->integer('metric_requests_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msm_context_id_submission_id');
|
||||
$table->unique(['context_id', 'submission_id', 'month'], 'msm_uc_context_id_submission_id_month');
|
||||
});
|
||||
|
||||
Schema::create('metrics_counter_submission_institution_daily', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_counter_submission_institution_daily_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'msid_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msid_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_counter_submission_institution_daily_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msid_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_counter_submission_institution_daily_submission_id');
|
||||
|
||||
$table->bigInteger('institution_id');
|
||||
$table->foreign('institution_id', 'msid_institution_id_foreign')->references('institution_id')->on('institutions')->onDelete('cascade');
|
||||
$table->index(['institution_id'], 'metrics_counter_submission_institution_daily_institution_id');
|
||||
|
||||
$table->date('date');
|
||||
$table->integer('metric_investigations');
|
||||
$table->integer('metric_investigations_unique');
|
||||
$table->integer('metric_requests');
|
||||
$table->integer('metric_requests_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msid_context_id_submission_id');
|
||||
$table->unique(['load_id', 'context_id', 'submission_id', 'institution_id', 'date'], 'msid_uc_load_id_context_id_submission_id_institution_id_date');
|
||||
});
|
||||
|
||||
Schema::create('metrics_counter_submission_institution_monthly', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_counter_submission_institution_monthly_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msim_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_counter_submission_institution_monthly_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msim_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_counter_submission_institution_monthly_submission_id');
|
||||
|
||||
$table->bigInteger('institution_id');
|
||||
$table->foreign('institution_id', 'msim_institution_id_foreign')->references('institution_id')->on('institutions')->onDelete('cascade');
|
||||
$table->index(['institution_id'], 'metrics_counter_submission_institution_monthly_institution_id');
|
||||
|
||||
$table->integer('month');
|
||||
$table->integer('metric_investigations');
|
||||
$table->integer('metric_investigations_unique');
|
||||
$table->integer('metric_requests');
|
||||
$table->integer('metric_requests_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msim_context_id_submission_id');
|
||||
$table->unique(['context_id', 'submission_id', 'institution_id', 'month'], 'msim_uc_context_id_submission_id_institution_id_month');
|
||||
});
|
||||
|
||||
Schema::create('metrics_submission_geo_daily', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_submission_geo_daily_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->index(['load_id'], 'msgd_load_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msgd_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_submission_geo_daily_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msgd_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_submission_geo_daily_submission_id');
|
||||
|
||||
$table->string('country', 2)->default('');
|
||||
$table->string('region', 3)->default('');
|
||||
$table->string('city', 255)->default('');
|
||||
$table->date('date');
|
||||
$table->integer('metric');
|
||||
$table->integer('metric_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msgd_context_id_submission_id');
|
||||
$table->unique(['load_id', 'context_id', 'submission_id', 'country', 'region', 'city', 'date'], 'msgd_uc_load_context_submission_c_r_c_date');
|
||||
});
|
||||
|
||||
Schema::create('metrics_submission_geo_monthly', function (Blueprint $table) {
|
||||
$table->bigIncrements('metrics_submission_geo_monthly_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'msgm_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'metrics_submission_geo_monthly_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'msgm_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'metrics_submission_geo_monthly_submission_id');
|
||||
|
||||
$table->string('country', 2)->default('');
|
||||
$table->string('region', 3)->default('');
|
||||
$table->string('city', 255)->default('');
|
||||
$table->integer('month');
|
||||
$table->integer('metric');
|
||||
$table->integer('metric_unique');
|
||||
|
||||
$table->index(['context_id', 'submission_id'], 'msgm_context_id_submission_id');
|
||||
$table->unique(['context_id', 'submission_id', 'country', 'region', 'city', 'month'], 'msgm_uc_context_submission_c_r_c_month');
|
||||
});
|
||||
|
||||
// Usage stats total item temporary records
|
||||
Schema::create('usage_stats_total_temporary_records', function (Blueprint $table) {
|
||||
$table->bigIncrements('usage_stats_temp_total_id');
|
||||
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 255);
|
||||
$table->string('user_agent', 255);
|
||||
$table->bigInteger('line_number');
|
||||
$table->string('canonical_url', 255);
|
||||
|
||||
$table->bigInteger('issue_id')->nullable();
|
||||
$table->foreign('issue_id', 'ust_issue_id_foreign')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'usage_stats_total_temporary_records_issue_id');
|
||||
|
||||
$table->bigInteger('issue_galley_id')->nullable();
|
||||
$table->foreign('issue_galley_id', 'ust_issue_galley_id_foreign')->references('galley_id')->on('issue_galleys')->onDelete('cascade');
|
||||
$table->index(['issue_galley_id'], 'usage_stats_total_temporary_records_issue_galley_id');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'ust_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'usage_stats_total_temporary_records_context_id');
|
||||
|
||||
$table->bigInteger('submission_id')->nullable();
|
||||
$table->foreign('submission_id', 'ust_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'usage_stats_total_temporary_records_submission_id');
|
||||
|
||||
$table->bigInteger('representation_id')->nullable();
|
||||
$table->foreign('representation_id', 'ust_representation_id_foreign')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
$table->index(['representation_id'], 'usage_stats_total_temporary_records_representation_id');
|
||||
|
||||
$table->bigInteger('submission_file_id')->unsigned()->nullable();
|
||||
$table->foreign('submission_file_id', 'ust_submission_file_id_foreign')->references('submission_file_id')->on('submission_files')->onDelete('cascade');
|
||||
$table->index(['submission_file_id'], 'usage_stats_total_temporary_records_submission_file_id');
|
||||
|
||||
$table->bigInteger('assoc_type');
|
||||
$table->smallInteger('file_type')->nullable();
|
||||
$table->string('country', 2)->default('');
|
||||
$table->string('region', 3)->default('');
|
||||
$table->string('city', 255)->default('');
|
||||
$table->string('load_id', 255);
|
||||
});
|
||||
|
||||
// Usage stats unique item investigations temporary records
|
||||
// No need to consider issue_id and issue_galley_id here because
|
||||
// investigations are only relevant/calculated on submission level.
|
||||
Schema::create('usage_stats_unique_item_investigations_temporary_records', function (Blueprint $table) {
|
||||
$table->bigIncrements('usage_stats_temp_unique_item_id');
|
||||
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 255);
|
||||
$table->string('user_agent', 255);
|
||||
$table->bigInteger('line_number');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'usii_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'usii_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'usii_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'usii_submission_id');
|
||||
|
||||
$table->bigInteger('representation_id')->nullable();
|
||||
$table->foreign('representation_id', 'usii_representation_id_foreign')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
$table->index(['representation_id'], 'usii_representation_id');
|
||||
|
||||
$table->bigInteger('submission_file_id')->unsigned()->nullable();
|
||||
$table->foreign('submission_file_id', 'usii_submission_file_id_foreign')->references('submission_file_id')->on('submission_files')->onDelete('cascade');
|
||||
$table->index(['submission_file_id'], 'usii_submission_file_id');
|
||||
|
||||
$table->bigInteger('assoc_type');
|
||||
$table->smallInteger('file_type')->nullable();
|
||||
$table->string('country', 2)->default('');
|
||||
$table->string('region', 3)->default('');
|
||||
$table->string('city', 255)->default('');
|
||||
$table->string('load_id', 255);
|
||||
});
|
||||
|
||||
// Usage stats unique item requests temporary records
|
||||
// No need to consider issue_id and issue_galley_id here because
|
||||
// requests are only relevant/calculated on submission level.
|
||||
Schema::create('usage_stats_unique_item_requests_temporary_records', function (Blueprint $table) {
|
||||
$table->bigIncrements('usage_stats_temp_item_id');
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 255);
|
||||
$table->string('user_agent', 255);
|
||||
$table->bigInteger('line_number');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'usir_context_id_foreign')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'usir_context_id');
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'usir_submission_id_foreign')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'usir_submission_id');
|
||||
|
||||
$table->bigInteger('representation_id')->nullable();
|
||||
$table->foreign('representation_id', 'usir_representation_id_foreign')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
$table->index(['representation_id'], 'usir_representation_id');
|
||||
|
||||
$table->bigInteger('submission_file_id')->unsigned()->nullable();
|
||||
$table->foreign('submission_file_id', 'usir_submission_file_id_foreign')->references('submission_file_id')->on('submission_files')->onDelete('cascade');
|
||||
$table->index(['submission_file_id'], 'usir_submission_file_id');
|
||||
|
||||
$table->bigInteger('assoc_type');
|
||||
$table->smallInteger('file_type')->nullable();
|
||||
$table->string('country', 2)->default('');
|
||||
$table->string('region', 3)->default('');
|
||||
$table->string('city', 255)->default('');
|
||||
$table->string('load_id', 255);
|
||||
});
|
||||
|
||||
// Usage stats institution temporary records
|
||||
// This table is needed because of data normalization
|
||||
Schema::create('usage_stats_institution_temporary_records', function (Blueprint $table) {
|
||||
$table->bigIncrements('usage_stats_temp_institution_id');
|
||||
|
||||
$table->string('load_id', 255);
|
||||
$table->bigInteger('line_number');
|
||||
|
||||
$table->bigInteger('institution_id');
|
||||
$table->foreign('institution_id', 'usi_institution_id_foreign')->references('institution_id')->on('institutions')->onDelete('cascade');
|
||||
$table->index(['institution_id'], 'usi_institution_id');
|
||||
|
||||
$table->unique(['load_id', 'line_number', 'institution_id'], 'usitr_load_id_line_number_institution_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_MetricsContext.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_MetricsContext
|
||||
*
|
||||
* @brief Migrate context stats data from the old DB table metrics into the new DB table metrics_context.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I6782_MetricsContext extends \PKP\migration\upgrade\v3_4_0\I6782_MetricsContext
|
||||
{
|
||||
private const ASSOC_TYPE_CONTEXT = 0x0000100;
|
||||
|
||||
protected function getMetricType(): string
|
||||
{
|
||||
return 'ojs::counter';
|
||||
}
|
||||
|
||||
protected function getContextAssocType(): int
|
||||
{
|
||||
return self::ASSOC_TYPE_CONTEXT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_MetricsGeo.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_MetricsGeo
|
||||
*
|
||||
* @brief Migrate submission stats Geo data from the old DB table metrics into the new DB table metrics_submission_geo_daily, then aggregate monthly.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I6782_MetricsGeo extends \PKP\migration\upgrade\v3_4_0\I6782_MetricsGeo
|
||||
{
|
||||
protected function getMetricType(): string
|
||||
{
|
||||
return 'ojs::counter';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_MetricsIssue.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_MetricsIssue
|
||||
*
|
||||
* @brief Migrate issue stats data from the old DB table metrics into the new DB table metrics_issue.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\config\Config;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I6782_MetricsIssue extends Migration
|
||||
{
|
||||
private const ASSOC_TYPE_ISSUE = 0x0000103;
|
||||
private const ASSOC_TYPE_ISSUE_GALLEY = 0x0000105;
|
||||
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$dayFormatSql = "DATE_FORMAT(STR_TO_DATE(m.day, '%Y%m%d'), '%Y-%m-%d')";
|
||||
if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') {
|
||||
$dayFormatSql = "to_date(m.day, 'YYYYMMDD')";
|
||||
}
|
||||
|
||||
// The not existing foreign keys should already be moved to the metrics_tmp in I6782_OrphanedMetrics
|
||||
// Migrate issue metrics; consider issue TOCs and galley files
|
||||
$selectIssueMetrics = DB::table('metrics as m')
|
||||
->select(DB::raw("m.load_id, m.context_id, m.assoc_id, null, {$dayFormatSql}, m.metric"))
|
||||
->where('m.assoc_type', '=', self::ASSOC_TYPE_ISSUE)
|
||||
->where('m.metric_type', '=', 'ojs::counter');
|
||||
DB::table('metrics_issue')->insertUsing(['load_id', 'context_id', 'issue_id', 'issue_galley_id', 'date', 'metric'], $selectIssueMetrics);
|
||||
|
||||
$selectIssueGalleyMetrics = DB::table('metrics as m')
|
||||
->join('issue_galleys as ig', 'ig.galley_id', '=', 'm.assoc_id')
|
||||
->select(DB::raw("m.load_id, m.context_id, ig.issue_id, m.assoc_id, {$dayFormatSql}, m.metric"))
|
||||
->where('m.assoc_type', '=', self::ASSOC_TYPE_ISSUE_GALLEY)
|
||||
->where('m.metric_type', '=', 'ojs::counter');
|
||||
DB::table('metrics_issue')->insertUsing(['load_id', 'context_id', 'issue_id', 'issue_galley_id', 'date', 'metric'], $selectIssueGalleyMetrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_MetricsSubmission.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_MetricsSubmission
|
||||
*
|
||||
* @brief Migrate submissions stats data from the old DB table metrics into the new DB table metrics_submission.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\config\Config;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I6782_MetricsSubmission extends Migration
|
||||
{
|
||||
private const ASSOC_TYPE_SUBMISSION = 0x0100009;
|
||||
private const ASSOC_TYPE_SUBMISSION_FILE = 0x0000203;
|
||||
private const ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER = 0x0000213;
|
||||
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$dayFormatSql = "DATE_FORMAT(STR_TO_DATE(m.day, '%Y%m%d'), '%Y-%m-%d')";
|
||||
if (substr(Config::getVar('database', 'driver'), 0, strlen('postgres')) === 'postgres') {
|
||||
$dayFormatSql = "to_date(m.day, 'YYYYMMDD')";
|
||||
}
|
||||
|
||||
// The not existing foreign keys should already be moved to the metrics_tmp in I6782_OrphanedMetrics
|
||||
// Migrate submission metrics; consider abstracts, galley and supp files
|
||||
$selectSubmissionMetrics = DB::table('metrics as m')
|
||||
->select(DB::raw("m.load_id, m.context_id, m.assoc_id, null, null, null, m.assoc_type, {$dayFormatSql}, m.metric"))
|
||||
->where('m.assoc_type', '=', self::ASSOC_TYPE_SUBMISSION)
|
||||
->where('m.metric_type', '=', 'ojs::counter');
|
||||
DB::table('metrics_submission')->insertUsing(['load_id', 'context_id', 'submission_id', 'representation_id', 'submission_file_id', 'file_type', 'assoc_type', 'date', 'metric'], $selectSubmissionMetrics);
|
||||
|
||||
$selectSubmissionFileMetrics = DB::table('metrics as m')
|
||||
->select(DB::raw("m.load_id, m.context_id, m.submission_id, m.representation_id, m.assoc_id, m.file_type, m.assoc_type, {$dayFormatSql}, m.metric"))
|
||||
->where('m.assoc_type', '=', self::ASSOC_TYPE_SUBMISSION_FILE)
|
||||
->where('m.metric_type', '=', 'ojs::counter');
|
||||
DB::table('metrics_submission')->insertUsing(['load_id', 'context_id', 'submission_id', 'representation_id', 'submission_file_id', 'file_type', 'assoc_type', 'date', 'metric'], $selectSubmissionFileMetrics);
|
||||
|
||||
$selectSubmissionSuppFileMetrics = DB::table('metrics as m')
|
||||
->select(DB::raw("m.load_id, m.context_id, m.submission_id, m.representation_id, m.assoc_id, m.file_type, m.assoc_type, {$dayFormatSql}, m.metric"))
|
||||
->where('m.assoc_type', '=', self::ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER)
|
||||
->where('m.metric_type', '=', 'ojs::counter');
|
||||
DB::table('metrics_submission')->insertUsing(['load_id', 'context_id', 'submission_id', 'representation_id', 'submission_file_id', 'file_type', 'assoc_type', 'date', 'metric'], $selectSubmissionSuppFileMetrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_OrphanedMetrics.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_OrphanedMetrics
|
||||
*
|
||||
* @brief Migrate metrics data from objects that do not exist any more and from assoc types that are not considered in the upgrade into the temporary table.
|
||||
* These entries will be copied back and stay in the table metrics_old, s. I6782_CleanOldMetrics.
|
||||
* Consider only metric_type ojs::counter here, because these entries will be removed during the upgrade.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I6782_OrphanedMetrics extends \PKP\migration\upgrade\v3_4_0\I6782_OrphanedMetrics
|
||||
{
|
||||
private const ASSOC_TYPE_CONTEXT = 0x0000100;
|
||||
private const ASSOC_TYPE_ISSUE = 0x0000103;
|
||||
private const ASSOC_TYPE_ISSUE_GALLEY = 0x0000105;
|
||||
|
||||
protected function getMetricType(): string
|
||||
{
|
||||
return 'ojs::counter';
|
||||
}
|
||||
|
||||
protected function getContextAssocType(): int
|
||||
{
|
||||
return self::ASSOC_TYPE_CONTEXT;
|
||||
}
|
||||
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextKeyField(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
protected function getRepresentationTable(): string
|
||||
{
|
||||
return 'publication_galleys';
|
||||
}
|
||||
|
||||
protected function getRepresentationKeyField(): string
|
||||
{
|
||||
return 'galley_id';
|
||||
}
|
||||
|
||||
protected function getAssocTypesToMigrate(): array
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
self::ASSOC_TYPE_CONTEXT,
|
||||
self::ASSOC_TYPE_ISSUE,
|
||||
self::ASSOC_TYPE_ISSUE_GALLEY,
|
||||
],
|
||||
parent::getAssocTypesToMigrate()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migration.
|
||||
*
|
||||
* assoc_object_type, assoc_object_id, and pkp_section_id will not be considered here, because they are not relevant for the migration
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
$metricsColumns = Schema::getColumnListing('metrics_tmp');
|
||||
|
||||
// Metrics issue IDs
|
||||
// as m.assoc_id
|
||||
$orphanedIds = DB::table('metrics AS m')->leftJoin('issues AS i', 'm.assoc_id', '=', 'i.issue_id')->where('m.assoc_type', '=', self::ASSOC_TYPE_ISSUE)->whereNull('i.issue_id')->distinct()->pluck('m.assoc_id');
|
||||
$orphandedIssues = DB::table('metrics')->select($metricsColumns)->where('assoc_type', '=', self::ASSOC_TYPE_ISSUE)->whereIn('assoc_id', $orphanedIds)->where('metric_type', '=', $this->getMetricType());
|
||||
DB::table('metrics_tmp')->insertUsing($metricsColumns, $orphandedIssues);
|
||||
DB::table('metrics')->where('assoc_type', '=', self::ASSOC_TYPE_ISSUE)->whereIn('assoc_id', $orphanedIds)->delete();
|
||||
|
||||
// Clean orphaned metrics issue galley IDs
|
||||
$orphanedIds = DB::table('metrics AS m')->leftJoin('issue_galleys AS ig', 'm.assoc_id', '=', 'ig.galley_id')->where('m.assoc_type', '=', self::ASSOC_TYPE_ISSUE_GALLEY)->whereNull('ig.galley_id')->distinct()->pluck('m.assoc_id');
|
||||
$orphandedIssuesGalleys = DB::table('metrics')->select($metricsColumns)->where('assoc_type', '=', self::ASSOC_TYPE_ISSUE_GALLEY)->whereIn('assoc_id', $orphanedIds)->where('metric_type', '=', $this->getMetricType());
|
||||
DB::table('metrics_tmp')->insertUsing($metricsColumns, $orphandedIssuesGalleys);
|
||||
DB::table('metrics')->where('assoc_type', '=', self::ASSOC_TYPE_ISSUE_GALLEY)->whereIn('assoc_id', $orphanedIds)->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6782_RemovePlugins.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6782_RemovePlugins
|
||||
*
|
||||
* @brief Remove the usageStats and views report plugin.
|
||||
*
|
||||
* This script has to be called after I6782_Metrics, i.e. after usageStats plugin settings were successfully migrated.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I6782_RemovePlugins extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Remove usageStats plugin and views report plugin
|
||||
// Differently to versionDao->disableVersion, we will remove the entry from the table 'versions' and 'plugin_settings'
|
||||
// because the plugins cannot be used any more
|
||||
DB::table('versions')
|
||||
->where('product_type', '=', 'plugins.generic')
|
||||
->where('product', '=', 'usageStats')
|
||||
->delete();
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'usagestatsplugin')
|
||||
->delete();
|
||||
DB::table('versions')
|
||||
->where('product_type', '=', 'plugins.reports')
|
||||
->where('product', '=', 'views')
|
||||
->delete();
|
||||
|
||||
// It is not needed to remove usageStats plugin scheduled task from the Acron plugin, because
|
||||
// PKPAcronPlugin function _parseCrontab() will be called at the end of update, that
|
||||
// will overwrite the old crontab setting.
|
||||
|
||||
// Remove the old scheduled task from the table scheduled_tasks
|
||||
DB::table('scheduled_tasks')->where('class_name', '=', 'plugins.generic.usageStats.UsageStatsLoader')->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6807_SetLastModified.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 I6807_SetLastModified
|
||||
*
|
||||
* @brief Update last modification dates where they are not yet set.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I6807_SetLastModified extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// pkp/pkp-lib#6807 Make sure all submission/issue last modification dates are set
|
||||
DB::statement('UPDATE issues SET last_modified = date_published WHERE last_modified IS NULL');
|
||||
DB::statement('UPDATE submissions SET last_modified = NOW() WHERE last_modified IS NULL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// We don't have the data to downgrade and downgrades are unwanted here anyway.
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\APP\migration\upgrade\v3_4_0\I6807_SetLastModified', '\I6807_SetLastModified');
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I6895_Institutions.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I6895_Institutions
|
||||
*
|
||||
* @brief Migrate institution data from subscriptions into the new institution data model.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I6895_Institutions extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Requires that institution tables are already there
|
||||
// Add the new column institution_id to the table institutional_subscriptions
|
||||
Schema::table('institutional_subscriptions', function (Blueprint $table) {
|
||||
$table->bigInteger('institution_id')->default(0);
|
||||
});
|
||||
|
||||
// pkp/pkp-lib#6895 Migrate all institutions from institutional subscriptions into new databases
|
||||
$institutionalSubscriptions = DB::table('institutional_subscriptions AS i')
|
||||
->select('i.institutional_subscription_id', 'i.subscription_id', 'i.institution_name', 's.journal_id', 'j.primary_locale')
|
||||
->join('subscriptions AS s', 's.subscription_id', '=', 'i.subscription_id')
|
||||
->join('journals AS j', 'j.journal_id', '=', 's.journal_id')
|
||||
->get();
|
||||
|
||||
foreach ($institutionalSubscriptions as $institutionalSubscription) {
|
||||
$institutionId = DB::table('institutions')->insertGetId(['context_id' => $institutionalSubscription->journal_id], 'institution_id');
|
||||
if ($institutionId) {
|
||||
DB::table('institution_settings')->insert(['institution_id' => $institutionId, 'setting_name' => 'name', 'setting_value' => $institutionalSubscription->institution_name, 'locale' => $institutionalSubscription->primary_locale]);
|
||||
|
||||
$affected = DB::table('institutional_subscriptions')
|
||||
->where('institutional_subscription_id', $institutionalSubscription->institutional_subscription_id)
|
||||
->update(['institution_id' => $institutionId]);
|
||||
|
||||
// Get IP ranges
|
||||
$ipRanges = DB::table('institutional_subscription_ip')
|
||||
->select('ip_string', 'ip_start', 'ip_end')
|
||||
->where('subscription_id', '=', $institutionalSubscription->subscription_id)
|
||||
->get();
|
||||
foreach ($ipRanges as $ipRange) {
|
||||
DB::table('institution_ip')->insert(['institution_id' => $institutionId, 'ip_string' => $ipRange->ip_string, 'ip_start' => $ipRange->ip_start, 'ip_end' => $ipRange->ip_end]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the table institutional_subscription_ip
|
||||
Schema::drop('institutional_subscription_ip');
|
||||
|
||||
// Drop column institution_name form institutional_subscriptions
|
||||
Schema::table('institutional_subscriptions', function (Blueprint $table) {
|
||||
$table->dropColumn('institution_name');
|
||||
});
|
||||
|
||||
// Create the foreign key constraint (now that the values are correct and match the IDs in the parent table)
|
||||
Schema::table('institutional_subscriptions', function (Blueprint $table) {
|
||||
$table->foreign('institution_id')->references('institution_id')->on('institutions')->onDelete('cascade');
|
||||
$table->index(['institution_id'], 'institutional_subscriptions_institution_id');
|
||||
});
|
||||
|
||||
DB::statement('ALTER TABLE institutional_subscriptions ALTER COLUMN institution_id DROP DEFAULT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,794 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7014_DoiMigration.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 I7014_DoiMigration
|
||||
*
|
||||
* @brief Describe upgrade/downgrade operations for DB table dois.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use PKP\doi\Doi;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\upgrade\v3_4_0\PKPI7014_DoiMigration;
|
||||
|
||||
class I7014_DoiMigration extends PKPI7014_DoiMigration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
// Add doiId to issue
|
||||
Schema::table('issues', function (Blueprint $table) {
|
||||
$table->bigInteger('doi_id')->nullable();
|
||||
$table->foreign('doi_id')->references('doi_id')->on('dois')->nullOnDelete();
|
||||
$table->index(['doi_id'], 'issues_doi_id');
|
||||
});
|
||||
|
||||
// Add doiId to galley
|
||||
Schema::table('publication_galleys', function (Blueprint $table) {
|
||||
$table->bigInteger('doi_id')->nullable();
|
||||
$table->foreign('doi_id')->references('doi_id')->on('dois')->nullOnDelete();
|
||||
$table->index(['doi_id'], 'publication_galleys_doi_id');
|
||||
});
|
||||
|
||||
$this->migrateExistingDataUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
|
||||
protected function migrateExistingDataUp(): void
|
||||
{
|
||||
parent::migrateExistingDataUp();
|
||||
// Find all existing DOIs, move to new DOI objects and add foreign key for pub object
|
||||
$this->_migrateGalleyDoisUp();
|
||||
$this->_migrateIssueDoisUp();
|
||||
$this->_migrateCrossrefSettingsToContext();
|
||||
$this->_migrateDataciteSettingsToContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer over batch_id, failedMsg and settings, filter info for importExport to generic plugin transfer
|
||||
*/
|
||||
private function _migrateCrossrefSettingsToContext()
|
||||
{
|
||||
// ===== Filters ===== //
|
||||
DB::table('filters')
|
||||
->where('class_name', '=', 'plugins.importexport.crossref.filter.IssueCrossrefXmlFilter')
|
||||
->update(['class_name' => 'plugins.generic.crossref.filter.IssueCrossrefXmlFilter']);
|
||||
DB::table('filters')
|
||||
->where('class_name', '=', 'plugins.importexport.crossref.filter.ArticleCrossrefXmlFilter')
|
||||
->update(['class_name' => 'plugins.generic.crossref.filter.ArticleCrossrefXmlFilter']);
|
||||
|
||||
// ===== Submissions Statuses & Settings ===== //
|
||||
// 1. Get submissions with Crossref info
|
||||
$publicationDois = DB::table('publications', 'p')
|
||||
->select(['p.submission_id', 'p.doi_id'])
|
||||
->whereNotNull('p.doi_id')
|
||||
->get()
|
||||
->map(function ($item) {
|
||||
return [
|
||||
'submission_id' => $item->submission_id,
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
});
|
||||
$galleyDois = DB::table('publication_galleys', 'pg')
|
||||
->leftJoin('publications as p', 'pg.publication_id', '=', 'p.publication_id')
|
||||
->select(['p.submission_id', 'pg.doi_id'])
|
||||
->whereNotNull('pg.doi_id')
|
||||
->get()
|
||||
->map(function ($item) {
|
||||
return [
|
||||
'submission_id' => $item->submission_id,
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
});
|
||||
|
||||
// 2. Get all DOIs possibly associated with submission (publications and galleys)
|
||||
$doisBySubmission = $publicationDois->concat($galleyDois)
|
||||
->mapToGroups(function ($item) {
|
||||
return [$item['submission_id'] => $item['doi_id']];
|
||||
})
|
||||
->map(function ($item) {
|
||||
return ['doiIds' => $item->all()];
|
||||
})->toArray();
|
||||
// 3. Apply batchId and failedMsg to all DOIs
|
||||
DB::table('submissions', 's')
|
||||
->leftJoin('submission_settings as ss', 's.submission_id', '=', 'ss.submission_id')
|
||||
->whereIn('ss.setting_name', ['crossref::registeredDoi', 'crossref::status', 'crossref::batchId', 'crossref::failedMsg'])
|
||||
->select(['ss.submission_id', 'ss.setting_name', 'ss.setting_value'])
|
||||
->get()
|
||||
->each(function ($item) use (&$doisBySubmission) {
|
||||
if (!isset($doisBySubmission[$item->submission_id])) {
|
||||
return;
|
||||
}
|
||||
switch ($item->setting_name) {
|
||||
case 'crossref::registeredDoi':
|
||||
$doisBySubmission[$item->submission_id]['crossref::registeredDoi'] = $item->setting_value;
|
||||
return;
|
||||
case 'crossref::status':
|
||||
$status = Doi::STATUS_ERROR;
|
||||
$registrationAgency = null;
|
||||
if (in_array($item->setting_value, ['found', 'registered', 'markedRegistered'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
if ($item->setting_value == 'registered') {
|
||||
$registrationAgency = 'CrossrefExportPlugin';
|
||||
}
|
||||
}
|
||||
$doisBySubmission[$item->submission_id]['status'] = $status;
|
||||
if ($registrationAgency !== null) {
|
||||
$doisBySubmission[$item->submission_id]['registrationAgency'] = $registrationAgency;
|
||||
}
|
||||
return;
|
||||
case 'crossref::batchId':
|
||||
$doisBySubmission[$item->submission_id]['crossrefplugin_batchId'] = $item->setting_value;
|
||||
return;
|
||||
case 'crossref::failedMsg':
|
||||
$doisBySubmission[$item->submission_id]['crossrefplugin_failedMsg'] = $item->setting_value;
|
||||
return;
|
||||
}
|
||||
});
|
||||
// 4. Apply status to all DOIs
|
||||
$doiSettingInserts = [];
|
||||
$doiStatusUpdates = [];
|
||||
foreach ($doisBySubmission as $item) {
|
||||
$doiIds = $item['doiIds'];
|
||||
foreach ($doiIds as $doiId) {
|
||||
// Settings
|
||||
if (isset($item['crossrefplugin_batchId'])) {
|
||||
$doiSettingInserts[] = [
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'crossrefplugin_batchId',
|
||||
'setting_value' => $item['crossrefplugin_batchId'],
|
||||
];
|
||||
}
|
||||
if (isset($item['crossrefplugin_failedMsg'])) {
|
||||
$doiSettingInserts[] = [
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'crossrefplugin_failedMsg',
|
||||
'setting_value' => $item['crossrefplugin_failedMsg'],
|
||||
];
|
||||
}
|
||||
|
||||
// Status
|
||||
if (isset($item['status'])) {
|
||||
$doiStatusUpdates[$doiId] = ['status' => $item['status']];
|
||||
} elseif (isset($item['crossref::registeredDoi'])) {
|
||||
$doiStatusUpdates[$doiId] = ['status' => 3];
|
||||
}
|
||||
|
||||
if (isset($item['registrationAgency'])) {
|
||||
$doiSettingInserts[] = [
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'registrationAgency',
|
||||
'setting_value' => $item['registrationAgency']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_chunk($doiSettingInserts, 100) as $chunkedInserts) {
|
||||
DB::table('doi_settings')
|
||||
->insert($chunkedInserts);
|
||||
}
|
||||
foreach ($doiStatusUpdates as $doiId => $doiStatusUpdate) {
|
||||
DB::table('dois')
|
||||
->where('doi_id', '=', $doiId)
|
||||
->update($doiStatusUpdate);
|
||||
}
|
||||
|
||||
// 5. Clean up old settings
|
||||
DB::table('submission_settings')
|
||||
->whereIn('setting_name', ['crossref::registeredDoi', 'crossref::status', 'crossref::batchId'])
|
||||
->delete();
|
||||
|
||||
// ===== Issue Statuses & Settings ===== //
|
||||
// 1. Get issues with Crossref-related info
|
||||
$issueData = DB::table('issues', 'i')
|
||||
->leftJoin('issue_settings as iss', 'i.issue_id', '=', 'iss.issue_id')
|
||||
->whereIn('iss.setting_name', ['crossref::registeredDoi', 'crossref::status', 'crossref::batchId', 'crossref::failedMsg'])
|
||||
->select(['i.issue_id', 'i.doi_id', 'iss.setting_name', 'iss.setting_value'])
|
||||
->get()
|
||||
->reduce(function ($carry, $item) {
|
||||
if (!isset($carry[$item->issue_id])) {
|
||||
$carry[$item->issue_id] = [
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
}
|
||||
|
||||
$carry[$item->issue_id][$item->setting_name] = $item->setting_value;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
// 2. Map settings/status insert statements
|
||||
$inserts = [];
|
||||
$statuses = [];
|
||||
foreach ($issueData as $item) {
|
||||
// Settings
|
||||
if (isset($item['crossref::batchId'])) {
|
||||
$inserts[] = [
|
||||
'doi_id' => $item['doi_id'],
|
||||
'setting_name' => 'crossrefplugin_batchId',
|
||||
'setting_value' => $item['crossref::batchId'],
|
||||
];
|
||||
}
|
||||
|
||||
if (isset($item['crossref::failedMsg'])) {
|
||||
$inserts[] = [
|
||||
'doi_id' => $item['doi_id'],
|
||||
'setting_name' => 'crossrefplugin_failedMsg',
|
||||
'setting_value' => $item['crossref::failedMsg'],
|
||||
];
|
||||
}
|
||||
|
||||
// Status
|
||||
if (isset($item['crossref::status'])) {
|
||||
$status = Doi::STATUS_ERROR;
|
||||
$registrationAgency = null;
|
||||
if (in_array($item['crossref::status'], ['found', 'registered', 'markedRegistered'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
if ($item['crossref::status'] === 'registered') {
|
||||
$registrationAgency = 'CrossrefExportPlugin';
|
||||
}
|
||||
} elseif (isset($item['crossref::registeredDoi'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
}
|
||||
$statuses[$item['doi_id']] = ['status' => $status];
|
||||
if ($registrationAgency !== null) {
|
||||
$inserts[] = [
|
||||
'doi_id' => $item['doi_id'],
|
||||
'setting_name' => 'registrationAgency',
|
||||
'setting_value' => $registrationAgency
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Insert updated settings/statuses
|
||||
foreach (array_chunk($inserts, 100) as $chunkedInserts) {
|
||||
DB::table('doi_settings')
|
||||
->insert($chunkedInserts);
|
||||
}
|
||||
foreach ($statuses as $doiId => $insert) {
|
||||
DB::table('dois')
|
||||
->where('doi_id', '=', $doiId)
|
||||
->update($insert);
|
||||
}
|
||||
|
||||
// 4. Clean up old settings
|
||||
DB::table('issue_settings')
|
||||
->whereIn('setting_name', ['crossref::registeredDoi', 'crossref::status', 'crossref::batchId', 'crossref::failedMsg'])
|
||||
->delete();
|
||||
|
||||
// ===== General cleanup ===== //
|
||||
|
||||
// If any Crossref settings are configured, assume plugin is in use and enable
|
||||
$contextsWithPluginEnabled = DB::table('journals')
|
||||
->whereIn('journal_id', function (Builder $q) {
|
||||
$q->select('context_id')
|
||||
->from('plugin_settings')
|
||||
->where('plugin_name', '=', 'crossrefexportplugin');
|
||||
})
|
||||
->select(['journal_id'])
|
||||
->get();
|
||||
$contextsWithPluginEnabled->each(function ($item) {
|
||||
DB::table('plugin_settings')
|
||||
->insert(
|
||||
[
|
||||
'plugin_name' => 'crossrefplugin',
|
||||
'context_id' => $item->journal_id,
|
||||
'setting_name' => 'enabled',
|
||||
'setting_value' => 1,
|
||||
'setting_type' => 'bool'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Enable automatic DOI deposit if configured
|
||||
$contextsWithAutomaticDeposit = DB::table('journals')
|
||||
->whereIn('journal_id', function (Builder $q) {
|
||||
$q->select(['context_id'])
|
||||
->from('plugin_settings')
|
||||
->where('plugin_name', '=', 'crossrefexportplugin')
|
||||
->where('setting_name', '=', 'automaticRegistration')
|
||||
->where('setting_value', '=', 1) ;
|
||||
})
|
||||
->select(['journal_id'])
|
||||
->get();
|
||||
$contextsWithAutomaticDeposit->each(function ($item) {
|
||||
DB::table('journal_settings')
|
||||
->upsert(
|
||||
[
|
||||
'journal_id' => $item->journal_id,
|
||||
'setting_name' => 'automaticDoiDeposit',
|
||||
'setting_value' => 1
|
||||
],
|
||||
['journal_id', 'locale', 'setting_name'],
|
||||
['setting_value']
|
||||
);
|
||||
});
|
||||
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'crossrefexportplugin')
|
||||
->where('setting_name', '=', 'automaticRegistration')
|
||||
->delete();
|
||||
|
||||
// Update no-longer-in-use version for importExport plugin
|
||||
DB::table('versions')
|
||||
->where('product_type', '=', 'plugins.importexport')
|
||||
->where('product', '=', 'crossref')
|
||||
->delete();
|
||||
|
||||
// Remove scheduled task
|
||||
DB::table('scheduled_tasks')
|
||||
->where('class_name', '=', 'plugins.importexport.crossref.CrossrefInfoSender')
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer over settings, filter info for importExport to generic plugin transfer
|
||||
*/
|
||||
private function _migrateDataciteSettingsToContext()
|
||||
{
|
||||
// ===== Filters ===== //
|
||||
DB::table('filters')
|
||||
->where('class_name', '=', 'plugins.importexport.datacite.filter.DataciteXmlFilter')
|
||||
->update(['class_name' => 'plugins.generic.datacite.filter.DataciteXmlFilter']);
|
||||
|
||||
// ===== Issues Statuses & Settings ===== //
|
||||
// 1. Get issues with Datacite-related info
|
||||
$issueData = DB::table('issues', 'i')
|
||||
->leftJoin('issue_settings as iss', 'i.issue_id', '=', 'iss.issue_id')
|
||||
->whereIn('iss.setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->select(['i.issue_id', 'i.doi_id', 'iss.setting_name', 'iss.setting_value'])
|
||||
->get()
|
||||
->reduce(function ($carry, $item) {
|
||||
if (!isset($carry[$item->issue_id])) {
|
||||
$carry[$item->issue_id] = [
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
}
|
||||
|
||||
$carry[$item->issue_id][$item->setting_name] = $item->setting_value;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
// 2. Map statuses insert statements
|
||||
$statuses = [];
|
||||
$registrationAgencies = [];
|
||||
foreach ($issueData as $item) {
|
||||
// Status
|
||||
if (isset($item['datacite::status'])) {
|
||||
$status = Doi::STATUS_ERROR;
|
||||
$registrationAgency = null;
|
||||
if (in_array($item['datacite::status'], ['found', 'registered', 'markedRegistered'])) {
|
||||
if ($item['datacite::status'] === 'registered') {
|
||||
$registrationAgency = 'DataciteExportPlugin';
|
||||
}
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
} elseif (isset($item['datacite::registeredDoi'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
}
|
||||
$statuses[$item['doi_id']] = ['status' => $status];
|
||||
$registrationAgencies[$item['doi_id']] = $registrationAgency;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Insert updated statuses
|
||||
foreach ($statuses as $doiId => $insert) {
|
||||
DB::table('dois')
|
||||
->where('doi_id', '=', $doiId)
|
||||
->update($insert);
|
||||
}
|
||||
|
||||
foreach ($registrationAgencies as $doiId => $agency) {
|
||||
if ($agency === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('doi_settings')
|
||||
->insert([
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'registrationAgency',
|
||||
'setting_value' => $agency
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. Clean up old settings
|
||||
DB::table('issue_settings')
|
||||
->whereIn('setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->delete();
|
||||
|
||||
// ===== Publications Statuses & Settings ===== //
|
||||
// 1. Get publications with Datacite-related info
|
||||
$publicationData = DB::table('submissions', 's')
|
||||
->leftJoin('submission_settings as ss', 's.submission_id', '=', 'ss.submission_id')
|
||||
->leftJoin('publications as p', 's.current_publication_id', '=', 'p.publication_id')
|
||||
->whereIn('ss.setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->select(['p.publication_id', 'p.doi_id', 'ss.setting_name', 'ss.setting_value'])
|
||||
->get()
|
||||
->reduce(function ($carry, $item) {
|
||||
if (!isset($carry[$item->publication_id])) {
|
||||
$carry[$item->publication_id] = [
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
}
|
||||
|
||||
$carry[$item->publication_id][$item->setting_name] = $item->setting_value;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
// 2. Map statuses insert statements
|
||||
$statuses = [];
|
||||
$registrationAgencies = [];
|
||||
foreach ($publicationData as $item) {
|
||||
// Status
|
||||
if (isset($item['datacite::status'])) {
|
||||
$status = Doi::STATUS_ERROR;
|
||||
$registrationAgency = null;
|
||||
if (in_array($item['datacite::status'], ['found', 'registered', 'markedRegistered'])) {
|
||||
if ($item['datacite::status'] === 'registered') {
|
||||
$registrationAgency = 'DataciteExportPlugin';
|
||||
}
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
} elseif (isset($item['datacite::registeredDoi'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
}
|
||||
$statuses[$item['doi_id']] = ['status' => $status];
|
||||
$registrationAgencies[$item['doi_id']] = $registrationAgency;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Insert updated statuses
|
||||
foreach ($statuses as $doiId => $insert) {
|
||||
DB::table('dois')
|
||||
->where('doi_id', '=', $doiId)
|
||||
->update($insert);
|
||||
}
|
||||
|
||||
foreach ($registrationAgencies as $doiId => $agency) {
|
||||
if ($agency === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('doi_settings')
|
||||
->insert([
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'registrationAgency',
|
||||
'setting_value' => $agency
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. Clean up old settings
|
||||
DB::table('publication_settings')
|
||||
->whereIn('setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->delete();
|
||||
|
||||
// ===== Galleys Statuses & Settings ===== //
|
||||
// 1. Get galleys with Datacite-related info
|
||||
$galleyData = DB::table('publication_galleys', 'pg')
|
||||
->leftJoin('publication_galley_settings as pgs', 'pg.galley_id', '=', 'pgs.galley_id')
|
||||
->whereIn('pgs.setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->select(['pg.galley_id', 'pg.doi_id', 'pgs.setting_name', 'pgs.setting_value'])
|
||||
->get()
|
||||
->reduce(function ($carry, $item) {
|
||||
if (!isset($carry[$item->galley_id])) {
|
||||
$carry[$item->galley_id] = [
|
||||
'doi_id' => $item->doi_id
|
||||
];
|
||||
}
|
||||
|
||||
$carry[$item->galley_id][$item->setting_name] = $item->setting_value;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
// 2. Map statuses insert statements
|
||||
$statuses = [];
|
||||
$registrationAgencies = [];
|
||||
foreach ($galleyData as $item) {
|
||||
// Status
|
||||
if (isset($item['datacite::status'])) {
|
||||
$status = Doi::STATUS_ERROR;
|
||||
$registrationAgency = null;
|
||||
if (in_array($item['datacite::status'], ['found', 'registered', 'markedRegistered'])) {
|
||||
if ($item['datacite::status'] === 'registered') {
|
||||
$registrationAgency = 'DataciteExportPlugin';
|
||||
}
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
} elseif (isset($item['datacite::registeredDoi'])) {
|
||||
$status = Doi::STATUS_REGISTERED;
|
||||
}
|
||||
$statuses[$item['doi_id']] = ['status' => $status];
|
||||
$registrationAgencies[$item['doi_id']] = $registrationAgency;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Insert updated statuses
|
||||
foreach ($statuses as $doiId => $insert) {
|
||||
DB::table('dois')
|
||||
->where('doi_id', '=', $doiId)
|
||||
->update($insert);
|
||||
}
|
||||
|
||||
foreach ($registrationAgencies as $doiId => $agency) {
|
||||
if ($agency === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('doi_settings')
|
||||
->insert([
|
||||
'doi_id' => $doiId,
|
||||
'setting_name' => 'registrationAgency',
|
||||
'setting_value' => $agency
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. Clean up old settings
|
||||
DB::table('publication_galley_settings')
|
||||
->whereIn('setting_name', ['datacite::registeredDoi', 'datacite::status'])
|
||||
->delete();
|
||||
|
||||
// ===== General cleanup ===== //
|
||||
|
||||
// If any Datacite settings are configured, assume plugin is in use and enable
|
||||
$contextsWithPluginEnabled = DB::table('journals')
|
||||
->whereIn('journal_id', function (Builder $q) {
|
||||
$q->select('context_id')
|
||||
->from('plugin_settings')
|
||||
->where('plugin_name', '=', 'dataciteexportplugin');
|
||||
})
|
||||
->select(['journal_id'])
|
||||
->get();
|
||||
$contextsWithPluginEnabled->each(function ($item) {
|
||||
DB::table('plugin_settings')
|
||||
->insert(
|
||||
[
|
||||
'plugin_name' => 'dataciteplugin',
|
||||
'context_id' => $item->journal_id,
|
||||
'setting_name' => 'enabled',
|
||||
'setting_value' => 1,
|
||||
'setting_type' => 'bool'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Enable automatic DOI deposit if configured
|
||||
$contextsWithAutomaticDeposit = DB::table('journals')
|
||||
->whereIn('journal_id', function (Builder $q) {
|
||||
$q->select(['context_id'])
|
||||
->from('plugin_settings')
|
||||
->where('plugin_name', '=', 'dataciteexportplugin')
|
||||
->where('setting_name', '=', 'automaticRegistration')
|
||||
->where('setting_value', '=', 1) ;
|
||||
})
|
||||
->select(['journal_id'])
|
||||
->get();
|
||||
$contextsWithAutomaticDeposit->each(function ($item) {
|
||||
DB::table('journal_settings')
|
||||
->upsert(
|
||||
[
|
||||
'journal_id' => $item->journal_id,
|
||||
'setting_name' => 'automaticDoiDeposit',
|
||||
'setting_value' => 1
|
||||
],
|
||||
['journal_id', 'locale', 'setting_name'],
|
||||
['setting_value']
|
||||
);
|
||||
});
|
||||
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'dataciteexportplugin')
|
||||
->where('setting_name', '=', 'automaticRegistration')
|
||||
->delete();
|
||||
|
||||
// Update no-longer-in-use version for importExport plugin
|
||||
DB::table('versions')
|
||||
->where('product_type', '=', 'plugins.importexport')
|
||||
->where('product', '=', 'datacite')
|
||||
->delete();
|
||||
|
||||
// Remove scheduled task
|
||||
DB::table('scheduled_tasks')
|
||||
->where('class_name', '=', 'plugins.importexport.datacite.DataciteInfoSender')
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move galley DOIs from publication_galley_settings table to DOI objects
|
||||
*/
|
||||
private function _migrateGalleyDoisUp(): void
|
||||
{
|
||||
$q = DB::table('submissions', 's')
|
||||
->select(['s.context_id', 'pg.galley_id', 'pg.doi_id', 'pgss.setting_name', 'pgss.setting_value'])
|
||||
->leftJoin('publications as p', 'p.submission_id', '=', 's.submission_id')
|
||||
->leftJoin('publication_galleys as pg', 'pg.publication_id', '=', 'p.publication_id')
|
||||
->leftJoin('publication_galley_settings as pgss', 'pgss.galley_id', '=', 'pg.galley_id')
|
||||
->where('pgss.setting_name', '=', 'pub-id::doi');
|
||||
|
||||
$q->chunkById(1000, function ($items) {
|
||||
foreach ($items as $item) {
|
||||
// Double-check to ensure a DOI object does not already exist for galley
|
||||
if ($item->doi_id === null) {
|
||||
$doiId = $this->_addDoi($item->context_id, $item->setting_value);
|
||||
|
||||
// Add association to newly created DOI to galley
|
||||
DB::table('publication_galleys')
|
||||
->where('galley_id', '=', $item->galley_id)
|
||||
->update(['doi_id' => $doiId]);
|
||||
} else {
|
||||
// Otherwise update existing DOI object
|
||||
$this->_updateDoi($item->doi_id, $item->context_id, $item->setting_value);
|
||||
}
|
||||
}
|
||||
}, 'pg.galley_id', 'galley_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Move issue DOIs from issue_settings table to DOI objects
|
||||
*/
|
||||
private function _migrateIssueDoisUp(): void
|
||||
{
|
||||
$q = DB::table('issues', 'i')
|
||||
->select(['i.issue_id', 'i.journal_id', 'i.doi_id', 'iss.setting_name', 'iss.setting_value'])
|
||||
->leftJoin('issue_settings as iss', 'iss.issue_id', '=', 'i.issue_id')
|
||||
->where('iss.setting_name', '=', 'pub-id::doi');
|
||||
|
||||
$q->chunkById(1000, function ($items) {
|
||||
foreach ($items as $item) {
|
||||
// Double-check to ensure a DOI object does not already exist for issue
|
||||
if ($item->doi_id === null) {
|
||||
$doiId = $this->_addDoi($item->journal_id, $item->setting_value);
|
||||
|
||||
// Add association to newly created DOI to issue
|
||||
DB::table('issues')
|
||||
->where('issue_id', '=', $item->issue_id)
|
||||
->update(['doi_id' => $doiId]);
|
||||
} else {
|
||||
// Otherwise update existing DOI object
|
||||
$this->_updateDoi($item->doi_id, $item->journal_id, $item->setting_value);
|
||||
}
|
||||
}
|
||||
}, 'i.issue_id', 'issue_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets app-specific context table name, e.g. journals
|
||||
*
|
||||
*/
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets app-specific context_id column, e.g. journal_id
|
||||
*/
|
||||
protected function getContextIdColumn(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets app-specific context settings table, e.g. journal_settings
|
||||
*/
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds app-specific suffix patterns to data collector stdClass
|
||||
*/
|
||||
protected function addSuffixPatternsData(\stdClass $data): \stdClass
|
||||
{
|
||||
$data->doiIssueSuffixPattern = [];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add suffix pattern settings from DB into reducer's data
|
||||
*/
|
||||
protected function insertSuffixPatternsData(\stdClass $carry, \stdClass $item): \stdClass
|
||||
{
|
||||
switch ($item->setting_name) {
|
||||
case 'doiIssueSuffixPattern':
|
||||
$carry->doiIssueSuffixPattern[] = [
|
||||
$this->getContextIdColumn() => $item->context_id,
|
||||
'setting_name' => $item->setting_name,
|
||||
'setting_value' => $item->setting_value,
|
||||
];
|
||||
return $carry;
|
||||
default:
|
||||
return $carry;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add insert-ready statements for all applicable suffix pattern items
|
||||
*/
|
||||
protected function prepareSuffixPatternsForInsert(\stdClass $processedData, array $insertData): array
|
||||
{
|
||||
foreach ($processedData->doiIssueSuffixPattern as $item) {
|
||||
$insertData[] = $item;
|
||||
}
|
||||
|
||||
return $insertData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add app-specific enabled DOI types for insert into DB
|
||||
*/
|
||||
protected function insertEnabledDoiTypes(\stdClass $carry, \stdClass $item): \stdClass
|
||||
{
|
||||
if ($item->setting_name === 'enableIssueDoi') {
|
||||
if (!isset($carry->enabledDoiTypes[$item->context_id])) {
|
||||
$carry->enabledDoiTypes[$item->context_id] = [
|
||||
$this->getContextIdColumn() => $item->context_id,
|
||||
'setting_name' => 'enabledDoiTypes',
|
||||
'setting_value' => [],
|
||||
];
|
||||
}
|
||||
|
||||
if ($item->setting_value === '1') {
|
||||
$carry->enabledDoiTypes[$item->context_id]['setting_value'][] = 'issue';
|
||||
}
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array with the keys for each suffix pattern type
|
||||
*/
|
||||
protected function getSuffixPatternNames(): array
|
||||
{
|
||||
return ['doiPublicationSuffixPattern', 'doiRepresentationSuffixPattern', 'doiIssueSuffixPattern'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default pattern for the given suffix pattern type
|
||||
*/
|
||||
protected function getSuffixPatternValue(string $suffixPatternName): string
|
||||
{
|
||||
$pattern = '';
|
||||
switch ($suffixPatternName) {
|
||||
case 'doiPublicationSuffixPattern':
|
||||
$pattern = '%j.v%vi%i.%a';
|
||||
break;
|
||||
case 'doiRepresentationSuffixPattern':
|
||||
$pattern = '%j.v%vi%i.%a.g%g';
|
||||
break;
|
||||
case 'doiIssueSuffixPattern':
|
||||
$pattern = '%j.v%vi%i';
|
||||
break;
|
||||
}
|
||||
|
||||
return $pattern;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\APP\migration\upgrade\v3_4_0\I7014_DoiMigration', '\I7014_DoiMigration');
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7128_SectionEntityDAORefactor.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7128_SectionEntityDAORefactor
|
||||
*
|
||||
* @brief Remove deprecated setting_type requirement after converting the section DAO to use new repository pattern
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
|
||||
class I7128_SectionEntityDAORefactor extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
if (Schema::hasColumn('section_settings', 'setting_type')) {
|
||||
Schema::table('section_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('setting_type');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7129_IssueEntityDAORefactor.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 I7129_IssueEntityDAORefactor
|
||||
*
|
||||
* @brief Convert issue DAO to use new repository pattern
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I7129_IssueEntityDAORefactor extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Remove deprecated setting_type requirement
|
||||
Schema::table('issue_settings', function (Blueprint $table) {
|
||||
$table->string('setting_type', 6)->nullable()->change();
|
||||
});
|
||||
|
||||
// Move current issue status from Issue to Journal
|
||||
Schema::table('journals', function (Blueprint $table) {
|
||||
$table->bigInteger('current_issue_id')->nullable()->default(null);
|
||||
$table->foreign('current_issue_id')->references('issue_id')->on('issues')->onDelete('set null');
|
||||
$table->index(['current_issue_id'], 'journals_current_issue_id');
|
||||
});
|
||||
$this->transferCurrentStatusToJournal();
|
||||
Schema::table('issues', function (Blueprint $table) {
|
||||
$table->dropColumn('current');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Restore deprecated setting_type requirement
|
||||
Schema::table('issue_settings', function (Blueprint $table) {
|
||||
$table->string('setting_type', 6)->change();
|
||||
});
|
||||
|
||||
// Move current issue status back to Issue from Journal
|
||||
Schema::table('issues', function (Blueprint $table) {
|
||||
$table->smallInteger('current')->default(0);
|
||||
});
|
||||
$this->transferCurrentStatusToIssue();
|
||||
Schema::table('journals', function (Blueprint $table) {
|
||||
$table->dropForeign('journals_current_issue_id_foreign');
|
||||
$table->dropColumn('current_issue_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers current issue status from Issue to Journal for each journal
|
||||
*/
|
||||
private function transferCurrentStatusToJournal()
|
||||
{
|
||||
$contexts = DB::table('journals', 'j')
|
||||
->select('j.journal_id')
|
||||
->get();
|
||||
|
||||
foreach ($contexts as $context) {
|
||||
$currentIssue = DB::table('issues', 'i')
|
||||
->select('i.issue_id')
|
||||
->where('i.journal_id', '=', $context->journal_id)
|
||||
->where('i.current', '=', 1)
|
||||
->get()
|
||||
->first();
|
||||
|
||||
if ($currentIssue !== null) {
|
||||
DB::table('journals', 'j')
|
||||
->where('j.journal_id', '=', $context->journal_id)
|
||||
->update(['current_issue_id' => $currentIssue->issue_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer current issue status from Journal to Issue for each journal
|
||||
private function transferCurrentStatusToIssue()
|
||||
{
|
||||
$contexts = DB::table('journals', 'j')
|
||||
->select('j.current_issue_id')
|
||||
->get();
|
||||
|
||||
foreach ($contexts as $context) {
|
||||
if ($context->current_issue_id != null) {
|
||||
DB::table('issues', 'i')
|
||||
->where('i.issue_id', '=', $context->current_issue_id)
|
||||
->update(['i.current' => 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\APP\migration\upgrade\v3_4_0\I7129_IssueEntityDAORefactor', '\I7129_IssueEntityDAORefactor');
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7186_OpenAccessNotification.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7186_OpenAccessNotification
|
||||
*
|
||||
* @brief Migrate the user's open access subscription setting from OJS 2.4.8 to
|
||||
* the notification subscriptions table.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I7186_OpenAccessNotification extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$userIds = DB::table('users')
|
||||
->whereNotIn('user_id', function (Builder $query) {
|
||||
$query->select('user_id')
|
||||
->from('user_settings')
|
||||
->where('setting_name', 'openAccessNotification')
|
||||
->where('setting_value', '1');
|
||||
})
|
||||
->pluck('user_id');
|
||||
|
||||
$contextIds = DB::table('journals')->pluck('journal_id');
|
||||
|
||||
$rows = [];
|
||||
foreach ($userIds as $userId) {
|
||||
foreach ($contextIds as $contextId) {
|
||||
$rows[] = [
|
||||
'setting_name' => 'blocked_emailed_notification',
|
||||
'setting_value' => 50331659, // Notification::NOTIFICATION_TYPE_OPEN_ACCESS
|
||||
'user_id' => $userId,
|
||||
'context' => $contextId,
|
||||
'setting_type' => 'int',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
DB::table('notification_subscription_settings')->insert($rows);
|
||||
|
||||
DB::table('user_settings')
|
||||
->where('setting_name', 'openAccessNotification')
|
||||
->where('setting_value', '1')
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7190_RemoveOrphanFilters.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 I7190_RemoveOrphanFilters
|
||||
*
|
||||
* @brief Remove old filters which have been left behind
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
|
||||
class I7190_RemoveOrphanFilters extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('filter_groups')
|
||||
->whereNotIn(
|
||||
'symbolic',
|
||||
[
|
||||
'mods34=>mods34-xml',
|
||||
'SubmissionArtworkFile=>native-xml',
|
||||
'SupplementaryFile=>native-xml',
|
||||
'native-xml=>SubmissionArtworkFile',
|
||||
'native-xml=>SupplementaryFile'
|
||||
]
|
||||
)
|
||||
->delete();
|
||||
|
||||
DB::table('filters')
|
||||
->whereNotExists(
|
||||
fn (Builder $query) => $query
|
||||
->from('filter_groups', 'fg')
|
||||
->whereColumn('fg.filter_group_id', '=', 'filters.filter_group_id')
|
||||
)
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7191_EditorAssignments.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 I7191_EditorAssignments
|
||||
*
|
||||
* @brief Update the subeditor_submission_group table to accomodate new editor assignment settings
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I7191_EditorAssignments extends \PKP\migration\upgrade\v3_4_0\I7191_EditorAssignments
|
||||
{
|
||||
protected string $sectionDb = 'sections';
|
||||
protected string $sectionIdColumn = 'section_id';
|
||||
protected string $contextColumn = 'journal_id';
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7191_InstallSubmissionHelpDefaults.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 I7191_InstallSubmissionHelpDefaults
|
||||
*
|
||||
* @brief Migrate the submissionChecklist setting from an array to a HTML string
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I7191_InstallSubmissionHelpDefaults extends \PKP\migration\upgrade\v3_4_0\I7191_InstallSubmissionHelpDefaults
|
||||
{
|
||||
protected string $CONTEXT_TABLE = 'journals';
|
||||
protected string $CONTEXT_SETTINGS_TABLE = 'journal_settings';
|
||||
protected string $CONTEXT_COLUMN = 'journal_id';
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7191_SubmissionChecklistMigration.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 I7191_SubmissionChecklistMigration
|
||||
*
|
||||
* @brief Migrate the submissionChecklist setting from an array to a HTML string
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I7191_SubmissionChecklistMigration extends \PKP\migration\upgrade\v3_4_0\I7191_SubmissionChecklistMigration
|
||||
{
|
||||
protected string $CONTEXT_SETTINGS_TABLE = 'journal_settings';
|
||||
protected string $CONTEXT_COLUMN = 'journal_id';
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7264_UpdateEmailTemplates.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 I7264_UpdateEmailTemplates
|
||||
*
|
||||
* @brief Describe upgrade/downgrade operations for DB table email_templates.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I7264_UpdateEmailTemplates extends \PKP\migration\upgrade\v3_4_0\I7264_UpdateEmailTemplates
|
||||
{
|
||||
protected function oldNewVariablesMap(): array
|
||||
{
|
||||
$oldNewVariablesMap = parent::oldNewVariablesMap();
|
||||
array_walk_recursive($oldNewVariablesMap, function (&$newVariable, $oldVariable) {
|
||||
if ($newVariable === 'contextName') {
|
||||
$newVariable = 'journalName';
|
||||
} elseif ($newVariable === 'contextUrl') {
|
||||
$newVariable = 'journalUrl';
|
||||
} elseif ($newVariable === 'contextSignature') {
|
||||
$newVariable = 'journalSignature';
|
||||
} elseif ($newVariable === 'contextAcronym') {
|
||||
$newVariable = 'journalAcronym';
|
||||
}
|
||||
});
|
||||
|
||||
return $oldNewVariablesMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7265_EditorialDecisions.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7265_EditorialDecisions
|
||||
*
|
||||
* @brief Database migrations for editorial decision refactor.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I7265_EditorialDecisions extends \PKP\migration\upgrade\v3_4_0\I7265_EditorialDecisions
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
$this->upNewDecisions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
parent::down();
|
||||
$this->downNewDecisions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change decisions taken in submission stage
|
||||
*
|
||||
* APP\decision\Decision::ACCEPT = 1
|
||||
* APP\decision\Decision::REVERT_DECLINE = 17
|
||||
*
|
||||
* When these decisions have been recorded in
|
||||
* the submission stage they must become become:
|
||||
*
|
||||
* APP\decision\Decision::SKIP_EXTERNAL_REVIEW = 19
|
||||
* APP\decision\Decision::REVERT_INITIAL_DECLINE = 18
|
||||
*
|
||||
* In 3.3 and earlier, the decision constants were global
|
||||
* and named:
|
||||
*
|
||||
* Decision::ACCEPT
|
||||
* Decision::REVERT_DECLINE
|
||||
*/
|
||||
public function upNewDecisions()
|
||||
{
|
||||
DB::table('edit_decisions')
|
||||
->where('stage_id', '=', 1) // WORKFLOW_STAGE_ID_SUBMISSION
|
||||
->where('decision', '=', 1) // APP\decision\Decision::ACCEPT
|
||||
->update([
|
||||
'decision' => 19, // APP\decision\Decision::SKIP_EXTERNAL_REVIEW
|
||||
]);
|
||||
DB::table('edit_decisions')
|
||||
->where('stage_id', '=', 1) // WORKFLOW_STAGE_ID_SUBMISSION
|
||||
->where('decision', '=', 17) // APP\decision\Decision::REVERT_DECLINE
|
||||
->update([
|
||||
'decision' => 18, // APP\decision\Decision::REVERT_INITIAL_DECLINE
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the decision type changes
|
||||
*
|
||||
* @see self::upNewSubmissionDecisions()
|
||||
*/
|
||||
public function downNewDecisions()
|
||||
{
|
||||
DB::table('edit_decisions')
|
||||
->where('stage_id', '=', 1) // WORKFLOW_STAGE_ID_SUBMISSION
|
||||
->where('decision', '=', 19) // APP\decision\Decision::ACCEPT
|
||||
->update([
|
||||
'decision' => 1, // APP\decision\Decision::ACCEPT
|
||||
]);
|
||||
DB::table('edit_decisions')
|
||||
->where('stage_id', '=', 1) // WORKFLOW_STAGE_ID_SUBMISSION
|
||||
->where('decision', '=', 18) // APP\decision\Decision::REVERT_INITIAL_DECLINE
|
||||
->update([
|
||||
'decision' => 17, // APP\decision\Decision::REVERT_DECLINE
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
protected function getContextIdColumn(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7470_FixDeprecatedFileStage.php
|
||||
*
|
||||
* Copyright (c) 2023 Simon Fraser University
|
||||
* Copyright (c) 2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7470_FixDeprecatedFileStage.php
|
||||
*
|
||||
* @brief Redirect deprecated file stages that remained after the OJS 2 > 3 migration.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I7470_FixDeprecatedFileStage extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('submission_files')
|
||||
// From SUBMISSION_FILE_FAIR_COPY
|
||||
->where('file_stage', 7)
|
||||
// To \PKP\submissionFile::SUBMISSION_FILE_FINAL
|
||||
->update(['file_stage' => 6]);
|
||||
DB::table('submission_files')
|
||||
// From SUBMISSION_FILE_EDITOR
|
||||
->where('file_stage', 8)
|
||||
// To \PKP\submissionFile::SUBMISSION_FILE_COPYEDIT
|
||||
->update(['file_stage' => 9]);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7513_DoiSettings.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7513_DoiSettings
|
||||
*
|
||||
* @brief Database migrations for DOI settings refactor.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I7513_DoiSettings extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'crossrefexportplugin')
|
||||
->update(['plugin_name' => 'crossrefplugin']);
|
||||
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'dataciteexportplugin')
|
||||
->update(['plugin_name' => 'dataciteplugin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'crossrefplugin')
|
||||
->whereNot('setting_name', '=', 'enabled')
|
||||
->update(['plugin_name' => 'crossrefexportplugin']);
|
||||
|
||||
DB::table('plugin_settings')
|
||||
->where('plugin_name', '=', 'dataciteplugin')
|
||||
->whereNot('setting_name', '=', 'enabled')
|
||||
->update(['plugin_name' => 'dataciteexportplugin']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7520_IssueGalleyLabelLength.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 I7520_IssueGalleyLabelLength
|
||||
*
|
||||
* @brief This migration increases the length of the issue galley label column in the database
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I7520_IssueGalleyLabelLength extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('issue_galleys', function (Blueprint $table) {
|
||||
$table->string('label', 255)->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('issue_galleys', function (Blueprint $table) {
|
||||
$table->string('label', 32)->nullable()->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7596_RemoveNonExpiring.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 I7596_RemoveNonExpiring
|
||||
*
|
||||
* @brief Remove the subscription non_expiring column if it exists.
|
||||
* By OJS 3.3.0-x the non-expiring state of the subscription was determined by
|
||||
* the NULL status of the duration column, but not all code had been updated to
|
||||
* reflect this. Issue 7596 converts the outstanding cases to check the
|
||||
* duration column instead, and this migration removes the superfluous column.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I7596_RemoveNonExpiring extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Installations that began with OJS 3.3.0 will not have this column.
|
||||
// Older installations will.
|
||||
if (Schema::hasColumn('subscription_types', 'non_expiring')) {
|
||||
Schema::table('subscription_types', function (Blueprint $table) {
|
||||
$table->dropColumn('non_expiring');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Regardless of whether the column existed before the migration was
|
||||
// executed, OJS 3.3.x did not use it and it should not be re-added.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7725_DecisionConstantsUpdate.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7725_DecisionConstantsUpdate
|
||||
*
|
||||
* @brief Editorial decision constant sync up across all application
|
||||
*
|
||||
* @see https://github.com/pkp/pkp-lib/issues/7725
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I7725_DecisionConstantsUpdate extends \PKP\migration\upgrade\v3_4_0\I7725_DecisionConstantsUpdate
|
||||
{
|
||||
/**
|
||||
* Get the decisions constants mappings
|
||||
*
|
||||
*/
|
||||
public function getDecisionMappings(): array
|
||||
{
|
||||
return [
|
||||
// \PKP\decision\Decision::ACCEPT
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EDITING],
|
||||
'current_value' => 1,
|
||||
'updated_value' => 2,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::EXTERNAL_REVIEW
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 8,
|
||||
'updated_value' => 3,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::PENDING_REVISIONS
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 2,
|
||||
'updated_value' => 4,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::RESUBMIT
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 3,
|
||||
'updated_value' => 5,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::DECLINE
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 4,
|
||||
'updated_value' => 6,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::INITIAL_DECLINE
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_SUBMISSION],
|
||||
'current_value' => 9,
|
||||
'updated_value' => 8,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::RECOMMEND_ACCEPT
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 11,
|
||||
'updated_value' => 9,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::RECOMMEND_PENDING_REVISIONS
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 12,
|
||||
'updated_value' => 10,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::RECOMMEND_RESUBMIT
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 13,
|
||||
'updated_value' => 11,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::RECOMMEND_DECLINE
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 14,
|
||||
'updated_value' => 12,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::NEW_EXTERNAL_ROUND
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 16,
|
||||
'updated_value' => 14,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::REVERT_DECLINE
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 17,
|
||||
'updated_value' => 15,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::REVERT_INITIAL_DECLINE
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_SUBMISSION],
|
||||
'current_value' => 18,
|
||||
'updated_value' => 16
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::SKIP_EXTERNAL_REVIEW
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EDITING],
|
||||
'current_value' => 19,
|
||||
'updated_value' => 17,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::BACK_FROM_PRODUCTION
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_EDITING],
|
||||
'current_value' => 31,
|
||||
'updated_value' => 29,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::BACK_FROM_COPYEDITING
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_SUBMISSION, WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 32,
|
||||
'updated_value' => 30,
|
||||
],
|
||||
|
||||
// \PKP\decision\Decision::CANCEL_REVIEW_ROUND
|
||||
[
|
||||
'stage_id' => [WORKFLOW_STAGE_ID_SUBMISSION, WORKFLOW_STAGE_ID_EXTERNAL_REVIEW],
|
||||
'current_value' => 33,
|
||||
'updated_value' => 31,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7796_UpdateCrossrefSchema.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I7796_UpdateCrossrefSchema
|
||||
*
|
||||
* @brief Upgrade Crossref schema in filter_groups.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
|
||||
class I7796_UpdateCrossrefSchema extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::table('filter_groups')
|
||||
->where('output_type', 'xml::schema(https://www.crossref.org/schemas/crossref4.3.6.xsd)')
|
||||
->update(['output_type' => 'xml::schema(https://www.crossref.org/schemas/crossref5.3.1.xsd)']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I7901_Duplicate_OAI_IDs.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 I7901_Duplicate_OAI_IDs
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I7901_Duplicate_OAI_IDs extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql':
|
||||
DB::unprepared(
|
||||
"DELETE dot
|
||||
FROM data_object_tombstones dot
|
||||
JOIN submissions s ON (dot.data_object_id = s.submission_id)
|
||||
JOIN journals j ON (j.journal_id = s.context_id)
|
||||
JOIN publications p ON (s.current_publication_id = p.publication_id)
|
||||
JOIN publication_settings psissue ON (psissue.publication_id = p.publication_id AND psissue.setting_name='issueId' AND psissue.locale='')
|
||||
JOIN issues i ON (CAST(i.issue_id AS CHAR(20)) = psissue.setting_value)
|
||||
WHERE i.published = 1 AND j.enabled = 1 AND p.status = 3"
|
||||
);
|
||||
break;
|
||||
case 'pgsql':
|
||||
DB::unprepared(
|
||||
"DELETE FROM data_object_tombstones dot
|
||||
USING submissions s, journals j, publications p, publication_settings psissue, issues i
|
||||
WHERE dot.data_object_id = s.submission_id
|
||||
AND j.journal_id = s.context_id
|
||||
AND s.current_publication_id = p.publication_id
|
||||
AND psissue.publication_id = p.publication_id
|
||||
AND psissue.setting_name='issueId' AND psissue.locale='' AND (CAST(i.issue_id AS CHAR(20)) = psissue.setting_value)
|
||||
AND i.published = 1 AND j.enabled = 1 AND p.status = 3"
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// The migration deletes bad data, which is not recovered on downgrade.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I8027_DoiVersioning.php
|
||||
*
|
||||
* Copyright (c) 2022 Simon Fraser University
|
||||
* Copyright (c) 2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I8027_DoiVersioning
|
||||
*
|
||||
* @brief Add new DOI versioning context setting
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class I8027_DoiVersioning extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$journalIds = DB::table('journals')
|
||||
->distinct()
|
||||
->get(['journal_id']);
|
||||
$insertStatements = $journalIds->reduce(function ($carry, $item) {
|
||||
$carry[] = [
|
||||
'journal_id' => $item->journal_id,
|
||||
'setting_name' => 'doiVersioning',
|
||||
'setting_value' => 0
|
||||
];
|
||||
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
DB::table('journal_settings')
|
||||
->insert($insertStatements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('journal_settings')
|
||||
->where('setting_name', '=', 'doiVersioning')
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I8151_ExtendSettingValues.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 I8151_ExtendSettingValues
|
||||
*
|
||||
* @brief Describe upgrade/downgrade operations for extending TEXT columns to MEDIUMTEXT
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class I8151_ExtendSettingValues extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('section_settings', function (Blueprint $table) {
|
||||
$table->mediumText('setting_value')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('issue_settings', function (Blueprint $table) {
|
||||
$table->mediumText('setting_value')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('issue_galley_settings', function (Blueprint $table) {
|
||||
$table->mediumText('setting_value')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('publication_galley_settings', function (Blueprint $table) {
|
||||
$table->mediumText('setting_value')->nullable()->change();
|
||||
});
|
||||
|
||||
Schema::table('subscription_type_settings', function (Blueprint $table) {
|
||||
$table->mediumText('setting_value')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// This downgrade is intentionally not implemented. Changing MEDIUMTEXT back to TEXT
|
||||
// may result in data truncation. Having MEDIUMTEXT in place of TEXT in an otherwise
|
||||
// downgraded database will not have side-effects.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I8933_EventLogLocalized.php
|
||||
*
|
||||
* Copyright (c) 2023 Simon Fraser University
|
||||
* Copyright (c) 2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I8933_EventLogLocalized.php
|
||||
*
|
||||
* @brief Extends the event log migration with the correct table names for OJS.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I8933_EventLogLocalized extends \PKP\migration\upgrade\v3_4_0\I8933_EventLogLocalized
|
||||
{
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextIdColumn(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I8992_FixEmptyUrlPaths.php
|
||||
*
|
||||
* Copyright (c) 2014-2023 Simon Fraser University
|
||||
* Copyright (c) 2000-2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I8992_FixEmptyUrlPaths.php
|
||||
*
|
||||
* @brief Standardize the url columns to hold NULL instead of NULL/empty string.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I8992_FixEmptyUrlPaths extends \PKP\migration\upgrade\v3_4_0\I8992_FixEmptyUrlPaths
|
||||
{
|
||||
/**
|
||||
* @copydoc \PKP\migration\upgrade\v3_4_0\I8992_FixEmptyUrlPaths::getFieldset()
|
||||
*/
|
||||
protected function getFieldset(): array
|
||||
{
|
||||
return array_merge(parent::getFieldset(), [
|
||||
['publication_galleys', 'url_path'],
|
||||
['publication_galleys', 'remote_url'],
|
||||
['issue_galleys', 'url_path'],
|
||||
['issues', 'url_path']
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I9040_DropSettingType.php
|
||||
*
|
||||
* Copyright (c) 2023 Simon Fraser University
|
||||
* Copyright (c) 2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I9040_DropSettingType
|
||||
*
|
||||
* @brief Drop not needed setting_type fields
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class I9040_DropSettingType extends \PKP\migration\upgrade\v3_4_0\I9040_DropSettingType
|
||||
{
|
||||
/**
|
||||
* @copydoc \PKP\migration\upgrade\v3_4_0\I9040_DropSettingType::getEntities()
|
||||
*/
|
||||
protected function getEntities(): array
|
||||
{
|
||||
return array_merge(parent::getEntities(), ['journal_settings', 'issue_settings']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/I9231_FixMetricsIndexes.php
|
||||
*
|
||||
* Copyright (c) 2023 Simon Fraser University
|
||||
* Copyright (c) 2023 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class I9231_FixMetricsIndexes
|
||||
*
|
||||
* @brief Use smaller data type for load_id, and use city column prefix index for MySQL.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema as Schema;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
use PKP\migration\Migration;
|
||||
|
||||
class I9231_FixMetricsIndexes extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Decrease the size of the column load_id to 50 characters
|
||||
$loadIdTables = [
|
||||
'metrics_context',
|
||||
'metrics_submission',
|
||||
'metrics_issue',
|
||||
'metrics_counter_submission_daily',
|
||||
'metrics_counter_submission_institution_daily',
|
||||
'metrics_submission_geo_daily',
|
||||
'usage_stats_total_temporary_records',
|
||||
'usage_stats_unique_item_investigations_temporary_records',
|
||||
'usage_stats_unique_item_requests_temporary_records',
|
||||
'usage_stats_institution_temporary_records'
|
||||
];
|
||||
foreach ($loadIdTables as $loadIdTable) {
|
||||
Schema::table($loadIdTable, function (Blueprint $table) {
|
||||
$table->string('load_id', 50)->change();
|
||||
});
|
||||
}
|
||||
|
||||
// Drop the too big unique indexes
|
||||
// msgd_uc_load_context_submission_c_r_c_date and
|
||||
// msgm_uc_context_submission_c_r_c_month,
|
||||
// and create new ones using city column prefix for MySQL
|
||||
Schema::table('metrics_submission_geo_daily', function (Blueprint $table) {
|
||||
$table->dropUnique('msgd_uc_load_context_submission_c_r_c_date');
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql':
|
||||
$table->unique([DB::raw('load_id, context_id, submission_id, country, region, city(80), date')], 'msgd_uc_load_context_submission_c_r_c_date');
|
||||
break;
|
||||
case 'pgsql':
|
||||
$table->unique(['load_id', 'context_id', 'submission_id', 'country', 'region', 'city', 'date'], 'msgd_uc_load_context_submission_c_r_c_date');
|
||||
break;
|
||||
}
|
||||
});
|
||||
Schema::table('metrics_submission_geo_monthly', function (Blueprint $table) {
|
||||
$table->dropUnique('msgm_uc_context_submission_c_r_c_month');
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql':
|
||||
$table->unique([DB::raw('context_id, submission_id, country, region, city(80), month')], 'msgm_uc_context_submission_c_r_c_month');
|
||||
break;
|
||||
case 'pgsql':
|
||||
$table->unique(['context_id', 'submission_id', 'country', 'region', 'city', 'month'], 'msgm_uc_context_submission_c_r_c_month');
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the downgrades
|
||||
*
|
||||
* @throws DowngradeNotSupportedException
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/InstallEmailTemplates.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class InstallEmailTemplates
|
||||
*
|
||||
* @brief Install new email templates for 3.4
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
class InstallEmailTemplates extends \PKP\migration\upgrade\v3_4_0\InstallEmailTemplates
|
||||
{
|
||||
protected function getEmailTemplateKeys(): array
|
||||
{
|
||||
return [
|
||||
'EDITOR_DECISION_NOTIFY_OTHER_AUTHORS',
|
||||
'EDITOR_DECISION_NOTIFY_REVIEWERS',
|
||||
'EDITOR_DECISION_NEW_ROUND',
|
||||
'EDITOR_DECISION_REVERT_DECLINE',
|
||||
'EDITOR_DECISION_REVERT_INITIAL_DECLINE',
|
||||
'EDITOR_DECISION_SKIP_REVIEW',
|
||||
'EDITORIAL_REMINDER',
|
||||
'EDITOR_DECISION_BACK_FROM_PRODUCTION',
|
||||
'EDITOR_DECISION_BACK_FROM_COPYEDITING',
|
||||
'EDITOR_DECISION_CANCEL_REVIEW_ROUND',
|
||||
'REVIEW_RESEND_REQUEST',
|
||||
'DISCUSSION_NOTIFICATION_SUBMISSION',
|
||||
'DISCUSSION_NOTIFICATION_REVIEW',
|
||||
'DISCUSSION_NOTIFICATION_COPYEDITING',
|
||||
'DISCUSSION_NOTIFICATION_PRODUCTION',
|
||||
'SUBMISSION_SAVED_FOR_LATER',
|
||||
'SUBMISSION_NEEDS_EDITOR',
|
||||
'PAYMENT_REQUEST_NOTIFICATION',
|
||||
'VERSION_CREATED',
|
||||
'REVIEW_COMPLETE',
|
||||
'REVIEW_EDIT',
|
||||
];
|
||||
}
|
||||
|
||||
protected function getAppVariableNames(): array
|
||||
{
|
||||
return [
|
||||
'contextName' => 'journalName',
|
||||
'contextUrl' => 'journalUrl',
|
||||
'contextSignature' => 'journalSignature',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/MergeLocalesMigration.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 MergeLocalesMigration
|
||||
*
|
||||
* @brief Change Locales from locale_countryCode localization folder notation to locale localization folder notation
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PKP\install\DowngradeNotSupportedException;
|
||||
|
||||
class MergeLocalesMigration extends \PKP\migration\upgrade\v3_4_0\MergeLocalesMigration
|
||||
{
|
||||
protected string $CONTEXT_TABLE = 'journals';
|
||||
protected string $CONTEXT_SETTINGS_TABLE = 'journal_settings';
|
||||
protected string $CONTEXT_COLUMN = 'journal_id';
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
|
||||
// issue_galleys
|
||||
$issueGalleys = DB::table('issue_galleys')
|
||||
->get();
|
||||
|
||||
foreach ($issueGalleys as $issueGalley) {
|
||||
$this->updateSingleValueLocale($issueGalley->locale, 'issue_galleys', 'locale', 'galley_id', $issueGalley->galley_id);
|
||||
}
|
||||
|
||||
// publication_galleys
|
||||
$publicationGalleys = DB::table('publication_galleys')
|
||||
->get();
|
||||
|
||||
foreach ($publicationGalleys as $publicationGalley) {
|
||||
$this->updateSingleValueLocale($publicationGalley->locale, 'publication_galleys', 'locale', 'galley_id', $publicationGalley->galley_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
throw new DowngradeNotSupportedException();
|
||||
}
|
||||
|
||||
public static function getSettingsTables(): Collection
|
||||
{
|
||||
return collect([
|
||||
'issue_galley_settings' => ['galley_id', 'issue_galley_setting_id'],
|
||||
'issue_settings' => ['issue_id', 'issue_setting_id'],
|
||||
'journal_settings' => ['journal_id', 'journal_setting_id'],
|
||||
'publication_galley_settings' => ['galley_id', 'publication_galley_setting_id'],
|
||||
'section_settings' => ['section_id', 'section_setting_id'],
|
||||
'static_page_settings' => ['static_page_id', 'static_page_setting_id'],
|
||||
'subscription_type_settings' => ['type_id', 'subscription_type_setting_id'],
|
||||
])->merge(parent::getSettingsTables());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/upgrade/v3_4_0/PreflightCheckMigration.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 PreflightCheckMigration
|
||||
*
|
||||
* @brief Check for common problems early in the upgrade process.
|
||||
*/
|
||||
|
||||
namespace APP\migration\upgrade\v3_4_0;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Throwable;
|
||||
|
||||
class PreflightCheckMigration extends \PKP\migration\upgrade\v3_4_0\PreflightCheckMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
parent::up();
|
||||
try {
|
||||
$this->checkDuplicateDoiRegistrationAgencies();
|
||||
} catch (Throwable $e) {
|
||||
if ($fallbackVersion = $this->setFallbackVersion()) {
|
||||
$this->_installer->log("A pre-flight check failed. The software was successfully upgraded to {$fallbackVersion} but could not be upgraded further (to " . $this->_installer->newVersion->getVersionString() . '). Check and correct the error, then try again.');
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getContextTable(): string
|
||||
{
|
||||
return 'journals';
|
||||
}
|
||||
|
||||
protected function getContextKeyField(): string
|
||||
{
|
||||
return 'journal_id';
|
||||
}
|
||||
|
||||
protected function getContextSettingsTable(): string
|
||||
{
|
||||
return 'journal_settings';
|
||||
}
|
||||
|
||||
protected function buildOrphanedEntityProcessor(): void
|
||||
{
|
||||
parent::buildOrphanedEntityProcessor();
|
||||
|
||||
$this->addTableProcessor('issues', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: doi_id->dois.doi_id(not found in previous version) journal_id->journals.journal_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issues', $this->getContextKeyField(), $this->getContextTable(), $this->getContextKeyField());
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
// Shared processor (there's another handler for this table at pkp-lib)
|
||||
$this->addTableProcessor('publications', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~4 entities: primary_contact_id->authors.author_id doi_id->dois.doi_id(not found in previous version) section_id->sections.section_id submission_id->submissions.submission_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
|
||||
// Attempts to recover the field publications.section_id before discarding the entry
|
||||
$rows = DB::table('publications AS p')
|
||||
->leftJoin('sections AS s', 's.section_id', '=', 'p.section_id')
|
||||
->join('submissions AS sub', 'sub.submission_id', '=', 'p.submission_id')
|
||||
->whereNull('s.section_id')
|
||||
->select('p.submission_id', 'p.publication_id', 'p.section_id')
|
||||
->selectSub(
|
||||
fn (Builder $q) => $q
|
||||
->from('sections AS s')
|
||||
->where('s.is_inactive', '=', 0)
|
||||
->whereColumn('s.journal_id', '=', 'sub.context_id')
|
||||
->selectRaw('MIN(s.section_id)'),
|
||||
'new_section_id'
|
||||
)
|
||||
->get();
|
||||
foreach ($rows as $row) {
|
||||
$this->_installer->log("The publication ID ({$row->publication_id}) for the submission ID {$row->submission_id} is assigned to an invalid section ID \"{$row->section_id}\", its section will be updated to {$row->new_section_id}");
|
||||
$affectedRows += DB::table('publications')->where('publication_id', '=', $row->publication_id)->update(['section_id' => $row->new_section_id]);
|
||||
}
|
||||
$affectedRows += $this->deleteOptionalReference('publications', 'section_id', 'sections', 'section_id');
|
||||
// Remaining cleanups are inherited
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('publication_galleys', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~3 entities: doi_id->dois.doi_id(not found in previous version) publication_id->publications.publication_id submission_file_id->submission_files.submission_file_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('publication_galleys', 'publication_id', 'publications', 'publication_id');
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteOptionalReference('publication_galleys', 'submission_file_id', 'submission_files', 'submission_file_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('issue_galleys', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: file_id->issue_files.file_id issue_id->issues.issue_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issue_galleys', 'issue_id', 'issues', 'issue_id');
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issue_galleys', 'file_id', 'issue_files', 'file_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('sections', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: journal_id->journals.journal_id review_form_id->review_forms.review_form_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('sections', $this->getContextKeyField(), $this->getContextTable(), $this->getContextKeyField());
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->cleanOptionalReference('sections', 'review_form_id', 'review_forms', 'review_form_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('subscription_types', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: journal_id->journals.journal_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('subscription_types', $this->getContextKeyField(), $this->getContextTable(), $this->getContextKeyField());
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('issue_files', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: issue_id->issues.issue_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issue_files', 'issue_id', 'issues', 'issue_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('subscriptions', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~3 entities: journal_id->journals.journal_id type_id->subscription_types.type_id user_id->users.user_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('subscriptions', 'user_id', 'users', 'user_id');
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('subscriptions', 'type_id', 'subscription_types', 'type_id');
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('subscriptions', $this->getContextKeyField(), $this->getContextTable(), $this->getContextKeyField());
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('completed_payments', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: context_id->journals.journal_id user_id->users.user_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('completed_payments', 'context_id', $this->getContextTable(), $this->getContextKeyField());
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteOptionalReference('completed_payments', 'user_id', 'users', 'user_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('custom_issue_orders', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: issue_id->issues.issue_id journal_id->journals.journal_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('custom_issue_orders', $this->getContextKeyField(), $this->getContextTable(), $this->getContextKeyField());
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('custom_issue_orders', 'issue_id', 'issues', 'issue_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('custom_section_orders', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: issue_id->issues.issue_id section_id->sections.section_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('custom_section_orders', 'section_id', 'sections', 'section_id');
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('custom_section_orders', 'issue_id', 'issues', 'issue_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('institutional_subscriptions', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~2 entities: institution_id->institutions.institution_id(not found in previous version) subscription_id->subscriptions.subscription_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('institutional_subscriptions', 'subscription_id', 'subscriptions', 'subscription_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('issue_galley_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: galley_id->issue_galleys.galley_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issue_galley_settings', 'galley_id', 'issue_galleys', 'galley_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('issue_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: issue_id->issues.issue_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('issue_settings', 'issue_id', 'issues', 'issue_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('publication_galley_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: galley_id->publication_galleys.galley_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('publication_galley_settings', 'galley_id', 'publication_galleys', 'galley_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('section_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: section_id->sections.section_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('section_settings', 'section_id', 'sections', 'section_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
$this->addTableProcessor('subscription_type_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
// Depends directly on ~1 entities: type_id->subscription_types.type_id
|
||||
// Custom field (not found in at least one of the softwares)
|
||||
$affectedRows += $this->deleteRequiredReference('subscription_type_settings', 'type_id', 'subscription_types', 'type_id');
|
||||
return $affectedRows;
|
||||
});
|
||||
|
||||
// Support for the issueId setting
|
||||
$this->addTableProcessor('publication_settings', function (): int {
|
||||
$affectedRows = 0;
|
||||
$rows = DB::table('publications AS p')
|
||||
->join('publication_settings AS ps', 'ps.publication_id', '=', 'p.publication_id')
|
||||
->leftJoin('issues AS i', DB::raw('CAST(i.issue_id AS CHAR(20))'), '=', 'ps.setting_value')
|
||||
->where('ps.setting_name', 'issueId')
|
||||
->whereNull('i.issue_id')
|
||||
->get(['p.submission_id', 'p.publication_id', 'ps.setting_value']);
|
||||
foreach ($rows as $row) {
|
||||
$this->_installer->log("The publication ID ({$row->publication_id}) for the submission ID {$row->submission_id} is assigned to an invalid issue ID \"{$row->setting_value}\", its value will be updated to NULL");
|
||||
$affectedRows += DB::table('publication_settings')
|
||||
->where('publication_id', '=', $row->publication_id)
|
||||
->where('setting_name', 'issueId')
|
||||
->where('setting_value', $row->setting_value)
|
||||
->delete();
|
||||
}
|
||||
return $affectedRows;
|
||||
});
|
||||
}
|
||||
|
||||
protected function getEntityRelationships(): array
|
||||
{
|
||||
return [
|
||||
$this->getContextTable() => ['submissions', 'issues', 'user_groups', 'sections', 'categories', 'subscription_types', 'navigation_menu_items', 'genres', 'filters', 'announcement_types', 'subscriptions', 'notifications', 'navigation_menus', 'library_files', 'email_templates', 'user_group_stage', 'subeditor_submission_group', 'plugin_settings', 'notification_subscription_settings', $this->getContextSettingsTable(), 'custom_issue_orders', 'completed_payments'],
|
||||
'users' => ['submission_files', 'review_assignments', 'subscriptions', 'notifications', 'event_log', 'email_log', 'user_user_groups', 'user_settings', 'user_interests', 'temporary_files', 'submission_comments', 'subeditor_submission_group', 'stage_assignments', 'sessions', 'query_participants', 'notification_subscription_settings', 'notes', 'email_log_users', 'edit_decisions', 'completed_payments', 'access_keys'],
|
||||
'submissions' => ['submission_files', 'publications', 'review_rounds', 'review_assignments', 'submission_search_objects', 'library_files', 'submission_settings', 'submission_comments', 'stage_assignments', 'review_round_files', 'edit_decisions'],
|
||||
'submission_files' => ['submission_files', 'publication_galleys', 'submission_file_settings', 'submission_file_revisions', 'review_round_files', 'review_files'],
|
||||
// publication_settings dependency added manually
|
||||
'issues' => [$this->getContextTable(), 'issue_galleys', 'issue_files', 'issue_settings', 'custom_section_orders', 'custom_issue_orders', 'publication_settings'],
|
||||
'user_groups' => ['authors', 'user_user_groups', 'user_group_stage', 'user_group_settings', 'subeditor_submission_group', 'stage_assignments'],
|
||||
'publications' => ['submissions', 'publication_galleys', 'authors', 'citations', 'publication_settings', 'publication_categories'],
|
||||
'publication_galleys' => ['publication_galley_settings'],
|
||||
'review_forms' => ['sections', 'review_form_elements', 'review_assignments', 'review_form_settings'],
|
||||
'categories' => ['categories', 'publication_categories', 'category_settings'],
|
||||
'issue_galleys' => ['issue_galley_settings'],
|
||||
'sections' => ['publications', 'section_settings', 'custom_section_orders'],
|
||||
'review_rounds' => ['review_assignments', 'review_round_files', 'edit_decisions'],
|
||||
'navigation_menu_item_assignments' => ['navigation_menu_item_assignments', 'navigation_menu_item_assignment_settings'],
|
||||
'authors' => ['publications', 'author_settings'],
|
||||
'controlled_vocab_entries' => ['user_interests', 'controlled_vocab_entry_settings'],
|
||||
'data_object_tombstones' => ['data_object_tombstone_settings', 'data_object_tombstone_oai_set_objects'],
|
||||
'files' => ['submission_files', 'submission_file_revisions'],
|
||||
'filters' => ['filters', 'filter_settings'],
|
||||
'genres' => ['submission_files', 'genre_settings'],
|
||||
'announcement_types' => ['announcements', 'announcement_type_settings'],
|
||||
'navigation_menu_items' => ['navigation_menu_item_assignments', 'navigation_menu_item_settings'],
|
||||
'review_assignments' => ['review_form_responses', 'review_files'],
|
||||
'review_form_elements' => ['review_form_responses', 'review_form_element_settings'],
|
||||
'subscription_types' => ['subscriptions', 'subscription_type_settings'],
|
||||
'announcements' => ['announcement_settings'],
|
||||
'queries' => ['query_participants'],
|
||||
'navigation_menus' => ['navigation_menu_item_assignments'],
|
||||
'notifications' => ['notification_settings'],
|
||||
'filter_groups' => ['filters'],
|
||||
'event_log' => ['event_log_settings'],
|
||||
'email_templates' => ['email_templates_settings'],
|
||||
'static_pages' => ['static_page_settings'],
|
||||
'email_log' => ['email_log_users'],
|
||||
'submission_search_keyword_list' => ['submission_search_object_keywords'],
|
||||
'submission_search_objects' => ['submission_search_object_keywords'],
|
||||
'controlled_vocabs' => ['controlled_vocab_entries'],
|
||||
'library_files' => ['library_file_settings'],
|
||||
'subscriptions' => ['institutional_subscriptions'],
|
||||
'citations' => ['citation_settings'],
|
||||
'issue_files' => ['issue_galleys']
|
||||
];
|
||||
}
|
||||
|
||||
protected function dropForeignKeys(): void
|
||||
{
|
||||
parent::dropForeignKeys();
|
||||
if (DB::getDoctrineSchemaManager()->introspectTable('publication_galleys')->hasForeignKey('publication_galleys_submission_file_id_foreign')) {
|
||||
Schema::table('publication_galleys', fn (Blueprint $table) => $table->dropForeign('publication_galleys_submission_file_id_foreign'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if DOIs have been marked registered with more than one registration agency.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function checkDuplicateDoiRegistrationAgencies(): void
|
||||
{
|
||||
$agencies = ['crossref::status', 'datacite::status', 'medra::status'];
|
||||
|
||||
$submissionIds = DB::table('submission_settings')
|
||||
->whereIn('setting_name', $agencies)
|
||||
->groupBy('submission_id')
|
||||
->havingRaw('COUNT(submission_id) > 1')
|
||||
->select(['submission_id'])
|
||||
->get();
|
||||
|
||||
$galleyIds = DB::table('publication_galley_settings')
|
||||
->whereIn('setting_name', $agencies)
|
||||
->groupBy('galley_id')
|
||||
->havingRaw('COUNT(galley_id) > 1')
|
||||
->select(['galley_id'])
|
||||
->get();
|
||||
|
||||
$issueIds = DB::table('issue_settings')
|
||||
->whereIn('setting_name', $agencies)
|
||||
->groupBy('issue_id')
|
||||
->havingRaw('COUNT(issue_id) > 1')
|
||||
->select(['issue_id'])
|
||||
->get();
|
||||
|
||||
if ($submissionIds->count() > 0 || $galleyIds->count() > 0 || $issueIds->count() > 0) {
|
||||
throw new Exception('Some DOIs have been registered with multiple registration agencies. Resolve duplicates before continuing by running `php tools/resolveAgencyDuplicates.php`.');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user