Skip to content

Commit

Permalink
[7.x] Conditionally returning appended attributes in API resources (#…
Browse files Browse the repository at this point in the history
…33422)

* Add hasAppended method to HasAttributes trait

* Add whenAppended() method for resources

* Fix docblock

* Test hasAppended() method

* Test whenAppended() method

* Fix docblock

* Improve test

* Test the unhappy path
  • Loading branch information
jessarcher committed Jul 3, 2020
1 parent f1a21b3 commit 9c29794
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Expand Up @@ -1484,6 +1484,17 @@ public function setAppends(array $appends)
return $this;
}

/**
* Return whether the accessor attribute has been appended.
*
* @param string $attribute
* @return bool
*/
public function hasAppended($attribute)
{
return in_array($attribute, $this->appends);
}

/**
* Get the mutated attributes for a given instance.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Illuminate/Http/Resources/ConditionallyLoadsAttributes.php
Expand Up @@ -209,6 +209,23 @@ protected function whenPivotLoadedAs($accessor, $table, $value, $default = null)
);
}

/**
* Retrieve an accessor when it has been appended.
*
* @param string $attribute
* @param mixed $value
* @param mixed $default
* @return \Illuminate\Http\Resources\MissingValue|mixed
*/
protected function whenAppended($attribute, $value = null, $default = null)
{
if ($this->resource->hasAppended($attribute)) {
return func_num_args() >= 2 ? value($value) : $this->resource->$attribute;
}

return func_num_args() === 3 ? value($default) : new MissingValue;
}

/**
* Transform the given value if it is present.
*
Expand Down
5 changes: 5 additions & 0 deletions tests/Database/DatabaseEloquentModelTest.php
Expand Up @@ -1593,6 +1593,11 @@ public function testAppendingOfAttributes()
$this->assertSame('camelCased', $model->camelCased);
$this->assertSame('StudlyCased', $model->StudlyCased);

$this->assertTrue($model->hasAppended('is_admin'));
$this->assertTrue($model->hasAppended('camelCased'));
$this->assertTrue($model->hasAppended('StudlyCased'));
$this->assertFalse($model->hasAppended('not_appended'));

$model->setHidden(['is_admin', 'camelCased', 'StudlyCased']);
$this->assertEquals([], $model->toArray());

Expand Down
10 changes: 10 additions & 0 deletions tests/Integration/Http/Fixtures/Post.php
Expand Up @@ -12,4 +12,14 @@ class Post extends Model
* @var array
*/
protected $guarded = [];

/**
* Return whether the post is published.
*
* @return bool
*/
public function getIsPublishedAttribute()
{
return true;
}
}
@@ -0,0 +1,24 @@
<?php

namespace Illuminate\Tests\Integration\Http\Fixtures;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResourceWithOptionalAppendedAttributes extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'first' => $this->whenAppended('is_published'),
'second' => $this->whenAppended('is_published', 'override value'),
'third' => $this->whenAppended('is_published', function () {
return 'override value';
}),
'fourth' => $this->whenAppended('is_published', $this->is_published, 'default'),
'fifth' => $this->whenAppended('is_published', $this->is_published, function () {
return 'default';
}),
];
}
}
54 changes: 54 additions & 0 deletions tests/Integration/Http/ResourceTest.php
Expand Up @@ -17,6 +17,7 @@
use Illuminate\Tests\Integration\Http\Fixtures\PostCollectionResource;
use Illuminate\Tests\Integration\Http\Fixtures\PostResource;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithExtraData;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalAppendedAttributes;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalData;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalMerging;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalPivotRelationship;
Expand Down Expand Up @@ -153,6 +154,59 @@ public function testResourcesMayHaveOptionalValues()
]);
}

public function testResourcesMayHaveOptionalAppendedAttributes()
{
Route::get('/', function () {
$post = new Post([
'id' => 5,
]);

$post->append('is_published');

return new PostResourceWithOptionalAppendedAttributes($post);
});

$response = $this->withoutExceptionHandling()->get(
'/', ['Accept' => 'application/json']
);

$response->assertStatus(200);

$response->assertJson([
'data' => [
'id' => 5,
'first' => true,
'second' => 'override value',
'third' => 'override value',
'fourth' => true,
'fifth' => true,
],
]);
}

public function testResourcesWithOptionalAppendedAttributesReturnDefaultValuesAndNotMissingValues()
{
Route::get('/', function () {
return new PostResourceWithOptionalAppendedAttributes(new Post([
'id' => 5,
]));
});

$response = $this->withoutExceptionHandling()->get(
'/', ['Accept' => 'application/json']
);

$response->assertStatus(200);

$response->assertExactJson([
'data' => [
'id' => 5,
'fourth' => 'default',
'fifth' => 'default',
],
]);
}

public function testResourcesMayHaveOptionalMerges()
{
Route::get('/', function () {
Expand Down

0 comments on commit 9c29794

Please sign in to comment.