Skip to content

Commit

Permalink
Merge branch '2.x' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
gregorip02 committed Jun 21, 2020
2 parents 01d7417 + 910243a commit 6ef10d5
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 85 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ php artisan restql:schema

Add the `RestqlAttributes` trait to your eloquent models.

> This is mandatory only if your endpoint will accept create or update clausules.
> **2.2** This is recomended because you can determine the selectable attributes with `onSelectFillable`.
```php
<?php
Expand Down
2 changes: 1 addition & 1 deletion docs
Submodule docs updated from d4a1b8 to cb90e0
22 changes: 18 additions & 4 deletions src/Arguments/SelectArgument.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

namespace Restql\Arguments;

use Restql\Contracts\ArgumentContract;
use Restql\ModelArgument;
use Restql\Contracts\ArgumentContract;
use Illuminate\Support\Collection;

class SelectArgument extends ModelArgument implements ArgumentContract
{
Expand All @@ -16,10 +17,23 @@ public function values(): array
{
$values = $this->excludeHiddenAttributes();

$pkName = $this->getKeyName();
/// The onSelectFillables method allow to developers to determine
/// what attributes can be obtained for clients based on
/// your roles or pemissions.
if ($this->unsingRestqlTrait()) {
$values = Collection::make(array_combine($values, $values))
->only($this->model->onSelectFillables())
->keys()
->toArray();
}

/// By default we include the model primary key on every
/// select clausule because is necesary for add correctly
/// the model releationships eager loaded.
$primaryKeyName = $this->getKeyName();

if (! in_array($pkName, $values)) {
$values[] = $pkName;
if (! in_array($primaryKeyName, $values)) {
$values[] = $primaryKeyName;
}

return $values;
Expand Down
13 changes: 12 additions & 1 deletion src/ModelArgument.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

namespace Restql;

use Illuminate\Database\Eloquent\Model;
use Restql\Argument;
use Restql\Traits\RestqlAttributes;
use Illuminate\Database\Eloquent\Model;

abstract class ModelArgument extends Argument
{
Expand Down Expand Up @@ -56,6 +57,16 @@ public function getHidden(): array
return $this->model->getHidden();
}

/**
* Determine if current model is using Restql\Traits\RestqlAttributes.
*
* @return bool
*/
public function unsingRestqlTrait(): bool
{
return in_array(RestqlAttributes::class, class_uses($this->model));
}

/**
* Exclude model hidden attributes.
*
Expand Down
10 changes: 10 additions & 0 deletions src/Traits/RestqlAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

trait RestqlAttributes
{
/**
* Get the fillable attributes for selects.
*
* @return array
*/
public function onSelectFillables(): array
{
return $this->getFillable();
}

/**
* Get the fillable attributes for creations.
*
Expand Down
14 changes: 14 additions & 0 deletions tests/App/app/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

use Testing\App\Author;
use Testing\App\Comment;
use Restql\Traits\RestqlAttributes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Article extends Model
{
use RestqlAttributes;

/**
* Get the article author.
*
Expand All @@ -29,4 +32,15 @@ public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}

/**
* Get the fillable attributes for selects.
*
* @return array
*/
public function onSelectFillables(): array
{
// You cand replace this with custom authorization.
return ['title', 'content'];
}
}
7 changes: 7 additions & 0 deletions tests/App/app/Author.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ class Author extends Model
{
use RestqlAttributes;

/**
* Fillable attributes for the model.
*
* @var array
*/
protected $fillable = ['name', 'email'];

/**
* Get the author articles.
*
Expand Down
7 changes: 7 additions & 0 deletions tests/App/app/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ class Comment extends Model
{
use RestqlAttributes;

/**
* Fillable attributes for the model.
*
* @var array
*/
protected $fillable = ['content'];

/**
* Get the comment author.
*
Expand Down
177 changes: 100 additions & 77 deletions tests/Feature/Clausules/SelectClausuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,83 +6,106 @@

final class SelectClausuleTest extends TestCase
{
/**
* @test Gets empty response.
*/
public function getsEmptyResponse(): void
{
$response = $this->json('get', 'restql');

$response->assertJson([
'data' => []
]);
}

/**
* @test Select specific attributes using implicit method
*/
public function getSpecificAttributesUsingImplicitMethod(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => 'name'
]
]);

$response->assertJsonCount(15, 'data.authors');

$response->assertJsonStructure([
'data' => ['authors' => [['name', 'id']]]
]);
}
/**
* @test Gets empty response.
*/
public function getsEmptyResponse(): void
{
$response = $this->json('get', 'restql');

$response->assertJson([
'data' => []
]);
}

/**
* @test Select specific attributes using explicit method
*/
public function getSpecificAttributesUsingExplicitMethod(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => ['name']
]
]);

$response->assertJsonCount(15, 'data.authors');

$response->assertJsonStructure([
'data' => ['authors' => [['name', 'id']]]
]);
}

/**
* @test Get specific attributes from diferents models.
*/
public function getSpecificAttributesFromDiferentsModels(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => ['name', 'email']
],
'articles' => [
'select' => 'title',
'take' => 20
],
'comments' => [
'select' => ['content']
]
]);

$response->assertJsonCount(3, 'data');
$response->assertJsonCount(15, 'data.authors');
$response->assertJsonCount(20, 'data.articles');
$response->assertJsonCount(15, 'data.comments');

$response->assertJsonStructure([
'data' => [
'authors' => [['id', 'name', 'email']],
'articles' => [['id', 'title']],
'comments' => [['id', 'content']]
]
]);
}
* @test Select specific attributes using implicit method
*/
public function getSpecificAttributesUsingImplicitMethod(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => 'name'
]
]);

$response->assertJsonCount(15, 'data.authors');

$response->assertJsonStructure([
'data' => ['authors' => [['name', 'id']]]
]);
}

/**
* @test Select specific attributes using explicit method
*/
public function getSpecificAttributesUsingExplicitMethod(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => ['name']
]
]);

$response->assertJsonCount(15, 'data.authors');

$response->assertJsonStructure([
'data' => ['authors' => [['name', 'id']]]
]);
}

/**
* @test Get specific attributes from diferents models.
*/
public function getSpecificAttributesFromDiferentsModels(): void
{
$response = $this->json('get', 'restql', [
'authors' => [
'select' => ['name', 'email']
],
'articles' => [
'select' => 'title',
'take' => 20
],
'comments' => [
'select' => ['content']
]
]);

$response->assertJsonCount(3, 'data');
$response->assertJsonCount(15, 'data.authors');
$response->assertJsonCount(20, 'data.articles');
$response->assertJsonCount(15, 'data.comments');

$response->assertJsonStructure([
'data' => [
'authors' => [['id', 'name', 'email']],
'articles' => [['id', 'title']],
'comments' => [['id', 'content']]
]
]);
}

/**
* @test Can't get specifc attributes from determinated model.
*/
public function cantGetProtectedAttributesFromArticleModel(): void
{
$publicAttr = (new \Testing\App\Article())->onSelectFillables();

$response = $this->json('get', 'restql', [
'articles' => [
/// TODO: Document this.
'select' => array_merge($publicAttr, ['public'])
]
]);

$response->assertJsonStructure([
'data' => [
'articles' => [array_merge($publicAttr, ['id'])]
]
]);

$response->assertDontSee("\"public\":", false);
}
}
20 changes: 20 additions & 0 deletions tests/Unit/ConfigTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Testing\Unit;

use Testing\TestCase;

final class ConfigTest extends TestCase
{
/**
* @test Testing clausules are published correctly.
*/
public function assertCountClausulesBetweenTestingAndPublished(): void
{
$internal = require(__DIR__ . '/../App/config/restql.php');

$external = require(__DIR__ . '/../../config/restql.php');

$this->assertEquals(count($internal['clausules']), count($external['clausules']));
}
}
1 change: 0 additions & 1 deletion tests/insomnia.json

This file was deleted.

0 comments on commit 6ef10d5

Please sign in to comment.