Skip to content

Commit

Permalink
pkp#1660 migration to import existing recommendations
Browse files Browse the repository at this point in the history
  • Loading branch information
touhidurabir committed Nov 11, 2024
1 parent 3ac9bd9 commit 54b8886
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function toArray(Request $request)
return [
'id' => $this->id,
'contextId' => $this->contextId,
'value' => $this->value,
'status' => $this->status,
'removable' => $this->removable,
'title' => $this->title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ public function __construct($action, $locales)
'options' => [
[
'label' => __('manager.reviewerRecommendations.activateUponSaving.label'),
'value' => true,
'value' => 1,
],
[
'label' => __('manager.reviewerRecommendations.activateUponSaving.deactivate'),
'value' => false,
'value' => 0,
],
],
'value' => true,
'value' => 1,
'size' => 'normal',
]));
}
Expand Down
39 changes: 8 additions & 31 deletions classes/migration/install/ReviewerRecommendationsMigration.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use PKP\facades\Locale;
use PKP\submission\reviewer\recommendation\ReviewerRecommendation;
use stdClass;
use Throwable;

abstract class ReviewerRecommendationsMigration extends \PKP\migration\Migration
{
abstract public function contextTable(): string;

abstract public function settingTable(): string;

abstract public function contextPrimaryKey(): string;

/**
Expand All @@ -45,6 +50,9 @@ public function up(): void

$table->index(['context_id'], 'reviewer_recommendations_context_id');

$table->unsignedInteger('value');
$table->unique(['context_id', 'value'], 'reviewer_recommendations_context_unique');

$table
->boolean('status')
->default(true)
Expand Down Expand Up @@ -81,7 +89,6 @@ public function up(): void
$table->unique(['recommendation_id', 'locale', 'setting_name'], 'reviewer_recommendation_settings_unique');
$table->index(['setting_name', 'locale'], 'reviewer_recommendation_settings_locale_setting_name_index');
});

}

/**
Expand All @@ -94,34 +101,4 @@ public function down(): void
Schema::drop('reviewer_recommendation_settings');
Schema::enableForeignKeyConstraints();
}

// TODO : need a way to store existing non removable recommendations
protected function seedNonRemovableRecommendations(): void
{
$recommendations = $this->systemDefineNonRemovableRecommendations();

if (empty($recommendations)) {
return;
}

try {

DB::beginTransaction();

// Store data

DB::commit();

} catch (Throwable $exception) {

DB::rollBack();

throw $exception;
}
}

protected function systemDefineNonRemovableRecommendations(): array
{
return [];
}
}
154 changes: 154 additions & 0 deletions classes/migration/upgrade/v3_6_0/I1660_ReviewerRecommendations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

/**
* @file classes/migration/upgrade/v3_6_0/I1660_ReviewerRecommendations.php
*
* Copyright (c) 2014-2024 Simon Fraser University
* Copyright (c) 2000-2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class I1660_ReviewerRecommendations
*
* @brief
*/

namespace PKP\migration\upgrade\v3_6_0;

use Illuminate\Support\Facades\DB;
use PKP\install\Installer;

use Throwable;

use stdClass;

use PKP\submission\reviewer\recommendation\ReviewerRecommendation;
use PKP\facades\Locale;
use APP\migration\install\ReviewerRecommendationsMigration;

abstract class I1660_ReviewerRecommendations extends \PKP\migration\Migration
{
abstract protected function systemDefineNonRemovableRecommendations(): array;

protected ReviewerRecommendationsMigration $recommendationInstallMigration;

/**
* Constructor
*/
public function __construct(Installer $installer, array $attributes)
{
$this->recommendationInstallMigration = new ReviewerRecommendationsMigration(
$installer,
$attributes
);

parent::__construct($installer, $attributes);
}

/**
* Run the migration.
*/
public function up(): void
{
$this->recommendationInstallMigration->up();
}

/**
* Reverse the migration
*/
public function down(): void
{
$this->recommendationInstallMigration->down();
}

// TODO : Optimize the process if possible
protected function seedNonRemovableRecommendations(): void
{
$nonRemovablerecommendations = $this->systemDefineNonRemovableRecommendations();

if (empty($nonRemovablerecommendations)) {
return;
}

$currentLocale = Locale::getLocale();
$contextSupportedLocales = DB::table($this->recommendationInstallMigration->contextTable())
->select($this->recommendationInstallMigration->contextPrimaryKey())
->addSelect([
"supportedLocales" => DB::table($this->recommendationInstallMigration->settingTable())
->select("setting_value")
->whereColumn(
$this->recommendationInstallMigration->contextPrimaryKey(),
"{$this->recommendationInstallMigration->contextTable()}.{$this->recommendationInstallMigration->contextPrimaryKey()}"
)
->where("setting_name", "supportedLocales")
->limit(1)
])
->get()
->pluck("supportedLocales", $this->recommendationInstallMigration->contextPrimaryKey())
->filter()
->map(fn($locales) => json_decode($locales));

try {

$recommendations = [];

foreach ($nonRemovablerecommendations as $recommendationValue => $translatableKey) {
$recommendations[$recommendationValue] = [
'contextId' => null,
'value' => $recommendationValue,
'removable' => 0,
'status' => 1,
'title' => [],
];
}

$allContextSupportLocales = $contextSupportedLocales
->values()
->flatten()
->unique()
->toArray();

ReviewerRecommendation::unguard();

DB::beginTransaction();

foreach ($allContextSupportLocales as $locale) {

Locale::setLocale($locale);

foreach ($nonRemovablerecommendations as $recommendationValue => $translatableKey) {
$recommendations[$recommendationValue]['title'][$locale] = __($translatableKey);
}
}

Locale::setLocale($currentLocale);

$contextSupportedLocales->each(
fn (array $supportedLocales, int $contextId) => collect($recommendations)->each(
fn (array $recommendation) =>
ReviewerRecommendation::create(
array_merge($recommendation, [
'contextId' => $contextId,
'title' => array_intersect_key(
$recommendation['title'],
array_flip($supportedLocales)
)
])
)
)
);

DB::commit();

ReviewerRecommendation::reguard();

} catch (Throwable $exception) {

DB::rollBack();
Locale::setLocale($currentLocale);
ReviewerRecommendation::reguard();

ray($exception);
throw $exception;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

use APP\facades\Repo;
use APP\core\Application;
use Exception;
use PKP\core\traits\ModelWithSettings;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use PKP\submission\reviewer\recommendation\cast\ReviewerRecommendationValueCast;

class ReviewerRecommendation extends Model
{
Expand Down Expand Up @@ -35,12 +37,23 @@ class ReviewerRecommendation extends Model
protected function casts(): array
{
return [
'value' => 'integer',
'context_id' => 'integer',
'status' => 'boolean',
'status' => 'integer', // We cast the boolean to corresponding int e.g. true/false to 1/0
'removable' => 'boolean',
];
}

/**
* The "booted" method of the model.
*/
protected static function booted(): void
{
static::creating(function (Model $recommendation) {
$recommendation->value = $recommendation->value;
});
}

/**
* @copydoc \PKP\core\traits\ModelWithSettings::getSettingsTable
*/
Expand Down Expand Up @@ -76,6 +89,43 @@ public function getMultilingualProps(): array
'title',
];
}

protected function value(): Attribute
{
return Attribute::make(
set: function (?int $value) {
if ($this->getRawOriginal('value')) {
return $this->getRawOriginal('value');
}

if ($value) {
$existingRecommendation = static::query()
->withContextId($this->contextId)
->where('value', $value)
->first();

if ($existingRecommendation) {
throw new Exception(
"Given recommendation value : {$value} already exist for given context"
);
}

return $value;
}

$lastRecommendationValue = static::query()
->withContextId($this->contextId)
->when(
$this->id,
fn ($query) => $query->where($this->getKeyName(), '!=', $this->id)
)
->orderBy($this->getKeyName(), 'desc')
->first()?->value ?? 0;

return $lastRecommendationValue + 1;
}
);
}

protected function removable(): Attribute
{
Expand All @@ -87,13 +137,17 @@ protected function removable(): Attribute

$reviewAssignmentCount = Repo::reviewAssignment()
->getCollector()
->filterByRecommenddations([$this->id])
->filterByRecommenddations([$this->value])
->getCount();

return $reviewAssignmentCount === 0;
},
set: function () {
return $this->getRawOriginal('removable');
// TODO : MUST FIX ME !!! This cause issue at data seeding in migration process
set: function (bool $value) {
if (!is_null($this->getRawOriginal('removable'))) {
return $this->getRawOriginal('removable');
}
return $value;
}
)->shouldCache();
}
Expand Down

0 comments on commit 54b8886

Please sign in to comment.