diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index fd6a6a3e..2a0dccb3 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -20,13 +20,15 @@
-
-
+
+
+
-
-
+
+
+
diff --git a/tests/Stubs/Models/Article.php b/tests/Stubs/Models/Article.php
index eb0aed22..6d4f9891 100644
--- a/tests/Stubs/Models/Article.php
+++ b/tests/Stubs/Models/Article.php
@@ -17,6 +17,7 @@
use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\MorphMany;
/**
* @method static ArticleEloquentBuilder query()
@@ -48,4 +49,9 @@ public function newEloquentBuilder($query): ArticleEloquentBuilder
{
return new ArticleEloquentBuilder($query);
}
+
+ public function morphableEntities(): MorphMany
+ {
+ return $this->morphMany(MorphableEntity::class, 'morphable');
+ }
}
diff --git a/tests/Stubs/Models/MorphableEntity.php b/tests/Stubs/Models/MorphableEntity.php
new file mode 100644
index 00000000..138106ee
--- /dev/null
+++ b/tests/Stubs/Models/MorphableEntity.php
@@ -0,0 +1,42 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Cog\Tests\Laravel\Love\Stubs\Models;
+
+use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableInterface;
+use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+final class MorphableEntity extends Model implements
+ ReactableInterface
+{
+ use HasFactory;
+ use Reactable;
+
+ /**
+ * The table associated with the model.
+ *
+ * @var string
+ */
+ protected $table = 'morphable_entities';
+
+ /**
+ * The attributes that are mass assignable.
+ *
+ * @var array
+ */
+ protected $fillable = [
+ 'name',
+ ];
+}
diff --git a/tests/Unit/Reactable/ReactableEloquentBuilderTraitTest.php b/tests/Unit/Reactable/ReactableEloquentBuilderTraitTest.php
index f00cb9b2..08d37917 100644
--- a/tests/Unit/Reactable/ReactableEloquentBuilderTraitTest.php
+++ b/tests/Unit/Reactable/ReactableEloquentBuilderTraitTest.php
@@ -17,6 +17,8 @@
use Cog\Laravel\Love\Reaction\Models\Reaction;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Cog\Tests\Laravel\Love\Stubs\Models\Article;
+use Cog\Tests\Laravel\Love\Stubs\Models\Entity;
+use Cog\Tests\Laravel\Love\Stubs\Models\MorphableEntity;
use Cog\Tests\Laravel\Love\Stubs\Models\User;
use Cog\Tests\Laravel\Love\TestCase;
use Illuminate\Support\Str;
@@ -1140,4 +1142,80 @@ public function it_can_chain_multiple_join_reaction_counter_of_type_with_custom_
];
})->toArray());
}
+
+ /** @test */
+ public function it_breaks_when_join_reaction_counter_with_type_is_used_with_count_on_morphables(): void
+ {
+ Reactant::factory()->create(); // Needed to have not same ids with Reactant
+
+ $reactionType1 = ReactionType::factory()->create([
+ 'name' => 'Like',
+ 'mass' => 2,
+ ]);
+ $reactionType2 = ReactionType::factory()->create([
+ 'mass' => 1,
+ ]);
+ $reactable1 = Article::factory()->has(MorphableEntity::factory()->count(3))->create();
+ $reactable2 = Article::factory()->has(MorphableEntity::factory()->count(2))->create();
+ $reactable3 = Article::factory()->has(MorphableEntity::factory()->count(4))->create();
+ Reaction::factory()->count(2)->create([
+ 'reaction_type_id' => $reactionType1->getId(),
+ 'reactant_id' => $reactable1->getLoveReactant()->getId(),
+ ]);
+ Reaction::factory()->count(3)->create([
+ 'reaction_type_id' => $reactionType1->getId(),
+ 'reactant_id' => $reactable2->getLoveReactant()->getId(),
+ ]);
+ Reaction::factory()->count(1)->create([
+ 'reaction_type_id' => $reactionType1->getId(),
+ 'reactant_id' => $reactable3->getLoveReactant()->getId(),
+ ]);
+ Reaction::factory()->count(4)->create([
+ 'reaction_type_id' => $reactionType2->getId(),
+ 'reactant_id' => $reactable1->getLoveReactant()->getId(),
+ ]);
+ Reaction::factory()->count(5)->create([
+ 'reaction_type_id' => $reactionType2->getId(),
+ 'reactant_id' => $reactable2->getLoveReactant()->getId(),
+ ]);
+ Reaction::factory()->count(6)->create([
+ 'reaction_type_id' => $reactionType2->getId(),
+ 'reactant_id' => $reactable3->getLoveReactant()->getId(),
+ ]);
+
+ $reactionType1CountKey = 'reaction_' . Str::snake($reactionType1->getName()) . '_count';
+ $reactionType1WeightKey = 'reaction_' . Str::snake($reactionType1->getName()) . '_weight';
+
+ $reactablesOrderedAsc = Article::query()
+ ->withCount(['morphableEntities'])
+ ->joinReactionCounterOfType($reactionType1->getName())
+ ->orderBy($reactionType1CountKey, 'asc')
+ ->get();
+
+ $reactablesOrderedDesc = Article::query()
+ ->joinReactionCounterOfType($reactionType1->getName())
+ ->orderBy($reactionType1CountKey, 'desc')
+ ->get();
+
+ $assertAsc = [
+ ['name' => $reactable3->name, "$reactionType1CountKey" => 1, "$reactionType1WeightKey" => 2],
+ ['name' => $reactable1->name, "$reactionType1CountKey" => 2, "$reactionType1WeightKey" => 4],
+ ['name' => $reactable2->name, "$reactionType1CountKey" => 3, "$reactionType1WeightKey" => 6],
+ ];
+ $assertDesc = array_reverse($assertAsc);
+ $this->assertEquals($assertAsc, $reactablesOrderedAsc->map(function (Article $reactable) use ($reactionType1CountKey, $reactionType1WeightKey) {
+ return [
+ 'name' => $reactable->getAttributeValue('name'),
+ "$reactionType1CountKey" => $reactable->{$reactionType1CountKey},
+ "$reactionType1WeightKey" => $reactable->{$reactionType1WeightKey},
+ ];
+ })->toArray());
+ $this->assertEquals($assertDesc, $reactablesOrderedDesc->map(function (Article $reactable) use ($reactionType1CountKey, $reactionType1WeightKey) {
+ return [
+ 'name' => $reactable->getAttributeValue('name'),
+ "$reactionType1CountKey" => $reactable->{$reactionType1CountKey},
+ "$reactionType1WeightKey" => $reactable->{$reactionType1WeightKey},
+ ];
+ })->toArray());
+ }
}
diff --git a/tests/database/factories/MorphableEntityFactory.php b/tests/database/factories/MorphableEntityFactory.php
new file mode 100644
index 00000000..6e03962c
--- /dev/null
+++ b/tests/database/factories/MorphableEntityFactory.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Cog\Tests\Laravel\Love\Database\Factories;
+
+use Cog\Tests\Laravel\Love\Stubs\Models\MorphableEntity;
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+final class MorphableEntityFactory extends Factory
+{
+ protected $model = MorphableEntity::class;
+
+ /**
+ * Define the model's default state.
+ *
+ * @return array
+ */
+ public function definition(): array
+ {
+ return [
+ 'name' => $this->faker->name(),
+ ];
+ }
+}
diff --git a/tests/database/migrations/2016_09_02_173301_create_morphable_entities_table.php b/tests/database/migrations/2016_09_02_173301_create_morphable_entities_table.php
new file mode 100644
index 00000000..24623da9
--- /dev/null
+++ b/tests/database/migrations/2016_09_02_173301_create_morphable_entities_table.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+ public function up(): void
+ {
+ Schema::create('morphable_entities', function (Blueprint $table) {
+ $table->increments('id');
+ $table->morphs('morphable');
+ $table->unsignedBigInteger('love_reactant_id')->nullable();
+ $table->string('name');
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('morphable_entities');
+ }
+};