From c29c88776f426f378487d1bca594af450367ce16 Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Sat, 23 Jan 2021 19:58:03 -0800 Subject: [PATCH] Add tagging support to foods and recipes --- .phpstorm.meta.php | 44 ++++ app/JsonApi/Adapters/FoodAdapter.php | 13 +- app/JsonApi/Adapters/JournalEntryAdapter.php | 3 +- app/JsonApi/Adapters/RecipeAdapter.php | 11 +- app/JsonApi/Adapters/RecipeStepAdapter.php | 4 +- app/JsonApi/Adapters/TagAdapter.php | 44 ++++ app/JsonApi/Adapters/UserAdapter.php | 3 +- app/JsonApi/Schemas/FoodSchema.php | 31 ++- .../Schemas/IngredientAmountSchema.php | 14 +- app/JsonApi/Schemas/JournalEntrySchema.php | 14 +- app/JsonApi/Schemas/RecipeSchema.php | 27 ++- app/JsonApi/Schemas/RecipeStepSchema.php | 14 +- app/JsonApi/Schemas/TagSchema.php | 34 +++ app/JsonApi/Schemas/UserSchema.php | 14 +- app/Models/Food.php | 10 +- app/Models/Recipe.php | 10 +- composer.json | 3 +- composer.lock | 220 +++++++++++++++++- config/json-api-v1.php | 1 + .../2021_01_23_191532_create_tag_tables.php | 32 +++ routes/api.php | 8 +- 21 files changed, 484 insertions(+), 70 deletions(-) create mode 100644 app/JsonApi/Adapters/TagAdapter.php create mode 100644 app/JsonApi/Schemas/TagSchema.php create mode 100644 database/migrations/2021_01_23_191532_create_tag_tables.php diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 0247e24..160ff33 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -13,8 +13,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -189,8 +193,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -365,8 +373,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -541,8 +553,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -717,8 +733,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -893,8 +913,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -1069,8 +1093,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -1245,8 +1273,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -1421,8 +1453,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -1597,8 +1633,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, @@ -1773,8 +1813,12 @@ namespace PHPSTORM_META { '' => '@', 'Asm89\Stack\CorsService' => \Asm89\Stack\CorsService::class, 'CloudCreativity\LaravelJsonApi\Api\Repository' => \CloudCreativity\LaravelJsonApi\Api\Repository::class, + 'CloudCreativity\LaravelJsonApi\Contracts\ContainerInterface' => \CloudCreativity\LaravelJsonApi\Container::class, 'CloudCreativity\LaravelJsonApi\Contracts\Exceptions\ExceptionParserInterface' => \CloudCreativity\LaravelJsonApi\Exceptions\ExceptionParser::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Resolver\ResolverInterface' => \CloudCreativity\LaravelJsonApi\Resolver\AggregateResolver::class, + 'CloudCreativity\LaravelJsonApi\Contracts\Store\StoreInterface' => \CloudCreativity\LaravelJsonApi\Store\Store::class, 'CloudCreativity\LaravelJsonApi\Factories\Factory' => \CloudCreativity\LaravelJsonApi\Factories\Factory::class, + 'CloudCreativity\LaravelJsonApi\Routing\Route' => \CloudCreativity\LaravelJsonApi\Routing\Route::class, 'CloudCreativity\LaravelJsonApi\Services\JsonApiService' => \CloudCreativity\LaravelJsonApi\Services\JsonApiService::class, 'CloudCreativity\LaravelJsonApi\View\Renderer' => \CloudCreativity\LaravelJsonApi\View\Renderer::class, 'Cviebrock\EloquentSluggable\SluggableObserver' => \Cviebrock\EloquentSluggable\SluggableObserver::class, diff --git a/app/JsonApi/Adapters/FoodAdapter.php b/app/JsonApi/Adapters/FoodAdapter.php index dd509d7..67814c6 100644 --- a/app/JsonApi/Adapters/FoodAdapter.php +++ b/app/JsonApi/Adapters/FoodAdapter.php @@ -2,9 +2,10 @@ namespace App\JsonApi\Adapters; +use App\Models\Food; use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter; +use CloudCreativity\LaravelJsonApi\Eloquent\HasMany; use CloudCreativity\LaravelJsonApi\Pagination\StandardStrategy; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class FoodAdapter extends AbstractAdapter @@ -30,7 +31,7 @@ class FoodAdapter extends AbstractAdapter */ public function __construct(StandardStrategy $paging) { - parent::__construct(new \App\Models\Food(), $paging); + parent::__construct(new Food(), $paging); } /** @@ -48,4 +49,12 @@ class FoodAdapter extends AbstractAdapter } } + /** + * Tag relationships. + */ + protected function tags(): HasMany + { + return $this->hasMany(); + } + } diff --git a/app/JsonApi/Adapters/JournalEntryAdapter.php b/app/JsonApi/Adapters/JournalEntryAdapter.php index 8a686a2..b049ee9 100644 --- a/app/JsonApi/Adapters/JournalEntryAdapter.php +++ b/app/JsonApi/Adapters/JournalEntryAdapter.php @@ -2,6 +2,7 @@ namespace App\JsonApi\Adapters; +use App\Models\JournalEntry; use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter; use CloudCreativity\LaravelJsonApi\Eloquent\BelongsTo; use CloudCreativity\LaravelJsonApi\Eloquent\MorphHasMany; @@ -31,7 +32,7 @@ class JournalEntryAdapter extends AbstractAdapter */ public function __construct(StandardStrategy $paging) { - parent::__construct(new \App\Models\JournalEntry(), $paging); + parent::__construct(new JournalEntry(), $paging); } /** diff --git a/app/JsonApi/Adapters/RecipeAdapter.php b/app/JsonApi/Adapters/RecipeAdapter.php index 256935e..1c4846b 100644 --- a/app/JsonApi/Adapters/RecipeAdapter.php +++ b/app/JsonApi/Adapters/RecipeAdapter.php @@ -2,6 +2,7 @@ namespace App\JsonApi\Adapters; +use App\Models\Recipe; use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter; use CloudCreativity\LaravelJsonApi\Eloquent\HasMany; use CloudCreativity\LaravelJsonApi\Eloquent\MorphHasMany; @@ -31,7 +32,7 @@ class RecipeAdapter extends AbstractAdapter */ public function __construct(StandardStrategy $paging) { - parent::__construct(new \App\Models\Recipe(), $paging); + parent::__construct(new Recipe(), $paging); } /** @@ -58,4 +59,12 @@ class RecipeAdapter extends AbstractAdapter return $this->hasMany(); } + /** + * Tag relationships. + */ + protected function tags(): HasMany + { + return $this->hasMany(); + } + } diff --git a/app/JsonApi/Adapters/RecipeStepAdapter.php b/app/JsonApi/Adapters/RecipeStepAdapter.php index 0271cb5..083b4d7 100644 --- a/app/JsonApi/Adapters/RecipeStepAdapter.php +++ b/app/JsonApi/Adapters/RecipeStepAdapter.php @@ -2,10 +2,10 @@ namespace App\JsonApi\Adapters; +use App\Models\RecipeStep; use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter; use CloudCreativity\LaravelJsonApi\Eloquent\BelongsTo; use CloudCreativity\LaravelJsonApi\Pagination\StandardStrategy; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class RecipeStepAdapter extends AbstractAdapter @@ -31,7 +31,7 @@ class RecipeStepAdapter extends AbstractAdapter */ public function __construct(StandardStrategy $paging) { - parent::__construct(new \App\Models\RecipeStep(), $paging); + parent::__construct(new RecipeStep(), $paging); } /** diff --git a/app/JsonApi/Adapters/TagAdapter.php b/app/JsonApi/Adapters/TagAdapter.php new file mode 100644 index 0000000..8ff536b --- /dev/null +++ b/app/JsonApi/Adapters/TagAdapter.php @@ -0,0 +1,44 @@ +filterWithScopes($query, $filters); + } + +} diff --git a/app/JsonApi/Adapters/UserAdapter.php b/app/JsonApi/Adapters/UserAdapter.php index 16d9e90..9da07f1 100644 --- a/app/JsonApi/Adapters/UserAdapter.php +++ b/app/JsonApi/Adapters/UserAdapter.php @@ -2,6 +2,7 @@ namespace App\JsonApi\Adapters; +use App\Models\User; use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter; use CloudCreativity\LaravelJsonApi\Pagination\StandardStrategy; use Illuminate\Support\Collection; @@ -29,7 +30,7 @@ class UserAdapter extends AbstractAdapter */ public function __construct(StandardStrategy $paging) { - parent::__construct(new \App\Models\User(), $paging); + parent::__construct(new User(), $paging); } /** diff --git a/app/JsonApi/Schemas/FoodSchema.php b/app/JsonApi/Schemas/FoodSchema.php index 10a8305..3c86b5f 100644 --- a/app/JsonApi/Schemas/FoodSchema.php +++ b/app/JsonApi/Schemas/FoodSchema.php @@ -8,26 +8,22 @@ class FoodSchema extends SchemaProvider { /** - * @var string + * {@inheritdoc} */ protected $resourceType = 'foods'; /** - * @param \App\Models\Food $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\Food $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'name' => $resource->name, @@ -47,4 +43,21 @@ class FoodSchema extends SchemaProvider 'updatedAt' => $resource->updated_at, ]; } + + /** + * @inheritdoc + */ + public function getRelationships($resource, $isPrimary, array $includeRelationships): array + { + return [ + 'tags' => [ + self::SHOW_SELF => true, + self::SHOW_RELATED => true, + self::SHOW_DATA => isset($includeRelationships['tags']), + self::DATA => function () use ($resource) { + return $resource->tags; + }, + ] + ]; + } } diff --git a/app/JsonApi/Schemas/IngredientAmountSchema.php b/app/JsonApi/Schemas/IngredientAmountSchema.php index d832ca8..234a7b3 100644 --- a/app/JsonApi/Schemas/IngredientAmountSchema.php +++ b/app/JsonApi/Schemas/IngredientAmountSchema.php @@ -8,26 +8,22 @@ class IngredientAmountSchema extends SchemaProvider { /** - * @var string + * {@inheritdoc} */ protected $resourceType = 'ingredient-amounts'; /** - * @param \App\Models\IngredientAmount $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\IngredientAmount $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'amount' => $resource->amount, diff --git a/app/JsonApi/Schemas/JournalEntrySchema.php b/app/JsonApi/Schemas/JournalEntrySchema.php index 9d1a54e..bf6c391 100644 --- a/app/JsonApi/Schemas/JournalEntrySchema.php +++ b/app/JsonApi/Schemas/JournalEntrySchema.php @@ -8,26 +8,22 @@ class JournalEntrySchema extends SchemaProvider { /** - * @var string + * {@inheritdoc} */ protected $resourceType = 'journal-entries'; /** - * @param \App\Models\JournalEntry $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\JournalEntry $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'calories' => $resource->calories, diff --git a/app/JsonApi/Schemas/RecipeSchema.php b/app/JsonApi/Schemas/RecipeSchema.php index 83626da..6141be1 100644 --- a/app/JsonApi/Schemas/RecipeSchema.php +++ b/app/JsonApi/Schemas/RecipeSchema.php @@ -2,7 +2,6 @@ namespace App\JsonApi\Schemas; -use CloudCreativity\LaravelJsonApi\Eloquent\HasMany; use Neomerx\JsonApi\Schema\SchemaProvider; class RecipeSchema extends SchemaProvider @@ -14,21 +13,17 @@ class RecipeSchema extends SchemaProvider protected $resourceType = 'recipes'; /** - * @param \App\Models\Recipe $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\Recipe $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'name' => $resource->name, @@ -58,6 +53,14 @@ class RecipeSchema extends SchemaProvider public function getRelationships($resource, $isPrimary, array $includeRelationships): array { return [ + 'ingredient-amounts' => [ + self::SHOW_SELF => true, + self::SHOW_RELATED => true, + self::SHOW_DATA => isset($includeRelationships['ingredient-amounts']), + self::DATA => function () use ($resource) { + return $resource->ingredientAmounts; + }, + ], 'steps' => [ self::SHOW_SELF => true, self::SHOW_RELATED => true, @@ -66,12 +69,12 @@ class RecipeSchema extends SchemaProvider return $resource->steps; }, ], - 'ingredient-amounts' => [ + 'tags' => [ self::SHOW_SELF => true, self::SHOW_RELATED => true, - self::SHOW_DATA => isset($includeRelationships['ingredient-amounts']), + self::SHOW_DATA => isset($includeRelationships['tags']), self::DATA => function () use ($resource) { - return $resource->ingredientAmounts; + return $resource->tags; }, ] ]; diff --git a/app/JsonApi/Schemas/RecipeStepSchema.php b/app/JsonApi/Schemas/RecipeStepSchema.php index d00a37f..1c856ff 100644 --- a/app/JsonApi/Schemas/RecipeStepSchema.php +++ b/app/JsonApi/Schemas/RecipeStepSchema.php @@ -8,26 +8,22 @@ class RecipeStepSchema extends SchemaProvider { /** - * @var string + * {@inheritdoc} */ protected $resourceType = 'recipe-steps'; /** - * @param \App\Models\RecipeStep $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\RecipeStep $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'number' => $resource->number, diff --git a/app/JsonApi/Schemas/TagSchema.php b/app/JsonApi/Schemas/TagSchema.php new file mode 100644 index 0000000..89f82e4 --- /dev/null +++ b/app/JsonApi/Schemas/TagSchema.php @@ -0,0 +1,34 @@ +getRouteKey(); + } + + /** + * {@inheritdoc} + */ + public function getAttributes($resource): array + { + return [ + 'name' => $resource->name, + 'slug' => $resource->slug, + ]; + } + +} diff --git a/app/JsonApi/Schemas/UserSchema.php b/app/JsonApi/Schemas/UserSchema.php index df8bdd7..383af76 100644 --- a/app/JsonApi/Schemas/UserSchema.php +++ b/app/JsonApi/Schemas/UserSchema.php @@ -8,26 +8,22 @@ class UserSchema extends SchemaProvider { /** - * @var string + * {@inheritdoc} */ protected $resourceType = 'users'; /** - * @param \App\Models\User $resource - * the domain record being serialized. - * @return string + * {@inheritdoc} */ - public function getId($resource) + public function getId($resource): string { return (string) $resource->getRouteKey(); } /** - * @param \App\Models\User $resource - * the domain record being serialized. - * @return array + * {@inheritdoc} */ - public function getAttributes($resource) + public function getAttributes($resource): array { return [ 'name' => $resource->name, diff --git a/app/Models/Food.php b/app/Models/Food.php index 1bf1b9c..1061d0d 100644 --- a/app/Models/Food.php +++ b/app/Models/Food.php @@ -9,6 +9,7 @@ use App\Support\Number; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Spatie\Tags\HasTags; /** * App\Models\Food @@ -57,10 +58,17 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property-read int|null $ingredient_amounts_count * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountChildren * @property-read int|null $ingredient_amount_children_count + * @property-read string $type + * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags + * @property-read int|null $tags_count + * @method static \Illuminate\Database\Eloquent\Builder|Food withAllTags($tags, ?string $type = null) + * @method static \Illuminate\Database\Eloquent\Builder|Food withAllTagsOfAnyType($tags) + * @method static \Illuminate\Database\Eloquent\Builder|Food withAnyTags($tags, ?string $type = null) + * @method static \Illuminate\Database\Eloquent\Builder|Food withAnyTagsOfAnyType($tags) */ class Food extends Model { - use HasFactory, Ingredient, Journalable, Sluggable; + use HasFactory, HasTags, Ingredient, Journalable, Sluggable; /** * @inheritdoc diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php index 61f92e4..05fa598 100644 --- a/app/Models/Recipe.php +++ b/app/Models/Recipe.php @@ -9,6 +9,7 @@ use App\Models\Traits\Sluggable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; +use Spatie\Tags\HasTags; /** * App\Models\Recipe @@ -44,10 +45,17 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property-read int|null $ingredients_count * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\IngredientAmount[] $ingredientAmountChildren * @property-read int|null $ingredient_amount_children_count + * @property-read string $type + * @property \Illuminate\Database\Eloquent\Collection|\Spatie\Tags\Tag[] $tags + * @property-read int|null $tags_count + * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAllTags($tags, ?string $type = null) + * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAllTagsOfAnyType($tags) + * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAnyTags($tags, ?string $type = null) + * @method static \Illuminate\Database\Eloquent\Builder|Recipe withAnyTagsOfAnyType($tags) */ class Recipe extends Model { - use HasFactory, HasIngredients, Ingredient, Journalable, Sluggable; + use HasFactory, HasIngredients, HasTags, Ingredient, Journalable, Sluggable; /** * @inheritdoc diff --git a/composer.json b/composer.json index d98ae30..64c3bb2 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.12", "laravel/tinker": "^2.5", - "phospr/fraction": "^1.2" + "phospr/fraction": "^1.2", + "spatie/laravel-tags": "^3.0" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.9", diff --git a/composer.lock b/composer.lock index f1da4ca..31e6b4e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8c586d88695c23a7dde90bdc6994c13f", + "content-hash": "346f8fdf213e965dba75a3adbcd0c247", "packages": [ { "name": "asm89/stack-cors", @@ -2871,6 +2871,224 @@ ], "time": "2020-08-18T17:17:46+00:00" }, + { + "name": "spatie/eloquent-sortable", + "version": "3.11.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/eloquent-sortable.git", + "reference": "b06fa886559f8d40e31c8a69fd32bd45401dc5da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/eloquent-sortable/zipball/b06fa886559f8d40e31c8a69fd32bd45401dc5da", + "reference": "b06fa886559f8d40e31c8a69fd32bd45401dc5da", + "shasum": "" + }, + "require": { + "illuminate/database": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.3|^8.0" + }, + "require-dev": { + "orchestra/testbench": "^4.0|^5.0|^6.0", + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\EloquentSortable\\EloquentSortableServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\EloquentSortable\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be" + } + ], + "description": "Sortable behaviour for eloquent models", + "homepage": "https://github.com/spatie/eloquent-sortable", + "keywords": [ + "behaviour", + "eloquent", + "laravel", + "model", + "sort", + "sortable" + ], + "support": { + "issues": "https://github.com/spatie/eloquent-sortable/issues", + "source": "https://github.com/spatie/eloquent-sortable/tree/3.11.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2021-01-18T00:32:12+00:00" + }, + { + "name": "spatie/laravel-tags", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-tags.git", + "reference": "164cd45e2798ceba954f5419073de183b5a1df5f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-tags/zipball/164cd45e2798ceba954f5419073de183b5a1df5f", + "reference": "164cd45e2798ceba954f5419073de183b5a1df5f", + "shasum": "" + }, + "require": { + "laravel/framework": "^8.0", + "php": "^7.4|^8.0", + "spatie/eloquent-sortable": "^3.5", + "spatie/laravel-translatable": "^4.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "orchestra/testbench": "^6.0", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Tags\\TagsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\Tags\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Add tags and taggable behaviour to your Laravel app", + "homepage": "https://github.com/spatie/laravel-tags", + "keywords": [ + "laravel-tags", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-tags/issues", + "source": "https://github.com/spatie/laravel-tags/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2020-12-29T08:54:02+00:00" + }, + { + "name": "spatie/laravel-translatable", + "version": "4.6.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-translatable.git", + "reference": "5900d6002a5795712058a04c7ca7c2c44b3e0850" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/5900d6002a5795712058a04c7ca7c2c44b3e0850", + "reference": "5900d6002a5795712058a04c7ca7c2c44b3e0850", + "shasum": "" + }, + "require": { + "illuminate/database": "^6.0|^7.0|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "php": "^7.2|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.4", + "orchestra/testbench": "^4.0|^5.0|^6.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Translatable\\TranslatableServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\Translatable\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Sebastian De Deyne", + "email": "sebastian@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Mohamed Said", + "email": "theMohamedSaid@gmail.com", + "role": "Original idea" + } + ], + "description": "A trait to make an Eloquent model hold translations", + "homepage": "https://github.com/spatie/laravel-translatable", + "keywords": [ + "eloquent", + "i8n", + "laravel-translatable", + "model", + "multilingual", + "spatie", + "translate" + ], + "support": { + "issues": "https://github.com/spatie/laravel-translatable/issues", + "source": "https://github.com/spatie/laravel-translatable/tree/4.6.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2020-11-19T14:19:29+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.2.4", diff --git a/config/json-api-v1.php b/config/json-api-v1.php index bb69349..1043ce4 100644 --- a/config/json-api-v1.php +++ b/config/json-api-v1.php @@ -71,6 +71,7 @@ return [ 'journal-entries' => \App\Models\JournalEntry::class, 'recipes' => \App\Models\Recipe::class, 'recipe-steps' => \App\Models\RecipeStep::class, + 'tags' => \Spatie\Tags\Tag::class, 'users' => \App\Models\User::class, ], diff --git a/database/migrations/2021_01_23_191532_create_tag_tables.php b/database/migrations/2021_01_23_191532_create_tag_tables.php new file mode 100644 index 0000000..3e563df --- /dev/null +++ b/database/migrations/2021_01_23_191532_create_tag_tables.php @@ -0,0 +1,32 @@ +id(); + $table->json('name'); + $table->json('slug'); + $table->string('type')->nullable(); + $table->integer('order_column')->nullable(); + $table->timestamps(); + }); + + Schema::create('taggables', function (Blueprint $table) { + $table->foreignId('tag_id')->constrained()->cascadeOnDelete(); + $table->morphs('taggable'); + $table->unique(['tag_id', 'taggable_id', 'taggable_type']); + }); + } + + public function down() + { + Schema::drop('taggables'); + Schema::drop('tags'); + } +} diff --git a/routes/api.php b/routes/api.php index ee5ef9a..beec9ea 100644 --- a/routes/api.php +++ b/routes/api.php @@ -12,7 +12,9 @@ */ JsonApi::register('v1')->routes(function ($api) { - $api->resource('foods')->readOnly(); + $api->resource('foods')->relationships(function ($relations) { + $relations->hasMany('tags')->readOnly(); + })->readOnly(); $api->resource('ingredient-amounts')->relationships(function ($relations) { $relations->hasOne('ingredient')->readOnly(); $relations->hasOne('parent')->readOnly(); @@ -23,12 +25,14 @@ JsonApi::register('v1')->routes(function ($api) { $relations->hasOne('user')->readOnly(); })->readOnly(); $api->resource('recipes')->relationships(function ($relations) { - $relations->hasMany('steps')->readOnly(); $relations->hasMany('ingredient-amounts')->readOnly(); + $relations->hasMany('steps')->readOnly(); + $relations->hasMany('tags')->readOnly(); })->readOnly(); $api->resource('recipe-steps')->relationships(function ($relations) { $relations->hasOne('recipe')->readOnly(); })->readOnly(); + $api->resource('tags')->readOnly(); // $api->resource('users')->relationships(function ($relations) { // $relations->hasMany('journal-entries')->readOnly(); // })->readOnly();