Lines 53.84% 7 / 13
Methods 53.84% 7 / 13
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 register n/a 0 / 0 n/a 0 / 0 0
 boot 100.00% 1 / 1 100.00% 1 / 1 1
 provides 0.00% 0 / 1 0.00% 0 / 1 2
 isDeferred 100.00% 1 / 1 100.00% 1 / 1 1
 call 0.00% 0 / 1 0.00% 0 / 1 2
 make 100.00% 1 / 1 100.00% 1 / 1 1
 bind 0.00% 0 / 1 0.00% 0 / 1 2
 singleton 100.00% 1 / 1 100.00% 1 / 1 1
 instance 100.00% 1 / 1 100.00% 1 / 1 1
 alias 100.00% 1 / 1 100.00% 1 / 1 1
 when 0.00% 0 / 1 0.00% 0 / 1 2
 tag 0.00% 0 / 1 0.00% 0 / 1 2
 tagged 0.00% 0 / 1 0.00% 0 / 1 2
35abstract class ServiceProvider
36{
37    /**
38     * The container the provider registers services on.
39     */
40    protected Container $container;
41
42    /**
43     * Whether the provider is deferred (loaded lazily on first resolution of
44     * one of its {@see provides()} services).
45     *
46     * @var bool
47     */
48    protected bool $defer = false;
49
50    /**
51     * @param Container $container The container to register services on
52     */
53    public function __construct(Container $container)
54    {
55        $this->container = $container;
56    }
57
58    /**
59     * Register services with the container.
60     *
61     * Runs before anything is resolved, so only bindings should be declared
62     * here — never resolved.
63     *
64     * @return void
65     */
66    abstract public function register(): void;
67
68    /**
69     * Boot the provider after all providers have registered.
70     *
71     * Safe to resolve services here, because every binding now exists.
72     *
73     * @return void
74     */
75    public function boot(): void
76    {
77    }
78
79    /**
80     * The services this provider provides.
81     *
82     * Used for deferred loading: when one of these abstracts is resolved, the
83     * provider is loaded and registered.
84     *
85     * @return array<int, string> The provided service identifiers
86     */
87    public function provides(): array
88    {
89        return [];
90    }
91
92    /**
93     * Whether the provider is deferred.
94     *
95     * @return bool True if the provider loads lazily
96     */
97    public function isDeferred(): bool
98    {
99        return $this->defer;
100    }
101
102    /**
103     * Invoke a callable, resolving its parameters from the container.
104     *
105     * Internal helper for providers; passthrough to {@see Container::call()}.
106     *
107     * @param callable|string|array $callback The callable to invoke
108     * @param array $parameters Explicit values keyed by parameter name
109     * @param string|null $defaultMethod Method to invoke when $callback is an invokable class string
110     * @return mixed The callable's return value
111     */
112    protected function call(callable|string|array $callback, array $parameters = [], ?string $defaultMethod = null): mixed
113    {
114        return $this->container->call($callback, $parameters, $defaultMethod);
115    }
116
117    /**
118     * Resolve a service from the container, autowiring its dependencies.
119     *
120     * Internal helper for providers; passthrough to {@see Container::make()}.
121     *
122     * @param string $abstract Identifier (class name or alias) to resolve
123     * @param array $parameters Explicit values keyed by constructor parameter name
124     * @return mixed The resolved entry
125     */
126    protected function make(string $abstract, array $parameters = []): mixed
127    {
128        return $this->container->make($abstract, $parameters);
129    }
130
131    /**
132     * Register a non-shared binding.
133     *
134     * Internal helper for providers; passthrough to {@see Container::bind()}.
135     *
136     * @param string|callable $abstract Identifier (class name or alias) to register the entry under, or a factory callable whose return type names the identifier
137     * @param string|callable|null $concrete Class name to instantiate per resolution, or a factory callable; defaults to $abstract
138     * @return void
139     */
140    protected function bind(string|callable $abstract, string|callable|null $concrete = null): void
141    {
142        $this->container->bind($abstract, $concrete);
143    }
144
145    /**
146     * Register a shared singleton.
147     *
148     * Internal helper for providers; passthrough to {@see Container::singleton()}.
149     *
150     * @param string|callable $abstract Identifier (class name or alias) to register the entry under, or a factory callable whose return type names the identifier
151     * @param string|callable|null $concrete Class name to instantiate lazily, or a factory callable returning the instance; defaults to $abstract
152     * @return void
153     */
154    protected function singleton(string|callable $abstract, string|callable|null $concrete = null): void
155    {
156        $this->container->singleton($abstract, $concrete);
157    }
158
159    /**
160     * Register an existing object instance.
161     *
162     * Internal helper for providers; passthrough to {@see Container::instance()}.
163     *
164     * @param string|object $abstract Identifier (class name or alias) to register the instance under, or the instance itself (keyed by its class name)
165     * @param object|null $instance The instance to register; required when $abstract is a string
166     * @return object The registered instance
167     */
168    protected function instance(string|object $abstract, ?object $instance = null): object
169    {
170        return $this->container->instance($abstract, $instance);
171    }
172
173    /**
174     * Register an alias so a second identifier resolves to the same entry as
175     * an already-registered abstract.
176     *
177     * Internal helper for providers; passthrough to {@see Container::alias()}.
178     *
179     * @param string $abstract The identifier the alias points to
180     * @param string $alias The additional identifier to resolve to $abstract
181     * @return void
182     */
183    protected function alias(string $abstract, string $alias): void
184    {
185        $this->container->alias($abstract, $alias);
186    }
187
188    /**
189     * Begin a contextual binding for a concrete class.
190     *
191     * Internal helper for providers; passthrough to {@see Container::when()}.
192     *
193     * @param string $concrete The class whose dependencies to override
194     * @return ContextualBindingBuilder A builder to declare the needs/give pair
195     */
196    protected function when(string $concrete): ContextualBindingBuilder
197    {
198        return $this->container->when($concrete);
199    }
200
201    /**
202     * Assign tags to abstracts.
203     *
204     * Internal helper for providers; passthrough to {@see Container::tag()}.
205     *
206     * @param string|array $abstracts Identifier(s) to tag
207     * @param array $tags Tag name(s) to assign
208     * @return void
209     */
210    protected function tag(string|array $abstracts, array $tags): void
211    {
212        $this->container->tag($abstracts, $tags);
213    }
214
215    /**
216     * Resolve every abstract assigned to a tag.
217     *
218     * Internal helper for providers; passthrough to {@see Container::tagged()}.
219     *
220     * @param string $tag The tag name
221     * @return array<int, mixed> The resolved instances
222     */
223    protected function tagged(string $tag): array
224    {
225        return $this->container->tagged($tag);
226    }
227}