Skip to content

Commit

Permalink
#10292 added multilingual casting as part of #10476
Browse files Browse the repository at this point in the history
  • Loading branch information
touhidurabir committed Oct 22, 2024
1 parent 9475987 commit 160d196
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 7 deletions.
55 changes: 55 additions & 0 deletions classes/core/casts/MultilingualSettingAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/**
* @file classes/core/casts/MultilingualSettingAttribute.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class MultilingualSettingAttribute
*
* @brief Caster to cast the viven values of multilingual attribute in proper
* format before storing in DB.
*/

namespace PKP\core\casts;

use Exception;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use PKP\core\traits\ModelWithSettings;
use PKP\facades\Locale;

class MultilingualSettingAttribute implements CastsInboundAttributes
{
/**
* Prepare the given value for storage.
*/
public function set(Model $model, string $key, mixed $value, array $attributes): array
{
if (!in_array(ModelWithSettings::class, class_uses_recursive(get_class($model)))) {
throw new Exception(
sprintf(
"model class %s does not support multilingual setting attributes/properties",
get_class($model)
)
);
}

$key = Str::camel($key);

if (!in_array($key, $model->getMultilingualProps())) {
throw new Exception(
'Applying multilingual casting on non-maltilingual attribute is not allowed'
);
}

if (is_string($value)) {
return [$key => [Locale::getLocale() => $value]];
}

return [$key => array_filter($value)];
}
}
31 changes: 24 additions & 7 deletions classes/core/traits/ModelWithSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Eloquence\Behaviours\HasCamelCasing;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Casts\Attribute;
use PKP\core\casts\MultilingualSettingAttribute;
use PKP\core\maps\Schema;
use PKP\core\SettingsBuilder;
use PKP\facades\Locale;
Expand Down Expand Up @@ -78,6 +79,14 @@ public function __construct(array $attributes = [])
if (static::getSchemaName()) {
$this->setSchemaData();
} else {
$this->generateAttributeCast(
collect($this->getMultilingualProps())
->flatMap(
fn (string $attribute): array => [$attribute => MultilingualSettingAttribute::class]
)
->toArray()
);

if (!empty($this->fillable)) {
$this->mergeFillable(array_merge($this->getSettings(), $this->getMultilingualProps()));
}
Expand Down Expand Up @@ -163,16 +172,24 @@ protected function setSchemaData(): void
protected function convertSchemaToCasts(stdClass $schema): void
{
$propCast = [];

foreach ($schema->properties as $propName => $propSchema) {
// Don't cast multilingual values as Eloquent tries to convert them from string to arrays with json_decode()
if (isset($propSchema->multilingual)) {
continue;
}
$propCast[$propName] = $propSchema->type;

$propCast[$propName] = isset($propSchema->multilingual) && $propSchema->multilingual == true
? MultilingualSettingAttribute::class
: $propSchema->type;
}

$propCasts = $this->ensureCastsAreStringValues($propCast);
$this->casts = array_merge($propCasts, $this->casts);
$this->generateAttributeCast($propCast);
}

/**
* Generate the final cast from dynamically generated attr casts
*/
protected function generateAttributeCast(array $attrCast): void
{
$attrCasts = $this->ensureCastsAreStringValues($attrCast);
$this->casts = array_merge($attrCasts, $this->casts);
}

/**
Expand Down

0 comments on commit 160d196

Please sign in to comment.