Skip to content

Commit

Permalink
Fix retrieval of property to work for Astrotomic/translatable
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofandel committed Jan 25, 2025
1 parent 9e75111 commit 56bd051
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 24 deletions.
32 changes: 13 additions & 19 deletions src/Normalizers/Normalized/NormalizedModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Spatie\LaravelData\Normalizers\Normalized;

use Illuminate\Database\Eloquent\MissingAttributeException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use ReflectionProperty;
Expand All @@ -23,11 +24,9 @@ public function __construct(

public function getProperty(string $name, DataProperty $dataProperty): mixed
{
$propertyName = $this->model::$snakeAttributes ? Str::snake($name) : $name;

$value = array_key_exists($propertyName, $this->properties)
? $this->properties[$propertyName]
: $this->fetchNewProperty($propertyName, $dataProperty);
$value = array_key_exists($name, $this->properties)
? $this->properties[$name]
: $this->fetchNewProperty($name, $dataProperty);

if ($value === null && ! $dataProperty->type->isNullable) {
return UnknownProperty::create();
Expand All @@ -38,25 +37,23 @@ public function getProperty(string $name, DataProperty $dataProperty): mixed

protected function fetchNewProperty(string $name, DataProperty $dataProperty): mixed
{
if ($this->hasModelAttribute($name)) {
return $this->properties[$name] = $this->model->getAttributeValue($name);
}

$camelName = Str::camel($name);

if ($dataProperty->attributes->contains(fn (object $attribute) => $attribute::class === LoadRelation::class)) {
if (method_exists($this->model, $name)) {
$this->model->loadMissing($name);
} elseif (method_exists($this->model, $camelName)) {
$this->model->loadMissing($camelName);
}
}

if ($this->model->relationLoaded($name)) {
return $this->properties[$name] = $this->model->getRelation($name);
}
if ($this->model->relationLoaded($camelName)) {
return $this->properties[$name] = $this->model->getRelation($camelName);

if (!$this->model->isRelation($name)) {
try {
$propertyName = $this->model::$snakeAttributes ? Str::snake($name) : $name;
return $this->properties[$name] = $this->model->getAttribute($propertyName);
} catch (MissingAttributeException) {
// Fallback if missing Attribute
}
}

return $this->properties[$name] = UnknownProperty::create();
Expand All @@ -68,16 +65,13 @@ protected function hasModelAttribute(string $name): bool
return $this->model->hasAttribute($name);
}

// TODO: to use that one once we stop supporting Laravel 10

// TODO: remove this once we stop supporting Laravel 10
if (! isset($this->attributesProperty)) {
$this->attributesProperty = new ReflectionProperty($this->model, 'attributes');
$this->attributesProperty->setAccessible(true);
}

if (! isset($this->castsProperty)) {
$this->castsProperty = new ReflectionProperty($this->model, 'casts');
$this->castsProperty->setAccessible(true);
}

return array_key_exists($name, $this->attributesProperty->getValue($this->model)) ||
Expand Down
4 changes: 3 additions & 1 deletion tests/Fakes/FakeModelData.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

use Carbon\CarbonImmutable;
use Spatie\LaravelData\Attributes\DataCollectionOf;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\Mappers\CamelCaseMapper;
use Spatie\LaravelData\Optional;

class FakeModelData extends Data
Expand All @@ -14,7 +16,7 @@ public function __construct(
public string $string,
public ?string $nullable,
public CarbonImmutable $date,
#[DataCollectionOf(FakeNestedModelData::class)]
#[DataCollectionOf(FakeNestedModelData::class), MapInputName(CamelCaseMapper::class)]
public Optional|null|DataCollection $fake_nested_models,
public string $accessor,
public string $old_accessor,
Expand Down
11 changes: 7 additions & 4 deletions tests/Normalizers/ModelNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@

$dataClass = new class () extends Data {
#[LoadRelation, DataCollectionOf(FakeNestedModelData::class)]
public array $fake_nested_models;
public array $fakeNestedModels;

#[LoadRelation, DataCollectionOf(FakeNestedModelData::class)]
public array $fake_nested_models_snake_cased;
Expand All @@ -131,7 +131,7 @@

$queryLog = DB::getQueryLog();

expect($data->fake_nested_models)
expect($data->fakeNestedModels)
->toHaveCount(2)
->each->toBeInstanceOf(FakeNestedModelData::class);

Expand Down Expand Up @@ -183,15 +183,18 @@

$dataClass = new class () extends Data {
#[DataCollectionOf(FakeNestedModelData::class), MapInputName(SnakeCaseMapper::class)]
public array|Optional $fakeNestedModels;
public array $fakeNestedModels;
#[DataCollectionOf(FakeNestedModelData::class), MapInputName(SnakeCaseMapper::class), LoadRelation]
public array|Optional $fakeNestedModelsSnakeCased;

#[MapInputName(SnakeCaseMapper::class)]
public string $oldAccessor;
};

$data = $dataClass::from($model->load('fakeNestedModels'));

expect($data->fakeNestedModels)
expect(isset($data->fakeNestedModels))->toBeFalse();
expect($data->fakeNestedModelsSnakeCased)
->toHaveCount(2)
->each()
->toBeInstanceOf(FakeNestedModelData::class);
Expand Down

0 comments on commit 56bd051

Please sign in to comment.