first commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/install/JournalsMigration.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 JournalsMigration
|
||||
*
|
||||
* @brief Describe database table structures.
|
||||
*/
|
||||
|
||||
namespace APP\migration\install;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class JournalsMigration extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Journals and basic journal settings.
|
||||
Schema::create('journals', function (Blueprint $table) {
|
||||
$table->comment('A list of all journals in the installation of OJS.');
|
||||
$table->bigInteger('journal_id')->autoIncrement();
|
||||
$table->string('path', 32);
|
||||
$table->float('seq', 8, 2)->default(0)->comment('Used to order lists of journals');
|
||||
$table->string('primary_locale', 14);
|
||||
$table->smallInteger('enabled')->default(1)->comment('Controls whether or not the journal is considered "live" and will appear on the website. (Note that disabled journals may still be accessible, but only if the user knows the URL.)');
|
||||
$table->unique(['path'], 'journals_path');
|
||||
$table->bigInteger('current_issue_id')->nullable()->default(null);
|
||||
});
|
||||
|
||||
// Journal settings.
|
||||
Schema::create('journal_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about journals, including localized properties like policies.');
|
||||
$table->bigIncrements('journal_setting_id');
|
||||
|
||||
$table->bigInteger('journal_id');
|
||||
$table->foreign('journal_id', 'journal_settings_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'journal_settings_journal_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
|
||||
$table->unique(['journal_id', 'locale', 'setting_name'], 'journal_settings_unique');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::drop('journal_settings');
|
||||
Schema::drop('journals');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/install/MetricsMigration.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 MetricsMigration
|
||||
*
|
||||
* @brief Describe database table structures.
|
||||
*/
|
||||
|
||||
namespace APP\migration\install;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema as Schema;
|
||||
|
||||
class MetricsMigration extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('metrics_context', function (Blueprint $table) {
|
||||
$table->comment('Daily statistics for views of the homepage.');
|
||||
$table->bigIncrements('metrics_context_id');
|
||||
|
||||
$table->string('load_id', 50);
|
||||
$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->comment('Daily statistics for views and downloads of published submissions and galleys.');
|
||||
$table->bigIncrements('metrics_submission_id');
|
||||
$table->string('load_id', 50);
|
||||
$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->comment('Daily statistics for views and downloads of published issues.');
|
||||
$table->bigIncrements('metrics_issue_id');
|
||||
|
||||
$table->string('load_id', 50);
|
||||
$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->comment('Daily statistics matching the COUNTER R5 protocol for views and downloads of published submissions and galleys.');
|
||||
$table->bigIncrements('metrics_counter_submission_daily_id');
|
||||
|
||||
$table->string('load_id', 50);
|
||||
$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->comment('Monthly statistics matching the COUNTER R5 protocol for views and downloads of published submissions and galleys.');
|
||||
$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->comment('Daily statistics matching the COUNTER R5 protocol for views and downloads from institutions.');
|
||||
$table->bigIncrements('metrics_counter_submission_institution_daily_id');
|
||||
$table->string('load_id', 50);
|
||||
$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->comment('Monthly statistics matching the COUNTER R5 protocol for views and downloads from institutions.');
|
||||
$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->comment('Daily statistics by country, region and city for views and downloads of published submissions and galleys.');
|
||||
$table->bigIncrements('metrics_submission_geo_daily_id');
|
||||
|
||||
$table->string('load_id', 50);
|
||||
$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');
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql':
|
||||
// See "Create a database table" here: https://db-ip.com/db/format/ip-to-city-lite/csv.html
|
||||
// where city is defined as varchar(80)
|
||||
$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::create('metrics_submission_geo_monthly', function (Blueprint $table) {
|
||||
$table->comment('Monthly statistics by country, region and city for views and downloads of published submissions and galleys.');
|
||||
$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');
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql':
|
||||
// See "Create a database table" here: https://db-ip.com/db/format/ip-to-city-lite/csv.html
|
||||
// where city is defined as varchar(80)
|
||||
$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;
|
||||
}
|
||||
});
|
||||
|
||||
// Usage stats total item temporary records
|
||||
Schema::create('usage_stats_total_temporary_records', function (Blueprint $table) {
|
||||
$table->comment('Temporary stats totals based on visitor log records. Data in this table is provisional. See the metrics_* tables for compiled stats.');
|
||||
$table->bigIncrements('usage_stats_temp_total_id');
|
||||
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 64);
|
||||
$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', 50);
|
||||
|
||||
$table->index(['load_id', 'context_id', 'ip'], 'ust_load_id_context_id_ip');
|
||||
});
|
||||
|
||||
// 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->comment('Temporary stats on unique downloads based on visitor log records. Data in this table is provisional. See the metrics_* tables for compiled stats.');
|
||||
$table->bigIncrements('usage_stats_temp_unique_item_id');
|
||||
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 64);
|
||||
$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', 50);
|
||||
|
||||
$table->index(['load_id', 'context_id', 'ip'], 'usii_load_id_context_id_ip');
|
||||
});
|
||||
|
||||
// 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->comment('Temporary stats on unique views based on visitor log records. Data in this table is provisional. See the metrics_* tables for compiled stats.');
|
||||
$table->bigIncrements('usage_stats_temp_item_id');
|
||||
$table->dateTime('date', $precision = 0);
|
||||
$table->string('ip', 64);
|
||||
$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', 50);
|
||||
|
||||
$table->index(['load_id', 'context_id', 'ip'], 'usir_load_id_context_id_ip');
|
||||
});
|
||||
|
||||
// Usage stats institution temporary records
|
||||
// This table is needed because of data normalization
|
||||
Schema::create('usage_stats_institution_temporary_records', function (Blueprint $table) {
|
||||
$table->comment('Temporary stats for views and downloads from institutions based on visitor log records. Data in this table is provisional. See the metrics_* tables for compiled stats.');
|
||||
$table->bigIncrements('usage_stats_temp_institution_id');
|
||||
|
||||
$table->string('load_id', 50);
|
||||
$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.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::drop('metrics_context');
|
||||
Schema::drop('metrics_submission');
|
||||
Schema::drop('metrics_issue');
|
||||
Schema::drop('metrics_counter_submission_daily');
|
||||
Schema::drop('metrics_counter_submission_monthly');
|
||||
Schema::drop('metrics_counter_submission_institution_daily');
|
||||
Schema::drop('metrics_counter_submission_institution_monthly');
|
||||
Schema::drop('metrics_submission_geo_daily');
|
||||
Schema::drop('metrics_submission_geo_monthly');
|
||||
Schema::drop('usage_stats_total_temporary_records');
|
||||
Schema::drop('usage_stats_unique_item_investigations_temporary_records');
|
||||
Schema::drop('usage_stats_unique_item_requests_temporary_records');
|
||||
Schema::drop('usage_stats_institution_temporary_records');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,455 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/migration/install/OJSMigration.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 OJSMigration
|
||||
*
|
||||
* @brief Describe database table structures.
|
||||
*/
|
||||
|
||||
namespace APP\migration\install;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class OJSMigration extends \PKP\migration\Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Journal sections.
|
||||
Schema::create('sections', function (Blueprint $table) {
|
||||
$table->comment('A list of all sections into which submissions can be organized, forming the table of contents.');
|
||||
$table->bigInteger('section_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('journal_id');
|
||||
$table->foreign('journal_id', 'sections_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'sections_journal_id');
|
||||
|
||||
$table->bigInteger('review_form_id')->nullable();
|
||||
$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->float('seq', 8, 2)->default(0);
|
||||
$table->smallInteger('editor_restricted')->default(0);
|
||||
$table->smallInteger('meta_indexed')->default(0);
|
||||
$table->smallInteger('meta_reviewed')->default(1);
|
||||
$table->smallInteger('abstracts_not_required')->default(0);
|
||||
$table->smallInteger('hide_title')->default(0);
|
||||
$table->smallInteger('hide_author')->default(0);
|
||||
$table->smallInteger('is_inactive')->default(0);
|
||||
$table->bigInteger('abstract_word_count')->nullable();
|
||||
});
|
||||
|
||||
// Section-specific settings
|
||||
Schema::create('section_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about sections, including localized properties like section titles.');
|
||||
$table->bigIncrements('section_setting_id');
|
||||
|
||||
$table->bigInteger('section_id');
|
||||
$table->foreign('section_id', 'section_settings_section_id')->references('section_id')->on('sections')->onDelete('cascade');
|
||||
$table->index(['section_id'], 'section_settings_section_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
|
||||
$table->unique(['section_id', 'locale', 'setting_name'], 'section_settings_unique');
|
||||
});
|
||||
|
||||
// Journal issues.
|
||||
Schema::create('issues', function (Blueprint $table) {
|
||||
$table->comment('A list of all journal issues, with identifying information like year, number, volume, etc.');
|
||||
$table->bigInteger('issue_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('journal_id');
|
||||
$table->foreign('journal_id', 'issues_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'issues_journal_id');
|
||||
|
||||
$table->smallInteger('volume')->nullable();
|
||||
$table->string('number', 40)->nullable();
|
||||
$table->smallInteger('year')->nullable();
|
||||
$table->smallInteger('published')->default(0);
|
||||
$table->datetime('date_published')->nullable();
|
||||
$table->datetime('date_notified')->nullable();
|
||||
$table->datetime('last_modified')->nullable();
|
||||
$table->smallInteger('access_status')->default(1);
|
||||
$table->datetime('open_access_date')->nullable();
|
||||
$table->smallInteger('show_volume')->default(0);
|
||||
$table->smallInteger('show_number')->default(0);
|
||||
$table->smallInteger('show_year')->default(0);
|
||||
$table->smallInteger('show_title')->default(0);
|
||||
$table->string('style_file_name', 90)->nullable();
|
||||
$table->string('original_style_file_name', 255)->nullable();
|
||||
$table->string('url_path', 64)->nullable();
|
||||
|
||||
$table->bigInteger('doi_id')->nullable();
|
||||
$table->foreign('doi_id')->references('doi_id')->on('dois')->nullOnDelete();
|
||||
$table->index(['doi_id'], 'issues_doi_id');
|
||||
|
||||
$table->index(['url_path'], 'issues_url_path');
|
||||
});
|
||||
|
||||
// Locale-specific issue data
|
||||
Schema::create('issue_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about issues, including localized properties such as issue titles.');
|
||||
$table->bigIncrements('issue_setting_id');
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$table->foreign('issue_id', 'issue_settings_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'issue_settings_issue_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
|
||||
$table->unique(['issue_id', 'locale', 'setting_name'], 'issue_settings_unique');
|
||||
});
|
||||
// Add partial index (DBMS-specific)
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql': DB::unprepared('CREATE INDEX issue_settings_name_value ON issue_settings (setting_name(50), setting_value(150))');
|
||||
break;
|
||||
case 'pgsql': DB::unprepared("CREATE INDEX issue_settings_name_value ON issue_settings (setting_name, setting_value) WHERE setting_name IN ('medra::registeredDoi', 'datacite::registeredDoi')");
|
||||
break;
|
||||
}
|
||||
|
||||
Schema::create('issue_files', function (Blueprint $table) {
|
||||
$table->comment('Relationships between issues and issue files, such as cover images.');
|
||||
$table->bigInteger('file_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$table->foreign('issue_id', 'issue_files_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'issue_files_issue_id');
|
||||
|
||||
$table->string('file_name', 90);
|
||||
$table->string('file_type', 255);
|
||||
$table->bigInteger('file_size');
|
||||
$table->bigInteger('content_type');
|
||||
$table->string('original_file_name', 127)->nullable();
|
||||
$table->datetime('date_uploaded');
|
||||
$table->datetime('date_modified');
|
||||
});
|
||||
|
||||
// Issue galleys.
|
||||
Schema::create('issue_galleys', function (Blueprint $table) {
|
||||
$table->comment('Issue galleys are representations of the entire issue in a single file, such as a complete issue PDF.');
|
||||
$table->bigInteger('galley_id')->autoIncrement();
|
||||
|
||||
$table->string('locale', 14)->nullable();
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$table->foreign('issue_id', 'issue_galleys_issue_id')->references('issue_id')->on('issues')->onDelete('cascade');
|
||||
$table->index(['issue_id'], 'issue_galleys_issue_id');
|
||||
|
||||
$table->bigInteger('file_id');
|
||||
$table->foreign('file_id', 'issue_galleys_file_id')->references('file_id')->on('issue_files')->onDelete('cascade');
|
||||
$table->index(['file_id'], 'issue_galleys_file_id');
|
||||
|
||||
$table->string('label', 255)->nullable();
|
||||
$table->float('seq', 8, 2)->default(0);
|
||||
$table->string('url_path', 64)->nullable();
|
||||
|
||||
$table->index(['url_path'], 'issue_galleys_url_path');
|
||||
});
|
||||
|
||||
// Issue galley metadata.
|
||||
Schema::create('issue_galley_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about issue galleys, including localized content such as labels.');
|
||||
$table->bigIncrements('issue_galley_setting_id');
|
||||
|
||||
$table->bigInteger('galley_id');
|
||||
$table->foreign('galley_id', 'issue_galleys_settings_galley_id')->references('galley_id')->on('issue_galleys')->onDelete('cascade');
|
||||
$table->index(['galley_id'], 'issue_galley_settings_galley_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
$table->string('setting_type', 6)->comment('(bool|int|float|string|object)');
|
||||
|
||||
$table->unique(['galley_id', 'locale', 'setting_name'], 'issue_galley_settings_unique');
|
||||
});
|
||||
|
||||
Schema::create('custom_issue_orders', function (Blueprint $table) {
|
||||
$table->comment('Ordering information for the issue list, when custom issue ordering is specified.');
|
||||
$table->bigIncrements('custom_issue_order_id');
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$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->bigInteger('journal_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');
|
||||
|
||||
$table->float('seq', 8, 2)->default(0);
|
||||
|
||||
$table->unique(['issue_id'], 'custom_issue_orders_unique');
|
||||
});
|
||||
|
||||
Schema::create('custom_section_orders', function (Blueprint $table) {
|
||||
$table->comment('Ordering information for sections within issues, when issue-specific section ordering is specified.');
|
||||
$table->bigIncrements('custom_section_order_id');
|
||||
|
||||
$table->bigInteger('issue_id');
|
||||
$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->bigInteger('section_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');
|
||||
|
||||
$table->float('seq', 8, 2)->default(0);
|
||||
|
||||
$table->unique(['issue_id', 'section_id'], 'custom_section_orders_unique');
|
||||
});
|
||||
|
||||
// Publications
|
||||
Schema::create('publications', function (Blueprint $table) {
|
||||
$table->comment('Each publication is one version of a submission.');
|
||||
$table->bigInteger('publication_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('access_status')->default(0)->nullable();
|
||||
$table->date('date_published')->nullable();
|
||||
$table->datetime('last_modified')->nullable();
|
||||
|
||||
$table->bigInteger('primary_contact_id')->nullable();
|
||||
$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');
|
||||
|
||||
$table->bigInteger('section_id')->nullable();
|
||||
$table->foreign('section_id', 'publications_section_id')->references('section_id')->on('sections')->onDelete('set null');
|
||||
$table->index(['section_id'], 'publications_section_id');
|
||||
|
||||
$table->float('seq', 8, 2)->default(0);
|
||||
|
||||
$table->bigInteger('submission_id');
|
||||
$table->foreign('submission_id', 'publications_submission_id')->references('submission_id')->on('submissions')->onDelete('cascade');
|
||||
$table->index(['submission_id'], 'publications_submission_id');
|
||||
|
||||
$table->smallInteger('status')->default(1); // PKPSubmission::STATUS_QUEUED
|
||||
$table->string('url_path', 64)->nullable();
|
||||
$table->bigInteger('version')->nullable();
|
||||
|
||||
$table->bigInteger('doi_id')->nullable();
|
||||
$table->foreign('doi_id')->references('doi_id')->on('dois')->nullOnDelete();
|
||||
$table->index(['doi_id'], 'publications_doi_id');
|
||||
|
||||
$table->index(['url_path'], 'publications_url_path');
|
||||
});
|
||||
// The following foreign key relationships are for tables defined in SubmissionsMigration
|
||||
// but they depend on publications to exist so are created here.
|
||||
Schema::table('submissions', function (Blueprint $table) {
|
||||
$table->foreign('current_publication_id', 'submissions_publication_id')->references('publication_id')->on('publications')->onDelete('set null');
|
||||
$table->index(['current_publication_id'], 'submissions_publication_id');
|
||||
});
|
||||
Schema::table('publication_settings', function (Blueprint $table) {
|
||||
$table->foreign('publication_id', 'publication_settings_publication_id')->references('publication_id')->on('publications')->onDelete('cascade');
|
||||
$table->index(['publication_id'], 'publication_settings_publication_id');
|
||||
});
|
||||
Schema::table('authors', function (Blueprint $table) {
|
||||
$table->foreign('publication_id')->references('publication_id')->on('publications')->onDelete('cascade');
|
||||
$table->index(['publication_id'], 'authors_publication_id');
|
||||
});
|
||||
// Publication galleys
|
||||
Schema::create('publication_galleys', function (Blueprint $table) {
|
||||
$table->comment('Publication galleys are representations of a publication in a specific format, e.g. a PDF.');
|
||||
$table->bigInteger('galley_id')->autoIncrement();
|
||||
$table->string('locale', 14)->nullable();
|
||||
|
||||
$table->bigInteger('publication_id');
|
||||
$table->foreign('publication_id', 'publication_galleys_publication_id')->references('publication_id')->on('publications')->onDelete('cascade');
|
||||
$table->index(['publication_id'], 'publication_galleys_publication_id');
|
||||
|
||||
$table->string('label', 255)->nullable();
|
||||
|
||||
$table->bigInteger('submission_file_id')->unsigned()->nullable();
|
||||
$table->foreign('submission_file_id')->references('submission_file_id')->on('submission_files');
|
||||
$table->index(['submission_file_id'], 'publication_galleys_submission_file_id');
|
||||
|
||||
$table->float('seq', 8, 2)->default(0);
|
||||
$table->string('remote_url', 2047)->nullable();
|
||||
$table->smallInteger('is_approved')->default(0);
|
||||
$table->string('url_path', 64)->nullable();
|
||||
|
||||
$table->bigInteger('doi_id')->nullable();
|
||||
$table->foreign('doi_id')->references('doi_id')->on('dois')->nullOnDelete();
|
||||
$table->index(['doi_id'], 'publication_galleys_doi_id');
|
||||
|
||||
$table->index(['url_path'], 'publication_galleys_url_path');
|
||||
});
|
||||
|
||||
// Galley metadata.
|
||||
Schema::create('publication_galley_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about publication galleys, including localized content such as labels.');
|
||||
$table->bigIncrements('publication_galley_setting_id');
|
||||
|
||||
$table->bigInteger('galley_id');
|
||||
$table->foreign('galley_id', 'publication_galley_settings_galley_id')->references('galley_id')->on('publication_galleys')->onDelete('cascade');
|
||||
$table->index(['galley_id'], 'publication_galley_settings_galley_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
|
||||
$table->unique(['galley_id', 'locale', 'setting_name'], 'publication_galley_settings_unique');
|
||||
});
|
||||
// Add partial index (DBMS-specific)
|
||||
switch (DB::getDriverName()) {
|
||||
case 'mysql': DB::unprepared('CREATE INDEX publication_galley_settings_name_value ON publication_galley_settings (setting_name(50), setting_value(150))');
|
||||
break;
|
||||
case 'pgsql': DB::unprepared('CREATE INDEX publication_galley_settings_name_value ON publication_galley_settings (setting_name, setting_value)');
|
||||
break;
|
||||
}
|
||||
|
||||
// Subscription types.
|
||||
Schema::create('subscription_types', function (Blueprint $table) {
|
||||
$table->comment('Subscription types represent the kinds of subscriptions that a user or institution may have, such as an annual subscription or a discounted subscription.');
|
||||
$table->bigInteger('type_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('journal_id');
|
||||
$table->foreign('journal_id', 'subscription_types_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'subscription_types_journal_id');
|
||||
|
||||
$table->float('cost', 8, 2);
|
||||
$table->string('currency_code_alpha', 3);
|
||||
$table->smallInteger('duration')->nullable();
|
||||
$table->smallInteger('format');
|
||||
$table->smallInteger('institutional')->default(0);
|
||||
$table->smallInteger('membership')->default(0);
|
||||
$table->smallInteger('disable_public_display');
|
||||
$table->float('seq', 8, 2);
|
||||
});
|
||||
|
||||
// Locale-specific subscription type data
|
||||
Schema::create('subscription_type_settings', function (Blueprint $table) {
|
||||
$table->comment('More data about subscription types, including localized properties such as names.');
|
||||
$table->bigIncrements('subscription_type_setting_id');
|
||||
|
||||
$table->bigInteger('type_id');
|
||||
$table->foreign('type_id', 'subscription_type_settings_type_id')->references('type_id')->on('subscription_types')->onDelete('cascade');
|
||||
$table->index(['type_id'], 'subscription_type_settings_type_id');
|
||||
|
||||
$table->string('locale', 14)->default('');
|
||||
$table->string('setting_name', 255);
|
||||
$table->mediumText('setting_value')->nullable();
|
||||
$table->string('setting_type', 6);
|
||||
|
||||
$table->unique(['type_id', 'locale', 'setting_name'], 'subscription_type_settings_unique');
|
||||
});
|
||||
|
||||
// Journal subscriptions.
|
||||
Schema::create('subscriptions', function (Blueprint $table) {
|
||||
$table->comment('A list of subscriptions, both institutional and individual, for journals that use subscription-based publishing.');
|
||||
$table->bigInteger('subscription_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('journal_id');
|
||||
$table->foreign('journal_id', 'subscriptions_journal_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['journal_id'], 'subscriptions_journal_id');
|
||||
|
||||
$table->bigInteger('user_id');
|
||||
$table->foreign('user_id', 'subscriptions_user_id')->references('user_id')->on('users')->onDelete('cascade');
|
||||
$table->index(['user_id'], 'subscriptions_user_id');
|
||||
|
||||
$table->bigInteger('type_id');
|
||||
$table->foreign('type_id', 'subscriptions_type_id')->references('type_id')->on('subscription_types')->onDelete('cascade');
|
||||
$table->index(['type_id'], 'subscriptions_type_id');
|
||||
|
||||
$table->date('date_start')->nullable();
|
||||
$table->datetime('date_end')->nullable();
|
||||
$table->smallInteger('status')->default(1);
|
||||
$table->string('membership', 40)->nullable();
|
||||
$table->string('reference_number', 40)->nullable();
|
||||
$table->text('notes')->nullable();
|
||||
});
|
||||
|
||||
// Journal institutional subscriptions.
|
||||
Schema::create('institutional_subscriptions', function (Blueprint $table) {
|
||||
$table->comment('A list of institutional subscriptions, linking a subscription with an institution.');
|
||||
$table->bigInteger('institutional_subscription_id')->autoIncrement();
|
||||
|
||||
$table->bigInteger('subscription_id');
|
||||
$table->foreign('subscription_id', 'institutional_subscriptions_subscription_id')->references('subscription_id')->on('subscriptions')->onDelete('cascade');
|
||||
$table->index(['subscription_id'], 'institutional_subscriptions_subscription_id');
|
||||
|
||||
$table->bigInteger('institution_id');
|
||||
$table->foreign('institution_id')->references('institution_id')->on('institutions')->onDelete('cascade');
|
||||
$table->index(['institution_id'], 'institutional_subscriptions_institution_id');
|
||||
|
||||
$table->string('mailing_address', 255)->nullable();
|
||||
$table->string('domain', 255)->nullable();
|
||||
|
||||
$table->index(['domain'], 'institutional_subscriptions_domain');
|
||||
});
|
||||
|
||||
// Logs queued (unfulfilled) payments.
|
||||
Schema::create('queued_payments', function (Blueprint $table) {
|
||||
$table->comment('Unfulfilled (queued) payments, i.e. payments that have not yet been completed via an online payment system.');
|
||||
$table->bigInteger('queued_payment_id')->autoIncrement();
|
||||
$table->datetime('date_created');
|
||||
$table->datetime('date_modified');
|
||||
$table->date('expiry_date')->nullable();
|
||||
$table->text('payment_data')->nullable();
|
||||
});
|
||||
|
||||
// Logs completed (fulfilled) payments.
|
||||
Schema::create('completed_payments', function (Blueprint $table) {
|
||||
$table->comment('A list of completed (fulfilled) payments relating to a payment type such as a subscription payment.');
|
||||
$table->bigInteger('completed_payment_id')->autoIncrement();
|
||||
$table->datetime('timestamp');
|
||||
$table->bigInteger('payment_type');
|
||||
|
||||
$table->bigInteger('context_id');
|
||||
$table->foreign('context_id', 'completed_payments_context_id')->references('journal_id')->on('journals')->onDelete('cascade');
|
||||
$table->index(['context_id'], 'completed_payments_context_id');
|
||||
|
||||
$table->bigInteger('user_id')->nullable();
|
||||
$table->foreign('user_id', 'completed_payments_user_id')->references('user_id')->on('users')->onDelete('set null');
|
||||
$table->index(['user_id'], 'completed_payments_user_id');
|
||||
|
||||
$table->bigInteger('assoc_id')->nullable();
|
||||
$table->float('amount', 8, 2);
|
||||
$table->string('currency_code_alpha', 3)->nullable();
|
||||
$table->string('payment_method_plugin_name', 80)->nullable();
|
||||
});
|
||||
|
||||
// Add additional foreign key constraints once all tables have been created
|
||||
Schema::table('journals', function (Blueprint $table) {
|
||||
$table->foreign('current_issue_id')->references('issue_id')->on('issues')->onDelete('set null');
|
||||
$table->index(['current_issue_id'], 'journals_issue_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::drop('completed_payments');
|
||||
Schema::drop('queued_payments');
|
||||
Schema::drop('institutional_subscription_ip');
|
||||
Schema::drop('institutional_subscriptions');
|
||||
Schema::drop('subscriptions');
|
||||
Schema::drop('subscription_type_settings');
|
||||
Schema::drop('subscription_types');
|
||||
Schema::drop('publication_galley_settings');
|
||||
Schema::drop('publication_galleys');
|
||||
Schema::drop('publications');
|
||||
Schema::drop('custom_section_orders');
|
||||
Schema::drop('custom_issue_orders');
|
||||
Schema::drop('issue_files');
|
||||
Schema::drop('issue_galley_settings');
|
||||
Schema::drop('issue_galleys');
|
||||
Schema::drop('issue_settings');
|
||||
Schema::drop('issues');
|
||||
Schema::drop('section_settings');
|
||||
Schema::drop('sections');
|
||||
}
|
||||
}
|
||||
@@ -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