Skip to content

Commit

Permalink
IncludingServiceTest completed;
Browse files Browse the repository at this point in the history
  • Loading branch information
hans-thomas committed May 6, 2023
1 parent e0cbc86 commit b54fee5
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/Http/Resources/Contracts/BaseJsonResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function toArray( $request ): array {
$data = array_merge( [ 'type' => $this->type() ], $extracted );

if ( $this->resource instanceof Model ) {
app( IncludingService::class, [ 'json_resource' => $this ] )
app( IncludingService::class, [ 'resource' => $this ] )
->registerIncludesUsingQueryStringWhen( $this->shouldParseIncludes(), $request->get( 'includes' ) )
->applyRequestedIncludes( $this->resource )
->mergeIncludedDataTo( $data );
Expand Down Expand Up @@ -196,7 +196,7 @@ public function getNestedEagerLoads(): array {
}

public function applyNestedEagerLoadsOnRelation( string $nested ): self {
$data = app( IncludingService::class, [ 'json_resource' => $this ] )->parseInclude( $nested );
$data = app( IncludingService::class, [ 'resource' => $this ] )->parseInclude( $nested );

if ( ! empty( $data[ 'nested' ] ) ) {
$this->setNestedEagerLoadsFor( $data[ 'relation' ], $data[ 'nested' ] );
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Resources/Contracts/BaseResourceCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public function toArray( $request ): array {
$data = array_merge( [ 'type' => $this->type() ], $extracted );

if ( $item->resource instanceof Model ) {
app( IncludingService::class, [ 'json_resource' => $this ] )
app( IncludingService::class, [ 'resource' => $this ] )
->registerIncludesUsingQueryStringWhen( $this->shouldParseIncludes(),
$request->get( 'includes' ) )
->applyRequestedIncludes( $item->resource )
Expand Down
81 changes: 46 additions & 35 deletions src/Services/Includes/IncludingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Hans\Valravn\Services\Includes;

use Hans\Valravn\Http\Resources\Contracts\BaseJsonResource;
use Hans\Valravn\Http\Resources\Contracts\Includes;
use Hans\Valravn\Services\Includes\Actions\LimitAction;
use Hans\Valravn\Services\Includes\Actions\OrderAction;
Expand All @@ -11,7 +12,7 @@
use Illuminate\Support\Str;

class IncludingService {
private JsonResource $json_resource;
private BaseJsonResource $resource;
private array $data = [];
private array $registeredActions = [
'select' => SelectAction::class,
Expand All @@ -20,10 +21,10 @@ class IncludingService {
];

/**
* @param JsonResource $json_resource
* @param BaseJsonResource $resource
*/
public function __construct( JsonResource $json_resource ) {
$this->json_resource = $json_resource;
public function __construct( BaseJsonResource $resource ) {
$this->resource = $resource;
}

/**
Expand All @@ -42,11 +43,14 @@ public function registerIncludesUsingQueryString( string|array|null $includes ):

foreach ( $includes as $include ) {
$data = $this->parseInclude( $include );
if ( is_null( $data ) ) {
continue;
}

if ( ! empty( $data[ 'nested' ] ) ) {
$this->json_resource->setNestedEagerLoadsFor( $data[ 'relation' ], $data[ 'nested' ] );
$this->resource->setNestedEagerLoadsFor( $data[ 'relation' ], $data[ 'nested' ] );
}
$this->json_resource
$this->resource
->registerInclude(
$this->getAvailableIncludes()[ $data[ 'relation' ] ],
$data[ 'actions' ]
Expand All @@ -57,14 +61,34 @@ public function registerIncludesUsingQueryString( string|array|null $includes ):
return $this;
}

public function parseInclude( string $include ): ?array {
$relation = Str::of( $include )->before( ':' )->before( '.' )->toString();
$data = compact( 'relation' );
$data[ 'actions' ] = [];
public function registerIncludesUsingQueryStringWhen( bool $condition, string|array|null $includes ): self {
if ( $condition ) {
$this->registerIncludesUsingQueryString( $includes );
}

return $this;
}

public function parseInclude( string $include ): array {
$relation = Str::of( $include )->before( ':' )->before( '.' )->toString();
$data[ 'relation' ] = $relation;
$data[ 'actions' ] = [];
$data[ 'nested' ] = [];
if ( ! key_exists( $relation, $this->getAvailableIncludes() ) ) {
return null;
return $data;
}
$filters = Str::of( $include )->substr( strlen( $relation ) + 1 )->before( '.' )->explode( ':' );
// nested data
$nested = Str::of( $include )
->substr( Str::of( $include )->before( '.' )->length() )
->after( '.' )
->toString();
$data[ 'nested' ] = $nested;
// actions data
$filters = Str::of( $include )
->replace( "$relation.", '' )
->replace( $data[ 'nested' ], '' )
->before( '.' )
->explode( ':' );
foreach ( $filters as $filter ) {
$action = Str::before( $filter, '(' );
$params = Str::of( $filter )
Expand All @@ -80,49 +104,36 @@ public function parseInclude( string $include ): ?array {
$action = $this->registeredActions[ $action ];
$data[ 'actions' ][ $action ] = $params;
}
// TODO: support nested eager loading
$nested = Str::of( $include )
->substr( Str::of( $include )->before( '.' )->length() )
->after( '.' )
->toString();
$data[ 'nested' ] = $nested;

return $data;
}

public function registerIncludesUsingQueryStringWhen( bool $condition, string|array|null $includes ): self {
if ( $condition ) {
$this->registerIncludesUsingQueryString( $includes );
}

return $this;
}

public function applyRequestedIncludes( Model $model ): self {
foreach ( $this->json_resource->getRequestedIncludes() as $include => $actions ) {
foreach ( $this->resource->getRequestedIncludes() as $include => $actions ) {
$this->data[ $this->getInstanceKey( $include ) ] = app( $include )->run( $model )
->registerActions( $actions )
->applyActions()
->toResource();
if ( key_exists( $this->getInstanceKey( $include ), $this->json_resource->getNestedEagerLoads() ) ) {
$this->data[ $this->getInstanceKey( $include ) ]->applyNestedEagerLoadsOnRelation(
$this->json_resource->getNestedEagerLoadsFor( $this->getInstanceKey( $include ) )
);
if ( key_exists( $this->getInstanceKey( $include ), $this->resource->getNestedEagerLoads() ) ) {
$this->data[ $this->getInstanceKey( $include ) ]
->applyNestedEagerLoadsOnRelation(
$this->resource->getNestedEagerLoadsFor( $this->getInstanceKey( $include ) )
);
}
}

return $this;
}

public function getAvailableIncludes(): array {
return $this->json_resource->getAvailableIncludes();
protected function getAvailableIncludes(): array {
return $this->resource->getAvailableIncludes();
}

public function getIncludeInstance( string $include ): Includes {
protected function getIncludeInstance( string $include ): Includes {
return app( $this->getAvailableIncludes()[ $include ] );
}

public function getInstanceKey( string|object $instance ): string {
protected function getInstanceKey( string|object $instance ): string {
$instance = is_object( $instance ) ? get_class( $instance ) : $instance;

return array_flip( $this->getAvailableIncludes() )[ $instance ];
Expand Down
5 changes: 5 additions & 0 deletions tests/Core/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Hans\Valravn\Models\Contracts\Filtering\Filterable;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Post extends BaseModel implements Filterable {
Expand All @@ -21,6 +22,10 @@ public function comments(): HasMany {
return $this->hasMany( Comment::class );
}

public function categories(): BelongsToMany {
return $this->belongsToMany( Category::class );
}

/**
* Create a new factory instance for the model.
*
Expand Down
10 changes: 10 additions & 0 deletions tests/Core/Resources/Comment/CommentCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@

namespace Hans\Tests\Valravn\Core\Resources\Comment;

use Hans\Tests\Valravn\Instances\Http\Includes\PostIncludes;
use Hans\Valravn\Http\Resources\Contracts\BaseResourceCollection;
use Illuminate\Database\Eloquent\Model;

class CommentCollection extends BaseResourceCollection {

/**
* @return array
*/
public function getAvailableIncludes(): array {
return [
'post' => PostIncludes::class,
];
}

/**
* @param Model $model
*
Expand Down
10 changes: 10 additions & 0 deletions tests/Core/Resources/Comment/CommentResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@

namespace Hans\Tests\Valravn\Core\Resources\Comment;

use Hans\Tests\Valravn\Instances\Http\Includes\PostIncludes;
use Hans\Valravn\Http\Resources\Contracts\BaseJsonResource;
use Illuminate\Database\Eloquent\Model;

class CommentResource extends BaseJsonResource {

/**
* @return array
*/
public function getAvailableIncludes(): array {
return [
'post' => PostIncludes::class,
];
}

/**
* @param Model $model
*
Expand Down
4 changes: 3 additions & 1 deletion tests/Core/Resources/Post/PostResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Hans\Tests\Valravn\Core\Resources\Post;

use Hans\Tests\Valravn\Instances\Http\Includes\CategoriesIncludes;
use Hans\Tests\Valravn\Instances\Http\Includes\CommentsIncludes;
use Hans\Tests\Valravn\Instances\Http\Queries\FirstCommentQuery;
use Hans\Valravn\Http\Resources\Contracts\BaseJsonResource;
Expand All @@ -27,7 +28,8 @@ public function getAvailableQueries(): array {
*/
public function getAvailableIncludes(): array {
return [
'comments' => CommentsIncludes::class,
'comments' => CommentsIncludes::class,
'categories' => CategoriesIncludes::class,
];
}

Expand Down
Loading

0 comments on commit b54fee5

Please sign in to comment.