diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php deleted file mode 100644 index 4b49134..0000000 --- a/.php-cs-fixer.php +++ /dev/null @@ -1,48 +0,0 @@ -setRules([ - '@PSR12' => true, - 'binary_operator_spaces' => true, - 'blank_line_after_opening_tag' => true, - 'compact_nullable_typehint' => true, - 'declare_equal_normalize' => true, - 'lowercase_cast' => true, - 'lowercase_static_reference' => true, - 'new_with_braces' => true, - 'no_blank_lines_after_class_opening' => true, - 'no_leading_import_slash' => true, - 'no_whitespace_in_blank_line' => true, - 'ordered_class_elements' => [ - 'order' => [ - 'use_trait', - ], - ], - 'ordered_imports' => [ - 'imports_order' => [ - 'class', - 'function', - 'const', - ], - 'sort_algorithm' => 'none', - ], - 'return_type_declaration' => true, - 'short_scalar_cast' => true, - 'single_blank_line_before_namespace' => true, - 'single_trait_insert_per_statement' => true, - 'ternary_operator_spaces' => true, - 'unary_operator_spaces' => true, - 'visibility_required' => [ - 'elements' => [ - 'const', - 'method', - 'property', - ], - ], - ]) - ->setFinder( - PhpCsFixer\Finder::create() - ->exclude('vendor') - ->in([__DIR__.'/src/', __DIR__.'/tests/']) - ) -; diff --git a/README.md b/README.md index c6d01e5..5ad7bdd 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ $post = $user->attachFavoriteStatus($post); ], ``` -#### For `Collection | Paginator | LengthAwarePaginator | array`: +#### For `Collection | Paginator | CursorPaginator | array`: ```php $posts = Post::oldest('id')->get(); diff --git a/composer.json b/composer.json index 7564db1..3e3edf1 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,9 @@ "mockery/mockery": "^1.4.4", "phpunit/phpunit": "^9.5.10", "orchestra/testbench": "^7.0", - "brainmaestro/composer-git-hooks": "^2.8", - "friendsofphp/php-cs-fixer": "^3.5" + "friendsofphp/php-cs-fixer": "^3.5", + "brainmaestro/composer-git-hooks": "dev-master", + "laravel/pint": "^1.2" }, "extra": { "laravel": { @@ -57,8 +58,8 @@ "cghooks update" ], "cghooks": "vendor/bin/cghooks", - "check-style": "php-cs-fixer fix --using-cache=no --diff --dry-run --ansi", - "fix-style": "php-cs-fixer fix --using-cache=no --ansi", + "check-style": "vendor/bin/pint --test", + "fix-style": "vendor/bin/pint", "test": "vendor/bin/phpunit --colors=always" }, "scripts-descriptions": { diff --git a/src/FavoriteServiceProvider.php b/src/FavoriteServiceProvider.php index ef83c15..b1fd8b2 100644 --- a/src/FavoriteServiceProvider.php +++ b/src/FavoriteServiceProvider.php @@ -9,22 +9,22 @@ class FavoriteServiceProvider extends ServiceProvider public function boot() { $this->publishes([ - \dirname(__DIR__) . '/config/favorite.php' => config_path('favorite.php'), + \dirname(__DIR__).'/config/favorite.php' => config_path('favorite.php'), ], 'favorite-config'); $this->publishes([ - \dirname(__DIR__) . '/migrations/' => database_path('migrations'), + \dirname(__DIR__).'/migrations/' => database_path('migrations'), ], 'favorite-migrations'); if ($this->app->runningInConsole()) { - $this->loadMigrationsFrom(\dirname(__DIR__) . '/migrations/'); + $this->loadMigrationsFrom(\dirname(__DIR__).'/migrations/'); } } public function register() { $this->mergeConfigFrom( - \dirname(__DIR__) . '/config/favorite.php', + \dirname(__DIR__).'/config/favorite.php', 'favorite' ); } diff --git a/src/Traits/Favoriter.php b/src/Traits/Favoriter.php index 4e2025f..3638b19 100644 --- a/src/Traits/Favoriter.php +++ b/src/Traits/Favoriter.php @@ -2,13 +2,11 @@ namespace Overtrue\LaravelFavorite\Traits; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Contracts\Pagination\CursorPaginator; -use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Contracts\Pagination\Paginator; use Illuminate\Database\Eloquent\Model; +use Illuminate\Pagination\AbstractCursorPaginator; +use Illuminate\Pagination\AbstractPaginator; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\LazyCollection; /** @@ -18,8 +16,8 @@ trait Favoriter { public function favorite(Model $object): void { - /* @var \Overtrue\LaravelFavorite\Traits\Favoriteable $object */ - if (!$this->hasFavorited($object)) { + /* @var \Overtrue\LaravelFavorite\Traits\Favoriteable|Model $object */ + if (! $this->hasFavorited($object)) { $favorite = app(config('favorite.favorite_model')); $favorite->{config('favorite.user_foreign_key')} = $this->getKey(); @@ -59,52 +57,45 @@ public function favorites(): \Illuminate\Database\Eloquent\Relations\HasMany return $this->hasMany(config('favorite.favorite_model'), config('favorite.user_foreign_key'), $this->getKeyName()); } - public function attachFavoriteStatus($favoriteables, callable $resolver = null) + public function attachFavoriteStatus(&$favoriteables, callable $resolver = null) { - $returnFirst = false; - $toArray = false; - - switch (true) { - case $favoriteables instanceof Model: - $returnFirst = true; - $favoriteables = \collect([$favoriteables]); - break; - case $favoriteables instanceof LengthAwarePaginator: - $favoriteables = $favoriteables->getCollection(); - break; - case $favoriteables instanceof Paginator: - case $favoriteables instanceof CursorPaginator: - $favoriteables = \collect($favoriteables->items()); - break; - case $favoriteables instanceof LazyCollection: - $favoriteables = \collect($favoriteables->all()); - break; - case \is_array($favoriteables): - $favoriteables = \collect($favoriteables); - $toArray = true; - break; - } - - \abort_if(!($favoriteables instanceof Enumerable), 422, 'Invalid $favoriteables type.'); - - $favorited = $this->favorites()->get()->keyBy(function ($item) { - return \sprintf('%s:%s', $item->favoriteable_type, $item->favoriteable_id); + $favorites = $this->favorites()->get()->keyBy(function ($item) { + return \sprintf('%s-%s', $item->favoriteable_type, $item->favoriteable_id); }); - $favoriteables->map(function ($favoriteable) use ($favorited, $resolver) { + $attachStatus = function ($favoriteable) use ($favorites, $resolver) { $resolver = $resolver ?? fn ($m) => $m; $favoriteable = $resolver($favoriteable); - if ($favoriteable && \in_array(Favoriteable::class, \class_uses_recursive($favoriteable))) { - $key = \sprintf('%s:%s', $favoriteable->getMorphClass(), $favoriteable->getKey()); - $favoriteable->setAttribute('has_favorited', $favorited->has($key)); + if (\in_array(Favoriteable::class, \class_uses($favoriteable))) { + $key = \sprintf('%s-%s', $favoriteable->getMorphClass(), $favoriteable->getKey()); + $favoriteable->setAttribute('has_favorited', $favorites->has($key)); } - }); - return $returnFirst ? $favoriteables->first() : ($toArray ? $favoriteables->all() : $favoriteables); + return $favoriteable; + }; + + switch (true) { + case $favoriteables instanceof Model: + return $attachStatus($favoriteables); + case $favoriteables instanceof Collection: + return $favoriteables->each($attachStatus); + case $favoriteables instanceof LazyCollection: + return $favoriteables = $favoriteables->map($attachStatus); + case $favoriteables instanceof AbstractPaginator: + case $favoriteables instanceof AbstractCursorPaginator: + return $favoriteables->through($attachStatus); + case $favoriteables instanceof Paginator: + // custom paginator will return a collection + return collect($favoriteables->items())->transform($attachStatus); + case \is_array($favoriteables): + return \collect($favoriteables)->transform($attachStatus); + default: + throw new \InvalidArgumentException('Invalid argument type.'); + } } - public function getFavoriteItems(string $model): Builder + public function getFavoriteItems(string $model) { return app($model)->whereHas( 'favoriters', diff --git a/tests/FeatureTest.php b/tests/FeatureTest.php index cd5bffb..e1deaf7 100644 --- a/tests/FeatureTest.php +++ b/tests/FeatureTest.php @@ -185,16 +185,52 @@ public function test_favoriter_can_attach_favorite_status_to_votable_collection( $user->favorite($post1); $user->favorite($post2); - // collection + // Model + $post1->refresh(); + $this->assertNull($post1['has_favorited']); + + $user->attachFavoriteStatus($post1); + $this->assertTrue($post1['has_favorited']); + + // Collection $posts = Post::oldest('id')->get(); + $this->assertSame($posts, $user->attachFavoriteStatus($posts)); + $this->assertTrue($posts[0]['has_favorited']); + $this->assertTrue($posts[1]['has_favorited']); + $this->assertFalse($posts[2]['has_favorited']); + + // LazyCollection + $posts = Post::oldest('id')->cursor(); $user->attachFavoriteStatus($posts); $posts = $posts->toArray(); + $this->assertTrue($posts[0]['has_favorited']); + $this->assertTrue($posts[1]['has_favorited']); + $this->assertFalse($posts[2]['has_favorited']); - // user has up favorited post1 + // Paginator + $posts = Post::oldest('id')->paginate(20); + $postsWithFavoriteStatus = $user->attachFavoriteStatus($posts); + $this->assertSame($posts, $postsWithFavoriteStatus); $this->assertTrue($posts[0]['has_favorited']); - // user has down favorited post2 $this->assertTrue($posts[1]['has_favorited']); - // user hasn't favorited post3 + $this->assertFalse($posts[2]['has_favorited']); + + // https://github.com/overtrue/laravel-favorite/issues/33 + $this->assertTrue(method_exists($postsWithFavoriteStatus, 'links')); + + // cursor paginator + $posts = Post::oldest('id')->cursorPaginate(20); + $this->assertSame($posts, $user->attachFavoriteStatus($posts)); + $this->assertTrue($posts[0]['has_favorited']); + $this->assertTrue($posts[1]['has_favorited']); + $this->assertFalse($posts[2]['has_favorited']); + + // array + $posts = Post::oldest('id')->get()->all(); + $posts = $user->attachFavoriteStatus($posts); + $this->assertTrue($posts[0]['has_favorited']); + $this->assertTrue($posts[1]['has_favorited']); + $this->assertFalse($posts[2]['has_favorited']); // paginator @@ -227,7 +263,7 @@ public function test_favoriter_can_attach_favorite_status_to_votable_collection( // custom resolver $posts = [['post' => $post1], ['post' => $post2], ['post' => $post3]]; - $posts = $user->attachFavoriteStatus($posts, fn ($i) => $i['post']); + $user->attachFavoriteStatus($posts, fn ($i) => $i['post']); // user has up favorited post1 $this->assertTrue($posts[0]['post']['has_favorited']); @@ -257,7 +293,6 @@ public function test_has_favorited() $this->assertDatabaseCount('favorites', 0); } - protected function getQueryLog(\Closure $callback): \Illuminate\Support\Collection { $sqls = \collect([]); diff --git a/tests/TestCase.php b/tests/TestCase.php index 9a7eded..8d9956e 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,8 +9,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase /** * Load package service provider. * - * @param \Illuminate\Foundation\Application $app - * + * @param \Illuminate\Foundation\Application $app * @return array */ protected function getPackageProviders($app) @@ -21,7 +20,7 @@ protected function getPackageProviders($app) /** * Define environment setup. * - * @param \Illuminate\Foundation\Application $app + * @param \Illuminate\Foundation\Application $app */ protected function getEnvironmentSetUp($app) {