Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 69 additions & 1 deletion src/Fields/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ class Field extends OrganicField implements JsonSerializable
*/
protected $defaultCallback;

/**
* Closure be used for the field's default value when store/update.
*
* @var callable
*/
protected $appendCallback;

/**
* Closure be used to be called after the field value stored.
*/
Expand Down Expand Up @@ -190,12 +197,22 @@ public function fillAttribute(RestifyRequest $request, $model)
{
$this->resolveValueBeforeUpdate($request, $model);

if (isset($this->fillCallback)) {
if ($this->isHidden($request)) {
if (! isset($this->appendCallback)) {
return;
}
}

if (! $this->isHidden($request) && isset($this->fillCallback)) {
return call_user_func(
$this->fillCallback, $request, $model, $this->attribute
);
}

if (isset($this->appendCallback)) {
return $this->fillAttributeFromAppend($request, $model, $this->attribute);
}

if ($request->isStoreRequest() && is_callable($this->storeCallback)) {
return call_user_func(
$this->storeCallback, $request, $model, $this->attribute
Expand Down Expand Up @@ -227,6 +244,28 @@ protected function fillAttributeFromRequest(RestifyRequest $request, $model, $at
}
}

/**
* Fill the model with the default value.
*
* @param RestifyRequest $request
* @param $model
* @param $attribute
*/
protected function fillAttributeFromAppend(RestifyRequest $request, $model, $attribute)
{
if (! isset($this->appendCallback)) {
return;
}

if (is_callable($this->appendCallback)) {
return $model->{$attribute} = call_user_func(
$this->appendCallback, $request, $model, $attribute
);
}

$model->{$attribute} = $this->appendCallback;
}

/**
* @return callable|string|null
*/
Expand Down Expand Up @@ -477,4 +516,33 @@ public function invokeAfter(RestifyRequest $request, $repository)
call_user_func($this->afterUpdateCallback, $this->resolveAttribute($repository, $this->attribute), $this->valueBeforeUpdate, $repository, $request);
}
}

/**
* Indicate whatever the input is hidden or not.
*
* @param bool $callback
* @return $this
*/
public function hidden($callback = true)
{
$this->hideFromIndex($callback)
->hideFromShow($callback);

$this->hiddenCallback = $callback;

return $this;
}

/**
* Append values when store/update.
*
* @param callable|string $value
* @return $this
*/
public function append($value)
{
$this->appendCallback = $value;

return $this;
}
}
21 changes: 21 additions & 0 deletions src/Fields/OrganicField.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ abstract class OrganicField extends BaseField

public $readonlyCallback;

public $hiddenCallback;

public array $rules = [];

public array $storingRules = [];
Expand Down Expand Up @@ -64,6 +66,10 @@ public function hideFromIndex($callback = true)

public function isShownOnShow(RestifyRequest $request, $repository): bool
{
if ($this->isHidden($request)) {
return false;
}

if (is_callable($this->showOnShow)) {
$this->showOnShow = call_user_func($this->showOnShow, $request, $repository);
}
Expand All @@ -78,6 +84,10 @@ public function isHiddenOnShow(RestifyRequest $request, $repository): bool

public function isShownOnIndex(RestifyRequest $request, $repository): bool
{
if ($this->isHidden($request)) {
return false;
}

return false === $this->isHiddenOnIndex($request, $repository);
}

Expand Down Expand Up @@ -158,4 +168,15 @@ public function isShownOnStore(RestifyRequest $request, $repository): bool
{
return ! $this->isReadonly($request);
}

public function isHidden(RestifyRequest $request)
{
return with($this->hiddenCallback, function ($callback) use ($request) {
if ($callback === true || (is_callable($callback) && call_user_func($callback, $request))) {
return true;
}

return false;
});
}
}
35 changes: 35 additions & 0 deletions tests/Controllers/RepositoryShowControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,39 @@ public function test_show_mergeable_repository_containes_model_attributes_and_lo
],
]);
}

public function test_repository_hidden_fields_are_not_visible()
{
factory(Post::class)->create(['title' => 'Eduard']);

$response = $this->getJson('/restify-api/post-with-hidden-fields/1');

$this->assertArrayNotHasKey('user_id', $response->json('data.attributes'));
}

public function test_repository_hidden_fields_could_not_be_updated()
{
$post = factory(Post::class)->create(['user_id' => 2, 'title' => 'Eduard']);

$oldUserId = $post->user_id;

$this->putJson('/restify-api/post-with-hidden-fields/1', [
'title' => 'Updated title',
'user_id' => 1,
]);

$this->assertEquals($oldUserId, Post::find($post->id)->user_id);
}

public function test_repository_hidden_fields_could_be_updated_through_append()
{
$post = factory(Post::class)->create(['user_id' => 2, 'title' => 'Eduard', 'category' => 'Hidden category before update.']);

$this->putJson('/restify-api/post-with-hidden-fields/1', [
'title' => 'Updated title',
'category' => 'Trying to update hidden category.',
]);

$this->assertEquals('Append category for a hidden field.', $post->fresh()->category);
}
}
27 changes: 27 additions & 0 deletions tests/Fixtures/Post/PostWithHiddenFieldRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Fixtures\Post;

use Binaryk\LaravelRestify\Fields\Field;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use Binaryk\LaravelRestify\Repositories\Repository;

class PostWithHiddenFieldRepository extends Repository
{
public static $model = Post::class;

public static $uriKey = 'post-with-hidden-fields';

public static $globallySearchable = false;

public function fields(RestifyRequest $request)
{
return [
Field::new('user_id')->hidden(),

Field::new('category')->hidden()->append('Append category for a hidden field.'),

Field::new('title'),
];
}
}
2 changes: 2 additions & 0 deletions tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostMergeableRepository;
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostRepository;
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostUnauthorizedFieldRepository;
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithHiddenFieldRepository;
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostWithUnauthorizedFieldsRepository;
use Binaryk\LaravelRestify\Tests\Fixtures\User\User;
use Binaryk\LaravelRestify\Tests\Fixtures\User\UserRepository;
Expand Down Expand Up @@ -184,6 +185,7 @@ public function loadRepositories()
PostAuthorizeRepository::class,
PostWithUnauthorizedFieldsRepository::class,
PostUnauthorizedFieldRepository::class,
PostWithHiddenFieldRepository::class,
]);
}

Expand Down
50 changes: 50 additions & 0 deletions tests/Unit/FieldTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ public function test_field_fill_callback_has_high_priority()

/** * @var Field $field */
$field = Field::new('title')
->append(function () {
return 'from append callback';
})
->fillCallback(function ($request, $model) {
$model->title = 'from fill callback';
})
Expand Down Expand Up @@ -248,5 +251,52 @@ public function test_field_can_have_custom_label()
$field->resolveForIndex((object) ['name' => 'Binaryk'], 'name');

$this->assertEquals('custom_label', $field->label);
$this->assertEquals('custom_label', $field->jsonSerialize()['attribute']);
}

public function test_field_can_be_filled_from_the_append_value()
{
$request = new RepositoryStoreRequest([], []);

$request->merge([
'title' => 'Title from the request.',
]);

$model = new class extends Model {
protected $table = 'posts';
protected $fillable = ['title'];
};

/** * @var Field $field */
$field = Field::new('title')->append('Append title');

$field->fillAttribute($request, $model);

$model->save();

$this->assertEquals($model->title, 'Append title');
}

public function test_field_can_be_filled_from_the_append_callback()
{
$request = new RepositoryStoreRequest([], []);

$request->merge([
'title' => 'Title from the request.',
]);

$model = new class extends Model {
protected $table = 'posts';
protected $fillable = ['title'];
};

/** * @var Field $field */
$field = Field::new('title')->append(fn () => 'Append title');

$field->fillAttribute($request, $model);

$model->save();

$this->assertEquals($model->title, 'Append title');
}
}