Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
AddOnsService
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
2 / 2
2
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getYearlyForProduct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Http\Services;
4
5use App\Http\Models\AddOns;
6use App\Http\Repositories\interfaces\IAddOnsRepository;
7use Illuminate\Support\Collection;
8
9/**
10 * Read-side service for AddOns catalog lookups.
11 *
12 * Separate from RoleplayAddonLifecycleService (which mutates user<->addon
13 * assignments). This service is intentionally thin; it exists so controllers
14 * never query models directly — see CLAUDE.MD (Controller → Service → Repository → Model).
15 */
16class AddOnsService
17{
18    public function __construct(
19        private readonly IAddOnsRepository $addOnsRepository,
20    ) {}
21
22    /**
23     * List yearly addons for a product, excluding a set of identifiers
24     * (typically freemium/promotional tiers that should not be exposed
25     * to admins for company-wide assignment).
26     *
27     * @param  string  $product  e.g. "RolePlay".
28     * @param  array<int, string>  $excludeIdentifiers  e.g. ["roleplay-beginner"].
29     * @return Collection<int, AddOns> Sorted by price ascending.
30     */
31    public function getYearlyForProduct(string $product, array $excludeIdentifiers = []): Collection
32    {
33        return $this->addOnsRepository->findYearlyByProduct($product, $excludeIdentifiers);
34    }
35}