Skip to content

Commit

Permalink
[9.x] Add whenHas to JsonResource (#45376)
Browse files Browse the repository at this point in the history
* Add whenHas

* Add tests

* enhancement `whenCounted`

* Formatting

* Fix

* Replace isset function to `Arr::has()`

* formatting

* formatting

* adjust wording

* formatting

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
michaelnabil230 and taylorotwell authored Dec 23, 2022
1 parent 651b149 commit b83a1ce
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
25 changes: 24 additions & 1 deletion src/Illuminate/Http/Resources/ConditionallyLoadsAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,29 @@ protected function attributes($attributes)
);
}

/**
* Retrieve an attribute if it exists on the resource.
*
* @param string $attribute
* @param mixed $value
* @param mixed $default
* @return \Illuminate\Http\Resources\MissingValue|mixed
*/
public function whenHas($attribute, $value = null, $default = null)
{
if (func_num_args() < 3) {
$default = new MissingValue;
}

if (! array_key_exists($attribute, $this->resource->getAttributes())) {
return value($default);
}

return func_num_args() === 1
? $this->resource->{$attribute}
: value($value, $this->resource->{$attribute});
}

/**
* Retrieve a model attribute if it is null.
*
Expand Down Expand Up @@ -242,7 +265,7 @@ protected function whenLoaded($relationship, $value = null, $default = null)
public function whenCounted($relationship, $value = null, $default = null)
{
if (func_num_args() < 3) {
$default = new MissingValue();
$default = new MissingValue;
}

$attribute = (string) Str::of($relationship)->snake()->finish('_count');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Illuminate\Tests\Integration\Http\Fixtures;

use Illuminate\Http\Resources\Json\JsonResource;

class PostResourceWithOptionalHasAttributes extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'first' => $this->whenHas('is_published'),
'second' => $this->whenHas('is_published', 'override value'),
'third' => $this->whenHas('is_published', function () {
return 'override value';
}),
'fourth' => $this->whenHas('is_published', $this->is_published, 'default'),
'fifth' => $this->whenHas('is_published', $this->is_published, function () {
return 'default';
}),
];
}
}
55 changes: 55 additions & 0 deletions tests/Integration/Http/ResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalAppendedAttributes;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalAttributes;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalData;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalHasAttributes;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalMerging;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalPivotRelationship;
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalRelationship;
Expand Down Expand Up @@ -188,6 +189,60 @@ public function testResourcesMayHaveOptionalSelectedAttributes()
]);
}

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

return new PostResourceWithOptionalHasAttributes($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 testResourcesWithOptionalHasAttributesReturnDefaultValuesAndNotMissingValues()
{
Route::get('/', function () {
return new PostResourceWithOptionalHasAttributes(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 testResourcesMayHaveOptionalAppendedAttributes()
{
Route::get('/', function () {
Expand Down

0 comments on commit b83a1ce

Please sign in to comment.