Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
18 / 21
72.73% covered (warning)
72.73%
8 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
FeatureService
85.71% covered (warning)
85.71%
18 / 21
72.73% covered (warning)
72.73%
8 / 11
12.42
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAll
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getAllActive
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getById
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getByKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 create
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 update
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 delete
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getValueTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCategories
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 invalidateCache
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\Feature;
6use App\Http\Repositories\interfaces\IFeatureRepository;
7use Illuminate\Support\Collection;
8use Illuminate\Support\Facades\Cache;
9
10/**
11 * Service for feature business logic.
12 *
13 * This service handles all business logic related to features,
14 * coordinating with the repository for data access.
15 */
16class FeatureService
17{
18    /**
19     * Cache key for all features.
20     */
21    private const CACHE_KEY_ALL = 'features:all';
22
23    /**
24     * Cache TTL in seconds (1 hour).
25     */
26    private const CACHE_TTL = 3600;
27
28    public function __construct(
29        private IFeatureRepository $featureRepository
30    ) {}
31
32    /**
33     * Get all features with optional category filtering.
34     *
35     * @param  string|null  $category  Optional category to filter by
36     * @return Collection<int, Feature> Collection of features
37     */
38    public function getAll(?string $category = null): Collection
39    {
40        if ($category) {
41            // Don't cache filtered results
42            return $this->featureRepository->getAll($category);
43        }
44
45        return Cache::remember(self::CACHE_KEY_ALL, self::CACHE_TTL, function () {
46            return $this->featureRepository->getAll();
47        });
48    }
49
50    /**
51     * Get all active features.
52     *
53     * @param  string|null  $category  Optional category to filter by
54     * @return Collection<int, Feature> Collection of active features
55     */
56    public function getAllActive(?string $category = null): Collection
57    {
58        return $this->featureRepository->getAllActive($category);
59    }
60
61    /**
62     * Get a feature by its ID.
63     *
64     * @param  string  $id  The feature ID
65     * @return Feature|null The feature or null if not found
66     */
67    public function getById(string $id): ?Feature
68    {
69        return $this->featureRepository->findById($id);
70    }
71
72    /**
73     * Get a feature by its key.
74     *
75     * @param  string  $key  The feature key
76     * @return Feature|null The feature or null if not found
77     */
78    public function getByKey(string $key): ?Feature
79    {
80        return $this->featureRepository->findByKey($key);
81    }
82
83    /**
84     * Create a new feature.
85     *
86     * @param  array{
87     *     key: string,
88     *     name: string,
89     *     description?: string|null,
90     *     value_type: string,
91     *     category: string,
92     *     default_value?: mixed,
93     *     is_active?: bool,
94     *     display_order?: int
95     * }  $data  The feature data
96     * @return Feature The created feature
97     */
98    public function create(array $data): Feature
99    {
100        $feature = $this->featureRepository->create($data);
101
102        $this->invalidateCache();
103
104        return $feature;
105    }
106
107    /**
108     * Update an existing feature.
109     *
110     * @param  Feature  $feature  The feature to update
111     * @param  array{
112     *     key?: string,
113     *     name?: string,
114     *     description?: string|null,
115     *     value_type?: string,
116     *     category?: string,
117     *     default_value?: mixed,
118     *     is_active?: bool,
119     *     display_order?: int
120     * }  $data  The update data
121     * @return Feature The updated feature
122     */
123    public function update(Feature $feature, array $data): Feature
124    {
125        $feature = $this->featureRepository->update($feature, $data);
126
127        $this->invalidateCache();
128
129        return $feature;
130    }
131
132    /**
133     * Delete a feature.
134     *
135     * @param  Feature  $feature  The feature to delete
136     * @return bool True if deleted successfully
137     */
138    public function delete(Feature $feature): bool
139    {
140        $result = $this->featureRepository->delete($feature);
141
142        $this->invalidateCache();
143
144        return $result;
145    }
146
147    /**
148     * Get all available value types.
149     *
150     * @return array<string> Array of value types
151     */
152    public function getValueTypes(): array
153    {
154        return Feature::VALUE_TYPES;
155    }
156
157    /**
158     * Get all available categories.
159     *
160     * @return array<string> Array of categories
161     */
162    public function getCategories(): array
163    {
164        return Feature::CATEGORIES;
165    }
166
167    /**
168     * Invalidate feature caches.
169     */
170    public function invalidateCache(): void
171    {
172        Cache::forget(self::CACHE_KEY_ALL);
173    }
174}