Skip to content

Commit 3318d5b

Browse files
committed
Fix ingredient matching when multiple complex ingredients match #481
1 parent 6970cb1 commit 3318d5b

File tree

2 files changed

+28
-20
lines changed

2 files changed

+28
-20
lines changed

app/Services/CocktailService.php

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,25 @@ public function getCocktailsByIngredients(array $ingredientIds, int $barId, ?int
243243
// Basically, goes through all ingredients to match ($ingredientIds) and check if they can create complex ingredients
244244
// If they can, that ingredient is added to the list of ingredients to match
245245
if ($matchComplexIngredients) {
246-
$placeholders = str_repeat('?,', count($ingredientIds) - 1) . '?';
247-
$rawQuery = "WITH RECURSIVE IngredientChain AS (
248-
SELECT id AS matched_ingredient
249-
FROM ingredients
250-
WHERE id IN (" . $placeholders . ")
251-
UNION
252-
SELECT ci.main_ingredient_id AS matched_ingredient
253-
FROM complex_ingredients ci
254-
INNER JOIN IngredientChain ic ON ci.ingredient_id = ic.matched_ingredient
255-
)
256-
SELECT DISTINCT matched_ingredient
257-
FROM IngredientChain;";
258-
259-
$additionalIngredients = collect($this->db->select($rawQuery, $ingredientIds))->pluck('matched_ingredient');
260-
$ingredientIds = array_merge($ingredientIds, $additionalIngredients->toArray());
246+
$additionalIngredients = $this->db->table('complex_ingredients AS ci')
247+
->distinct()
248+
->select('ci.main_ingredient_id')
249+
->join('ingredients AS i_main', 'ci.main_ingredient_id', '=', 'i_main.id')
250+
->whereIn('ci.id', function ($query) use ($ingredientIds) {
251+
$query->select('ci_inner.id')
252+
->from('complex_ingredients AS ci_inner')
253+
->whereNotExists(function ($query) use ($ingredientIds) {
254+
$query->select('i_ingredient.id')
255+
->from('complex_ingredients AS ci_sub')
256+
->join('ingredients AS i_ingredient', 'ci_sub.ingredient_id', '=', 'i_ingredient.id')
257+
->whereColumn('ci_sub.main_ingredient_id', 'ci_inner.main_ingredient_id')
258+
->whereNotIn('i_ingredient.id', $ingredientIds);
259+
});
260+
})
261+
->pluck('main_ingredient_id')
262+
->toArray();
263+
264+
$ingredientIds = array_merge($ingredientIds, $additionalIngredients);
261265
$ingredientIds = array_unique($ingredientIds);
262266
}
263267

tests/Feature/Repository/CocktailRepositoryTest.php renamed to tests/Feature/Services/CocktailServiceTest.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace Tests\Feature\Repository;
5+
namespace Tests\Feature\Services;
66

77
use Tests\TestCase;
88
use Kami\Cocktail\Models\Cocktail;
@@ -13,7 +13,7 @@
1313
use Illuminate\Foundation\Testing\RefreshDatabase;
1414
use Kami\Cocktail\Models\CocktailIngredientSubstitute;
1515

16-
class CocktailRepositoryTest extends TestCase
16+
class CocktailServiceTest extends TestCase
1717
{
1818
use RefreshDatabase;
1919

@@ -186,10 +186,14 @@ public function test_gets_cocktails_that_can_be_made_with_complex_ingredients():
186186

187187
$whiskey = Ingredient::factory()->for($membership->bar)->create();
188188
$gin = Ingredient::factory()->for($membership->bar)->create();
189-
$lemon = Ingredient::factory()->for($membership->bar)->create();
189+
$lemonJuicePart1 = Ingredient::factory()->for($membership->bar)->create();
190+
$lemonJuicePart2 = Ingredient::factory()->for($membership->bar)->create();
191+
$lemonJuicePart3 = Ingredient::factory()->for($membership->bar)->create();
190192
$lemonJuice = Ingredient::factory()
191193
->for($membership->bar)
192-
->has(ComplexIngredient::factory()->for($lemon), 'ingredientParts')
194+
->has(ComplexIngredient::factory()->for($lemonJuicePart1), 'ingredientParts')
195+
->has(ComplexIngredient::factory()->for($lemonJuicePart2), 'ingredientParts')
196+
->has(ComplexIngredient::factory()->for($lemonJuicePart3), 'ingredientParts')
193197
->create();
194198

195199
Cocktail::factory()
@@ -232,7 +236,7 @@ public function test_gets_cocktails_that_can_be_made_with_complex_ingredients():
232236
Cocktail::factory()->recycle($membership->bar)->count(10)->create();
233237

234238
$repository = resolve(CocktailService::class);
235-
$cocktails = $repository->getCocktailsByIngredients([$gin->id, $lemon->id], $membership->bar_id);
239+
$cocktails = $repository->getCocktailsByIngredients([$gin->id, $lemonJuicePart1->id, $lemonJuicePart2->id, $lemonJuicePart3->id], $membership->bar_id);
236240

237241
$this->assertSame([1], $cocktails->toArray());
238242
}

0 commit comments

Comments
 (0)