Vous êtes connecté en tant que anonymous Se Deconnecter
Browse code

Application modulaire fonctionnelle !

Emmanuel ROY authored on 12/08/2019 15:10:25
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1279 +0,0 @@
1
-<?php
2
-
3
-namespace Illuminate\Container;
4
-
5
-use Closure;
6
-use Exception;
7
-use ArrayAccess;
8
-use LogicException;
9
-use ReflectionClass;
10
-use ReflectionParameter;
11
-use Illuminate\Support\Arr;
12
-use Illuminate\Contracts\Container\BindingResolutionException;
13
-use Illuminate\Contracts\Container\Container as ContainerContract;
14
-
15
-class Container implements ArrayAccess, ContainerContract
16
-{
17
-    /**
18
-     * The current globally available container (if any).
19
-     *
20
-     * @var static
21
-     */
22
-    protected static $instance;
23
-
24
-    /**
25
-     * An array of the types that have been resolved.
26
-     *
27
-     * @var bool[]
28
-     */
29
-    protected $resolved = [];
30
-
31
-    /**
32
-     * The container's bindings.
33
-     *
34
-     * @var array[]
35
-     */
36
-    protected $bindings = [];
37
-
38
-    /**
39
-     * The container's method bindings.
40
-     *
41
-     * @var \Closure[]
42
-     */
43
-    protected $methodBindings = [];
44
-
45
-    /**
46
-     * The container's shared instances.
47
-     *
48
-     * @var object[]
49
-     */
50
-    protected $instances = [];
51
-
52
-    /**
53
-     * The registered type aliases.
54
-     *
55
-     * @var string[]
56
-     */
57
-    protected $aliases = [];
58
-
59
-    /**
60
-     * The registered aliases keyed by the abstract name.
61
-     *
62
-     * @var array[]
63
-     */
64
-    protected $abstractAliases = [];
65
-
66
-    /**
67
-     * The extension closures for services.
68
-     *
69
-     * @var array[]
70
-     */
71
-    protected $extenders = [];
72
-
73
-    /**
74
-     * All of the registered tags.
75
-     *
76
-     * @var array[]
77
-     */
78
-    protected $tags = [];
79
-
80
-    /**
81
-     * The stack of concretions currently being built.
82
-     *
83
-     * @var array[]
84
-     */
85
-    protected $buildStack = [];
86
-
87
-    /**
88
-     * The parameter override stack.
89
-     *
90
-     * @var array[]
91
-     */
92
-    protected $with = [];
93
-
94
-    /**
95
-     * The contextual binding map.
96
-     *
97
-     * @var array[]
98
-     */
99
-    public $contextual = [];
100
-
101
-    /**
102
-     * All of the registered rebound callbacks.
103
-     *
104
-     * @var array[]
105
-     */
106
-    protected $reboundCallbacks = [];
107
-
108
-    /**
109
-     * All of the global resolving callbacks.
110
-     *
111
-     * @var \Closure[]
112
-     */
113
-    protected $globalResolvingCallbacks = [];
114
-
115
-    /**
116
-     * All of the global after resolving callbacks.
117
-     *
118
-     * @var \Closure[]
119
-     */
120
-    protected $globalAfterResolvingCallbacks = [];
121
-
122
-    /**
123
-     * All of the resolving callbacks by class type.
124
-     *
125
-     * @var array[]
126
-     */
127
-    protected $resolvingCallbacks = [];
128
-
129
-    /**
130
-     * All of the after resolving callbacks by class type.
131
-     *
132
-     * @var array[]
133
-     */
134
-    protected $afterResolvingCallbacks = [];
135
-
136
-    /**
137
-     * Define a contextual binding.
138
-     *
139
-     * @param  array|string  $concrete
140
-     * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
141
-     */
142
-    public function when($concrete)
143
-    {
144
-        $aliases = [];
145
-
146
-        foreach (Arr::wrap($concrete) as $c) {
147
-            $aliases[] = $this->getAlias($c);
148
-        }
149
-
150
-        return new ContextualBindingBuilder($this, $aliases);
151
-    }
152
-
153
-    /**
154
-     * Determine if the given abstract type has been bound.
155
-     *
156
-     * @param  string  $abstract
157
-     * @return bool
158
-     */
159
-    public function bound($abstract)
160
-    {
161
-        return isset($this->bindings[$abstract]) ||
162
-               isset($this->instances[$abstract]) ||
163
-               $this->isAlias($abstract);
164
-    }
165
-
166
-    /**
167
-     *  {@inheritdoc}
168
-     */
169
-    public function has($id)
170
-    {
171
-        return $this->bound($id);
172
-    }
173
-
174
-    /**
175
-     * Determine if the given abstract type has been resolved.
176
-     *
177
-     * @param  string  $abstract
178
-     * @return bool
179
-     */
180
-    public function resolved($abstract)
181
-    {
182
-        if ($this->isAlias($abstract)) {
183
-            $abstract = $this->getAlias($abstract);
184
-        }
185
-
186
-        return isset($this->resolved[$abstract]) ||
187
-               isset($this->instances[$abstract]);
188
-    }
189
-
190
-    /**
191
-     * Determine if a given type is shared.
192
-     *
193
-     * @param  string  $abstract
194
-     * @return bool
195
-     */
196
-    public function isShared($abstract)
197
-    {
198
-        return isset($this->instances[$abstract]) ||
199
-               (isset($this->bindings[$abstract]['shared']) &&
200
-               $this->bindings[$abstract]['shared'] === true);
201
-    }
202
-
203
-    /**
204
-     * Determine if a given string is an alias.
205
-     *
206
-     * @param  string  $name
207
-     * @return bool
208
-     */
209
-    public function isAlias($name)
210
-    {
211
-        return isset($this->aliases[$name]);
212
-    }
213
-
214
-    /**
215
-     * Register a binding with the container.
216
-     *
217
-     * @param  string  $abstract
218
-     * @param  \Closure|string|null  $concrete
219
-     * @param  bool  $shared
220
-     * @return void
221
-     */
222
-    public function bind($abstract, $concrete = null, $shared = false)
223
-    {
224
-        $this->dropStaleInstances($abstract);
225
-
226
-        // If no concrete type was given, we will simply set the concrete type to the
227
-        // abstract type. After that, the concrete type to be registered as shared
228
-        // without being forced to state their classes in both of the parameters.
229
-        if (is_null($concrete)) {
230
-            $concrete = $abstract;
231
-        }
232
-
233
-        // If the factory is not a Closure, it means it is just a class name which is
234
-        // bound into this container to the abstract type and we will just wrap it
235
-        // up inside its own Closure to give us more convenience when extending.
236
-        if (! $concrete instanceof Closure) {
237
-            $concrete = $this->getClosure($abstract, $concrete);
238
-        }
239
-
240
-        $this->bindings[$abstract] = compact('concrete', 'shared');
241
-
242
-        // If the abstract type was already resolved in this container we'll fire the
243
-        // rebound listener so that any objects which have already gotten resolved
244
-        // can have their copy of the object updated via the listener callbacks.
245
-        if ($this->resolved($abstract)) {
246
-            $this->rebound($abstract);
247
-        }
248
-    }
249
-
250
-    /**
251
-     * Get the Closure to be used when building a type.
252
-     *
253
-     * @param  string  $abstract
254
-     * @param  string  $concrete
255
-     * @return \Closure
256
-     */
257
-    protected function getClosure($abstract, $concrete)
258
-    {
259
-        return function ($container, $parameters = []) use ($abstract, $concrete) {
260
-            if ($abstract == $concrete) {
261
-                return $container->build($concrete);
262
-            }
263
-
264
-            return $container->resolve(
265
-                $concrete, $parameters, $raiseEvents = false
266
-            );
267
-        };
268
-    }
269
-
270
-    /**
271
-     * Determine if the container has a method binding.
272
-     *
273
-     * @param  string  $method
274
-     * @return bool
275
-     */
276
-    public function hasMethodBinding($method)
277
-    {
278
-        return isset($this->methodBindings[$method]);
279
-    }
280
-
281
-    /**
282
-     * Bind a callback to resolve with Container::call.
283
-     *
284
-     * @param  array|string  $method
285
-     * @param  \Closure  $callback
286
-     * @return void
287
-     */
288
-    public function bindMethod($method, $callback)
289
-    {
290
-        $this->methodBindings[$this->parseBindMethod($method)] = $callback;
291
-    }
292
-
293
-    /**
294
-     * Get the method to be bound in class@method format.
295
-     *
296
-     * @param  array|string $method
297
-     * @return string
298
-     */
299
-    protected function parseBindMethod($method)
300
-    {
301
-        if (is_array($method)) {
302
-            return $method[0].'@'.$method[1];
303
-        }
304
-
305
-        return $method;
306
-    }
307
-
308
-    /**
309
-     * Get the method binding for the given method.
310
-     *
311
-     * @param  string  $method
312
-     * @param  mixed  $instance
313
-     * @return mixed
314
-     */
315
-    public function callMethodBinding($method, $instance)
316
-    {
317
-        return call_user_func($this->methodBindings[$method], $instance, $this);
318
-    }
319
-
320
-    /**
321
-     * Add a contextual binding to the container.
322
-     *
323
-     * @param  string  $concrete
324
-     * @param  string  $abstract
325
-     * @param  \Closure|string  $implementation
326
-     * @return void
327
-     */
328
-    public function addContextualBinding($concrete, $abstract, $implementation)
329
-    {
330
-        $this->contextual[$concrete][$this->getAlias($abstract)] = $implementation;
331
-    }
332
-
333
-    /**
334
-     * Register a binding if it hasn't already been registered.
335
-     *
336
-     * @param  string  $abstract
337
-     * @param  \Closure|string|null  $concrete
338
-     * @param  bool  $shared
339
-     * @return void
340
-     */
341
-    public function bindIf($abstract, $concrete = null, $shared = false)
342
-    {
343
-        if (! $this->bound($abstract)) {
344
-            $this->bind($abstract, $concrete, $shared);
345
-        }
346
-    }
347
-
348
-    /**
349
-     * Register a shared binding in the container.
350
-     *
351
-     * @param  string  $abstract
352
-     * @param  \Closure|string|null  $concrete
353
-     * @return void
354
-     */
355
-    public function singleton($abstract, $concrete = null)
356
-    {
357
-        $this->bind($abstract, $concrete, true);
358
-    }
359
-
360
-    /**
361
-     * "Extend" an abstract type in the container.
362
-     *
363
-     * @param  string    $abstract
364
-     * @param  \Closure  $closure
365
-     * @return void
366
-     *
367
-     * @throws \InvalidArgumentException
368
-     */
369
-    public function extend($abstract, Closure $closure)
370
-    {
371
-        $abstract = $this->getAlias($abstract);
372
-
373
-        if (isset($this->instances[$abstract])) {
374
-            $this->instances[$abstract] = $closure($this->instances[$abstract], $this);
375
-
376
-            $this->rebound($abstract);
377
-        } else {
378
-            $this->extenders[$abstract][] = $closure;
379
-
380
-            if ($this->resolved($abstract)) {
381
-                $this->rebound($abstract);
382
-            }
383
-        }
384
-    }
385
-
386
-    /**
387
-     * Register an existing instance as shared in the container.
388
-     *
389
-     * @param  string  $abstract
390
-     * @param  mixed   $instance
391
-     * @return mixed
392
-     */
393
-    public function instance($abstract, $instance)
394
-    {
395
-        $this->removeAbstractAlias($abstract);
396
-
397
-        $isBound = $this->bound($abstract);
398
-
399
-        unset($this->aliases[$abstract]);
400
-
401
-        // We'll check to determine if this type has been bound before, and if it has
402
-        // we will fire the rebound callbacks registered with the container and it
403
-        // can be updated with consuming classes that have gotten resolved here.
404
-        $this->instances[$abstract] = $instance;
405
-
406
-        if ($isBound) {
407
-            $this->rebound($abstract);
408
-        }
409
-
410
-        return $instance;
411
-    }
412
-
413
-    /**
414
-     * Remove an alias from the contextual binding alias cache.
415
-     *
416
-     * @param  string  $searched
417
-     * @return void
418
-     */
419
-    protected function removeAbstractAlias($searched)
420
-    {
421
-        if (! isset($this->aliases[$searched])) {
422
-            return;
423
-        }
424
-
425
-        foreach ($this->abstractAliases as $abstract => $aliases) {
426
-            foreach ($aliases as $index => $alias) {
427
-                if ($alias == $searched) {
428
-                    unset($this->abstractAliases[$abstract][$index]);
429
-                }
430
-            }
431
-        }
432
-    }
433
-
434
-    /**
435
-     * Assign a set of tags to a given binding.
436
-     *
437
-     * @param  array|string  $abstracts
438
-     * @param  array|mixed   ...$tags
439
-     * @return void
440
-     */
441
-    public function tag($abstracts, $tags)
442
-    {
443
-        $tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1);
444
-
445
-        foreach ($tags as $tag) {
446
-            if (! isset($this->tags[$tag])) {
447
-                $this->tags[$tag] = [];
448
-            }
449
-
450
-            foreach ((array) $abstracts as $abstract) {
451
-                $this->tags[$tag][] = $abstract;
452
-            }
453
-        }
454
-    }
455
-
456
-    /**
457
-     * Resolve all of the bindings for a given tag.
458
-     *
459
-     * @param  string  $tag
460
-     * @return iterable
461
-     */
462
-    public function tagged($tag)
463
-    {
464
-        if (! isset($this->tags[$tag])) {
465
-            return [];
466
-        }
467
-
468
-        return new RewindableGenerator(function () use ($tag) {
469
-            foreach ($this->tags[$tag] as $abstract) {
470
-                yield $this->make($abstract);
471
-            }
472
-        }, count($this->tags[$tag]));
473
-    }
474
-
475
-    /**
476
-     * Alias a type to a different name.
477
-     *
478
-     * @param  string  $abstract
479
-     * @param  string  $alias
480
-     * @return void
481
-     *
482
-     * @throws \LogicException
483
-     */
484
-    public function alias($abstract, $alias)
485
-    {
486
-        if ($alias === $abstract) {
487
-            throw new LogicException("[{$abstract}] is aliased to itself.");
488
-        }
489
-
490
-        $this->aliases[$alias] = $abstract;
491
-
492
-        $this->abstractAliases[$abstract][] = $alias;
493
-    }
494
-
495
-    /**
496
-     * Bind a new callback to an abstract's rebind event.
497
-     *
498
-     * @param  string    $abstract
499
-     * @param  \Closure  $callback
500
-     * @return mixed
501
-     */
502
-    public function rebinding($abstract, Closure $callback)
503
-    {
504
-        $this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
505
-
506
-        if ($this->bound($abstract)) {
507
-            return $this->make($abstract);
508
-        }
509
-    }
510
-
511
-    /**
512
-     * Refresh an instance on the given target and method.
513
-     *
514
-     * @param  string  $abstract
515
-     * @param  mixed   $target
516
-     * @param  string  $method
517
-     * @return mixed
518
-     */
519
-    public function refresh($abstract, $target, $method)
520
-    {
521
-        return $this->rebinding($abstract, function ($app, $instance) use ($target, $method) {
522
-            $target->{$method}($instance);
523
-        });
524
-    }
525
-
526
-    /**
527
-     * Fire the "rebound" callbacks for the given abstract type.
528
-     *
529
-     * @param  string  $abstract
530
-     * @return void
531
-     */
532
-    protected function rebound($abstract)
533
-    {
534
-        $instance = $this->make($abstract);
535
-
536
-        foreach ($this->getReboundCallbacks($abstract) as $callback) {
537
-            call_user_func($callback, $this, $instance);
538
-        }
539
-    }
540
-
541
-    /**
542
-     * Get the rebound callbacks for a given type.
543
-     *
544
-     * @param  string  $abstract
545
-     * @return array
546
-     */
547
-    protected function getReboundCallbacks($abstract)
548
-    {
549
-        return $this->reboundCallbacks[$abstract] ?? [];
550
-    }
551
-
552
-    /**
553
-     * Wrap the given closure such that its dependencies will be injected when executed.
554
-     *
555
-     * @param  \Closure  $callback
556
-     * @param  array  $parameters
557
-     * @return \Closure
558
-     */
559
-    public function wrap(Closure $callback, array $parameters = [])
560
-    {
561
-        return function () use ($callback, $parameters) {
562
-            return $this->call($callback, $parameters);
563
-        };
564
-    }
565
-
566
-    /**
567
-     * Call the given Closure / class@method and inject its dependencies.
568
-     *
569
-     * @param  callable|string  $callback
570
-     * @param  array  $parameters
571
-     * @param  string|null  $defaultMethod
572
-     * @return mixed
573
-     */
574
-    public function call($callback, array $parameters = [], $defaultMethod = null)
575
-    {
576
-        return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
577
-    }
578
-
579
-    /**
580
-     * Get a closure to resolve the given type from the container.
581
-     *
582
-     * @param  string  $abstract
583
-     * @return \Closure
584
-     */
585
-    public function factory($abstract)
586
-    {
587
-        return function () use ($abstract) {
588
-            return $this->make($abstract);
589
-        };
590
-    }
591
-
592
-    /**
593
-     * An alias function name for make().
594
-     *
595
-     * @param  string  $abstract
596
-     * @param  array  $parameters
597
-     * @return mixed
598
-     */
599
-    public function makeWith($abstract, array $parameters = [])
600
-    {
601
-        return $this->make($abstract, $parameters);
602
-    }
603
-
604
-    /**
605
-     * Resolve the given type from the container.
606
-     *
607
-     * @param  string  $abstract
608
-     * @param  array  $parameters
609
-     * @return mixed
610
-     *
611
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
612
-     */
613
-    public function make($abstract, array $parameters = [])
614
-    {
615
-        return $this->resolve($abstract, $parameters);
616
-    }
617
-
618
-    /**
619
-     *  {@inheritdoc}
620
-     */
621
-    public function get($id)
622
-    {
623
-        try {
624
-            return $this->resolve($id);
625
-        } catch (Exception $e) {
626
-            if ($this->has($id)) {
627
-                throw $e;
628
-            }
629
-
630
-            throw new EntryNotFoundException($id);
631
-        }
632
-    }
633
-
634
-    /**
635
-     * Resolve the given type from the container.
636
-     *
637
-     * @param  string  $abstract
638
-     * @param  array  $parameters
639
-     * @param  bool   $raiseEvents
640
-     * @return mixed
641
-     *
642
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
643
-     */
644
-    protected function resolve($abstract, $parameters = [], $raiseEvents = true)
645
-    {
646
-        $abstract = $this->getAlias($abstract);
647
-
648
-        $needsContextualBuild = ! empty($parameters) || ! is_null(
649
-            $this->getContextualConcrete($abstract)
650
-        );
651
-
652
-        // If an instance of the type is currently being managed as a singleton we'll
653
-        // just return an existing instance instead of instantiating new instances
654
-        // so the developer can keep using the same objects instance every time.
655
-        if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
656
-            return $this->instances[$abstract];
657
-        }
658
-
659
-        $this->with[] = $parameters;
660
-
661
-        $concrete = $this->getConcrete($abstract);
662
-
663
-        // We're ready to instantiate an instance of the concrete type registered for
664
-        // the binding. This will instantiate the types, as well as resolve any of
665
-        // its "nested" dependencies recursively until all have gotten resolved.
666
-        if ($this->isBuildable($concrete, $abstract)) {
667
-            $object = $this->build($concrete);
668
-        } else {
669
-            $object = $this->make($concrete);
670
-        }
671
-
672
-        // If we defined any extenders for this type, we'll need to spin through them
673
-        // and apply them to the object being built. This allows for the extension
674
-        // of services, such as changing configuration or decorating the object.
675
-        foreach ($this->getExtenders($abstract) as $extender) {
676
-            $object = $extender($object, $this);
677
-        }
678
-
679
-        // If the requested type is registered as a singleton we'll want to cache off
680
-        // the instances in "memory" so we can return it later without creating an
681
-        // entirely new instance of an object on each subsequent request for it.
682
-        if ($this->isShared($abstract) && ! $needsContextualBuild) {
683
-            $this->instances[$abstract] = $object;
684
-        }
685
-
686
-        if ($raiseEvents) {
687
-            $this->fireResolvingCallbacks($abstract, $object);
688
-        }
689
-
690
-        // Before returning, we will also set the resolved flag to "true" and pop off
691
-        // the parameter overrides for this build. After those two things are done
692
-        // we will be ready to return back the fully constructed class instance.
693
-        $this->resolved[$abstract] = true;
694
-
695
-        array_pop($this->with);
696
-
697
-        return $object;
698
-    }
699
-
700
-    /**
701
-     * Get the concrete type for a given abstract.
702
-     *
703
-     * @param  string  $abstract
704
-     * @return mixed   $concrete
705
-     */
706
-    protected function getConcrete($abstract)
707
-    {
708
-        if (! is_null($concrete = $this->getContextualConcrete($abstract))) {
709
-            return $concrete;
710
-        }
711
-
712
-        // If we don't have a registered resolver or concrete for the type, we'll just
713
-        // assume each type is a concrete name and will attempt to resolve it as is
714
-        // since the container should be able to resolve concretes automatically.
715
-        if (isset($this->bindings[$abstract])) {
716
-            return $this->bindings[$abstract]['concrete'];
717
-        }
718
-
719
-        return $abstract;
720
-    }
721
-
722
-    /**
723
-     * Get the contextual concrete binding for the given abstract.
724
-     *
725
-     * @param  string  $abstract
726
-     * @return \Closure|string|null
727
-     */
728
-    protected function getContextualConcrete($abstract)
729
-    {
730
-        if (! is_null($binding = $this->findInContextualBindings($abstract))) {
731
-            return $binding;
732
-        }
733
-
734
-        // Next we need to see if a contextual binding might be bound under an alias of the
735
-        // given abstract type. So, we will need to check if any aliases exist with this
736
-        // type and then spin through them and check for contextual bindings on these.
737
-        if (empty($this->abstractAliases[$abstract])) {
738
-            return;
739
-        }
740
-
741
-        foreach ($this->abstractAliases[$abstract] as $alias) {
742
-            if (! is_null($binding = $this->findInContextualBindings($alias))) {
743
-                return $binding;
744
-            }
745
-        }
746
-    }
747
-
748
-    /**
749
-     * Find the concrete binding for the given abstract in the contextual binding array.
750
-     *
751
-     * @param  string  $abstract
752
-     * @return \Closure|string|null
753
-     */
754
-    protected function findInContextualBindings($abstract)
755
-    {
756
-        if (isset($this->contextual[end($this->buildStack)][$abstract])) {
757
-            return $this->contextual[end($this->buildStack)][$abstract];
758
-        }
759
-    }
760
-
761
-    /**
762
-     * Determine if the given concrete is buildable.
763
-     *
764
-     * @param  mixed   $concrete
765
-     * @param  string  $abstract
766
-     * @return bool
767
-     */
768
-    protected function isBuildable($concrete, $abstract)
769
-    {
770
-        return $concrete === $abstract || $concrete instanceof Closure;
771
-    }
772
-
773
-    /**
774
-     * Instantiate a concrete instance of the given type.
775
-     *
776
-     * @param  string  $concrete
777
-     * @return mixed
778
-     *
779
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
780
-     */
781
-    public function build($concrete)
782
-    {
783
-        // If the concrete type is actually a Closure, we will just execute it and
784
-        // hand back the results of the functions, which allows functions to be
785
-        // used as resolvers for more fine-tuned resolution of these objects.
786
-        if ($concrete instanceof Closure) {
787
-            return $concrete($this, $this->getLastParameterOverride());
788
-        }
789
-
790
-        $reflector = new ReflectionClass($concrete);
791
-
792
-        // If the type is not instantiable, the developer is attempting to resolve
793
-        // an abstract type such as an Interface or Abstract Class and there is
794
-        // no binding registered for the abstractions so we need to bail out.
795
-        if (! $reflector->isInstantiable()) {
796
-            return $this->notInstantiable($concrete);
797
-        }
798
-
799
-        $this->buildStack[] = $concrete;
800
-
801
-        $constructor = $reflector->getConstructor();
802
-
803
-        // If there are no constructors, that means there are no dependencies then
804
-        // we can just resolve the instances of the objects right away, without
805
-        // resolving any other types or dependencies out of these containers.
806
-        if (is_null($constructor)) {
807
-            array_pop($this->buildStack);
808
-
809
-            return new $concrete;
810
-        }
811
-
812
-        $dependencies = $constructor->getParameters();
813
-
814
-        // Once we have all the constructor's parameters we can create each of the
815
-        // dependency instances and then use the reflection instances to make a
816
-        // new instance of this class, injecting the created dependencies in.
817
-        try {
818
-            $instances = $this->resolveDependencies($dependencies);
819
-        } catch (BindingResolutionException $e) {
820
-            array_pop($this->buildStack);
821
-
822
-            throw $e;
823
-        }
824
-
825
-        array_pop($this->buildStack);
826
-
827
-        return $reflector->newInstanceArgs($instances);
828
-    }
829
-
830
-    /**
831
-     * Resolve all of the dependencies from the ReflectionParameters.
832
-     *
833
-     * @param  array  $dependencies
834
-     * @return array
835
-     *
836
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
837
-     */
838
-    protected function resolveDependencies(array $dependencies)
839
-    {
840
-        $results = [];
841
-
842
-        foreach ($dependencies as $dependency) {
843
-            // If this dependency has a override for this particular build we will use
844
-            // that instead as the value. Otherwise, we will continue with this run
845
-            // of resolutions and let reflection attempt to determine the result.
846
-            if ($this->hasParameterOverride($dependency)) {
847
-                $results[] = $this->getParameterOverride($dependency);
848
-
849
-                continue;
850
-            }
851
-
852
-            // If the class is null, it means the dependency is a string or some other
853
-            // primitive type which we can not resolve since it is not a class and
854
-            // we will just bomb out with an error since we have no-where to go.
855
-            $results[] = is_null($dependency->getClass())
856
-                            ? $this->resolvePrimitive($dependency)
857
-                            : $this->resolveClass($dependency);
858
-        }
859
-
860
-        return $results;
861
-    }
862
-
863
-    /**
864
-     * Determine if the given dependency has a parameter override.
865
-     *
866
-     * @param  \ReflectionParameter  $dependency
867
-     * @return bool
868
-     */
869
-    protected function hasParameterOverride($dependency)
870
-    {
871
-        return array_key_exists(
872
-            $dependency->name, $this->getLastParameterOverride()
873
-        );
874
-    }
875
-
876
-    /**
877
-     * Get a parameter override for a dependency.
878
-     *
879
-     * @param  \ReflectionParameter  $dependency
880
-     * @return mixed
881
-     */
882
-    protected function getParameterOverride($dependency)
883
-    {
884
-        return $this->getLastParameterOverride()[$dependency->name];
885
-    }
886
-
887
-    /**
888
-     * Get the last parameter override.
889
-     *
890
-     * @return array
891
-     */
892
-    protected function getLastParameterOverride()
893
-    {
894
-        return count($this->with) ? end($this->with) : [];
895
-    }
896
-
897
-    /**
898
-     * Resolve a non-class hinted primitive dependency.
899
-     *
900
-     * @param  \ReflectionParameter  $parameter
901
-     * @return mixed
902
-     *
903
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
904
-     */
905
-    protected function resolvePrimitive(ReflectionParameter $parameter)
906
-    {
907
-        if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
908
-            return $concrete instanceof Closure ? $concrete($this) : $concrete;
909
-        }
910
-
911
-        if ($parameter->isDefaultValueAvailable()) {
912
-            return $parameter->getDefaultValue();
913
-        }
914
-
915
-        $this->unresolvablePrimitive($parameter);
916
-    }
917
-
918
-    /**
919
-     * Resolve a class based dependency from the container.
920
-     *
921
-     * @param  \ReflectionParameter  $parameter
922
-     * @return mixed
923
-     *
924
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
925
-     */
926
-    protected function resolveClass(ReflectionParameter $parameter)
927
-    {
928
-        try {
929
-            return $this->make($parameter->getClass()->name);
930
-        }
931
-
932
-        // If we can not resolve the class instance, we will check to see if the value
933
-        // is optional, and if it is we will return the optional parameter value as
934
-        // the value of the dependency, similarly to how we do this with scalars.
935
-        catch (BindingResolutionException $e) {
936
-            if ($parameter->isOptional()) {
937
-                return $parameter->getDefaultValue();
938
-            }
939
-
940
-            throw $e;
941
-        }
942
-    }
943
-
944
-    /**
945
-     * Throw an exception that the concrete is not instantiable.
946
-     *
947
-     * @param  string  $concrete
948
-     * @return void
949
-     *
950
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
951
-     */
952
-    protected function notInstantiable($concrete)
953
-    {
954
-        if (! empty($this->buildStack)) {
955
-            $previous = implode(', ', $this->buildStack);
956
-
957
-            $message = "Target [$concrete] is not instantiable while building [$previous].";
958
-        } else {
959
-            $message = "Target [$concrete] is not instantiable.";
960
-        }
961
-
962
-        throw new BindingResolutionException($message);
963
-    }
964
-
965
-    /**
966
-     * Throw an exception for an unresolvable primitive.
967
-     *
968
-     * @param  \ReflectionParameter  $parameter
969
-     * @return void
970
-     *
971
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
972
-     */
973
-    protected function unresolvablePrimitive(ReflectionParameter $parameter)
974
-    {
975
-        $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";
976
-
977
-        throw new BindingResolutionException($message);
978
-    }
979
-
980
-    /**
981
-     * Register a new resolving callback.
982
-     *
983
-     * @param  \Closure|string  $abstract
984
-     * @param  \Closure|null  $callback
985
-     * @return void
986
-     */
987
-    public function resolving($abstract, Closure $callback = null)
988
-    {
989
-        if (is_string($abstract)) {
990
-            $abstract = $this->getAlias($abstract);
991
-        }
992
-
993
-        if (is_null($callback) && $abstract instanceof Closure) {
994
-            $this->globalResolvingCallbacks[] = $abstract;
995
-        } else {
996
-            $this->resolvingCallbacks[$abstract][] = $callback;
997
-        }
998
-    }
999
-
1000
-    /**
1001
-     * Register a new after resolving callback for all types.
1002
-     *
1003
-     * @param  \Closure|string  $abstract
1004
-     * @param  \Closure|null  $callback
1005
-     * @return void
1006
-     */
1007
-    public function afterResolving($abstract, Closure $callback = null)
1008
-    {
1009
-        if (is_string($abstract)) {
1010
-            $abstract = $this->getAlias($abstract);
1011
-        }
1012
-
1013
-        if ($abstract instanceof Closure && is_null($callback)) {
1014
-            $this->globalAfterResolvingCallbacks[] = $abstract;
1015
-        } else {
1016
-            $this->afterResolvingCallbacks[$abstract][] = $callback;
1017
-        }
1018
-    }
1019
-
1020
-    /**
1021
-     * Fire all of the resolving callbacks.
1022
-     *
1023
-     * @param  string  $abstract
1024
-     * @param  mixed   $object
1025
-     * @return void
1026
-     */
1027
-    protected function fireResolvingCallbacks($abstract, $object)
1028
-    {
1029
-        $this->fireCallbackArray($object, $this->globalResolvingCallbacks);
1030
-
1031
-        $this->fireCallbackArray(
1032
-            $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
1033
-        );
1034
-
1035
-        $this->fireAfterResolvingCallbacks($abstract, $object);
1036
-    }
1037
-
1038
-    /**
1039
-     * Fire all of the after resolving callbacks.
1040
-     *
1041
-     * @param  string  $abstract
1042
-     * @param  mixed   $object
1043
-     * @return void
1044
-     */
1045
-    protected function fireAfterResolvingCallbacks($abstract, $object)
1046
-    {
1047
-        $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);
1048
-
1049
-        $this->fireCallbackArray(
1050
-            $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
1051
-        );
1052
-    }
1053
-
1054
-    /**
1055
-     * Get all callbacks for a given type.
1056
-     *
1057
-     * @param  string  $abstract
1058
-     * @param  object  $object
1059
-     * @param  array   $callbacksPerType
1060
-     *
1061
-     * @return array
1062
-     */
1063
-    protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
1064
-    {
1065
-        $results = [];
1066
-
1067
-        foreach ($callbacksPerType as $type => $callbacks) {
1068
-            if ($type === $abstract || $object instanceof $type) {
1069
-                $results = array_merge($results, $callbacks);
1070
-            }
1071
-        }
1072
-
1073
-        return $results;
1074
-    }
1075
-
1076
-    /**
1077
-     * Fire an array of callbacks with an object.
1078
-     *
1079
-     * @param  mixed  $object
1080
-     * @param  array  $callbacks
1081
-     * @return void
1082
-     */
1083
-    protected function fireCallbackArray($object, array $callbacks)
1084
-    {
1085
-        foreach ($callbacks as $callback) {
1086
-            $callback($object, $this);
1087
-        }
1088
-    }
1089
-
1090
-    /**
1091
-     * Get the container's bindings.
1092
-     *
1093
-     * @return array
1094
-     */
1095
-    public function getBindings()
1096
-    {
1097
-        return $this->bindings;
1098
-    }
1099
-
1100
-    /**
1101
-     * Get the alias for an abstract if available.
1102
-     *
1103
-     * @param  string  $abstract
1104
-     * @return string
1105
-     */
1106
-    public function getAlias($abstract)
1107
-    {
1108
-        if (! isset($this->aliases[$abstract])) {
1109
-            return $abstract;
1110
-        }
1111
-
1112
-        return $this->getAlias($this->aliases[$abstract]);
1113
-    }
1114
-
1115
-    /**
1116
-     * Get the extender callbacks for a given type.
1117
-     *
1118
-     * @param  string  $abstract
1119
-     * @return array
1120
-     */
1121
-    protected function getExtenders($abstract)
1122
-    {
1123
-        $abstract = $this->getAlias($abstract);
1124
-
1125
-        return $this->extenders[$abstract] ?? [];
1126
-    }
1127
-
1128
-    /**
1129
-     * Remove all of the extender callbacks for a given type.
1130
-     *
1131
-     * @param  string  $abstract
1132
-     * @return void
1133
-     */
1134
-    public function forgetExtenders($abstract)
1135
-    {
1136
-        unset($this->extenders[$this->getAlias($abstract)]);
1137
-    }
1138
-
1139
-    /**
1140
-     * Drop all of the stale instances and aliases.
1141
-     *
1142
-     * @param  string  $abstract
1143
-     * @return void
1144
-     */
1145
-    protected function dropStaleInstances($abstract)
1146
-    {
1147
-        unset($this->instances[$abstract], $this->aliases[$abstract]);
1148
-    }
1149
-
1150
-    /**
1151
-     * Remove a resolved instance from the instance cache.
1152
-     *
1153
-     * @param  string  $abstract
1154
-     * @return void
1155
-     */
1156
-    public function forgetInstance($abstract)
1157
-    {
1158
-        unset($this->instances[$abstract]);
1159
-    }
1160
-
1161
-    /**
1162
-     * Clear all of the instances from the container.
1163
-     *
1164
-     * @return void
1165
-     */
1166
-    public function forgetInstances()
1167
-    {
1168
-        $this->instances = [];
1169
-    }
1170
-
1171
-    /**
1172
-     * Flush the container of all bindings and resolved instances.
1173
-     *
1174
-     * @return void
1175
-     */
1176
-    public function flush()
1177
-    {
1178
-        $this->aliases = [];
1179
-        $this->resolved = [];
1180
-        $this->bindings = [];
1181
-        $this->instances = [];
1182
-        $this->abstractAliases = [];
1183
-    }
1184
-
1185
-    /**
1186
-     * Set the globally available instance of the container.
1187
-     *
1188
-     * @return static
1189
-     */
1190
-    public static function getInstance()
1191
-    {
1192
-        if (is_null(static::$instance)) {
1193
-            static::$instance = new static;
1194
-        }
1195
-
1196
-        return static::$instance;
1197
-    }
1198
-
1199
-    /**
1200
-     * Set the shared instance of the container.
1201
-     *
1202
-     * @param  \Illuminate\Contracts\Container\Container|null  $container
1203
-     * @return \Illuminate\Contracts\Container\Container|static
1204
-     */
1205
-    public static function setInstance(ContainerContract $container = null)
1206
-    {
1207
-        return static::$instance = $container;
1208
-    }
1209
-
1210
-    /**
1211
-     * Determine if a given offset exists.
1212
-     *
1213
-     * @param  string  $key
1214
-     * @return bool
1215
-     */
1216
-    public function offsetExists($key)
1217
-    {
1218
-        return $this->bound($key);
1219
-    }
1220
-
1221
-    /**
1222
-     * Get the value at a given offset.
1223
-     *
1224
-     * @param  string  $key
1225
-     * @return mixed
1226
-     */
1227
-    public function offsetGet($key)
1228
-    {
1229
-        return $this->make($key);
1230
-    }
1231
-
1232
-    /**
1233
-     * Set the value at a given offset.
1234
-     *
1235
-     * @param  string  $key
1236
-     * @param  mixed   $value
1237
-     * @return void
1238
-     */
1239
-    public function offsetSet($key, $value)
1240
-    {
1241
-        $this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
1242
-            return $value;
1243
-        });
1244
-    }
1245
-
1246
-    /**
1247
-     * Unset the value at a given offset.
1248
-     *
1249
-     * @param  string  $key
1250
-     * @return void
1251
-     */
1252
-    public function offsetUnset($key)
1253
-    {
1254
-        unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
1255
-    }
1256
-
1257
-    /**
1258
-     * Dynamically access container services.
1259
-     *
1260
-     * @param  string  $key
1261
-     * @return mixed
1262
-     */
1263
-    public function __get($key)
1264
-    {
1265
-        return $this[$key];
1266
-    }
1267
-
1268
-    /**
1269
-     * Dynamically set container services.
1270
-     *
1271
-     * @param  string  $key
1272
-     * @param  mixed   $value
1273
-     * @return void
1274
-     */
1275
-    public function __set($key, $value)
1276
-    {
1277
-        $this[$key] = $value;
1278
-    }
1279
-}
Browse code

initial commit

Emmanuel ROY authored on 09/08/2019 08:39:02
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1279 @@
1
+<?php
2
+
3
+namespace Illuminate\Container;
4
+
5
+use Closure;
6
+use Exception;
7
+use ArrayAccess;
8
+use LogicException;
9
+use ReflectionClass;
10
+use ReflectionParameter;
11
+use Illuminate\Support\Arr;
12
+use Illuminate\Contracts\Container\BindingResolutionException;
13
+use Illuminate\Contracts\Container\Container as ContainerContract;
14
+
15
+class Container implements ArrayAccess, ContainerContract
16
+{
17
+    /**
18
+     * The current globally available container (if any).
19
+     *
20
+     * @var static
21
+     */
22
+    protected static $instance;
23
+
24
+    /**
25
+     * An array of the types that have been resolved.
26
+     *
27
+     * @var bool[]
28
+     */
29
+    protected $resolved = [];
30
+
31
+    /**
32
+     * The container's bindings.
33
+     *
34
+     * @var array[]
35
+     */
36
+    protected $bindings = [];
37
+
38
+    /**
39
+     * The container's method bindings.
40
+     *
41
+     * @var \Closure[]
42
+     */
43
+    protected $methodBindings = [];
44
+
45
+    /**
46
+     * The container's shared instances.
47
+     *
48
+     * @var object[]
49
+     */
50
+    protected $instances = [];
51
+
52
+    /**
53
+     * The registered type aliases.
54
+     *
55
+     * @var string[]
56
+     */
57
+    protected $aliases = [];
58
+
59
+    /**
60
+     * The registered aliases keyed by the abstract name.
61
+     *
62
+     * @var array[]
63
+     */
64
+    protected $abstractAliases = [];
65
+
66
+    /**
67
+     * The extension closures for services.
68
+     *
69
+     * @var array[]
70
+     */
71
+    protected $extenders = [];
72
+
73
+    /**
74
+     * All of the registered tags.
75
+     *
76
+     * @var array[]
77
+     */
78
+    protected $tags = [];
79
+
80
+    /**
81
+     * The stack of concretions currently being built.
82
+     *
83
+     * @var array[]
84
+     */
85
+    protected $buildStack = [];
86
+
87
+    /**
88
+     * The parameter override stack.
89
+     *
90
+     * @var array[]
91
+     */
92
+    protected $with = [];
93
+
94
+    /**
95
+     * The contextual binding map.
96
+     *
97
+     * @var array[]
98
+     */
99
+    public $contextual = [];
100
+
101
+    /**
102
+     * All of the registered rebound callbacks.
103
+     *
104
+     * @var array[]
105
+     */
106
+    protected $reboundCallbacks = [];
107
+
108
+    /**
109
+     * All of the global resolving callbacks.
110
+     *
111
+     * @var \Closure[]
112
+     */
113
+    protected $globalResolvingCallbacks = [];
114
+
115
+    /**
116
+     * All of the global after resolving callbacks.
117
+     *
118
+     * @var \Closure[]
119
+     */
120
+    protected $globalAfterResolvingCallbacks = [];
121
+
122
+    /**
123
+     * All of the resolving callbacks by class type.
124
+     *
125
+     * @var array[]
126
+     */
127
+    protected $resolvingCallbacks = [];
128
+
129
+    /**
130
+     * All of the after resolving callbacks by class type.
131
+     *
132
+     * @var array[]
133
+     */
134
+    protected $afterResolvingCallbacks = [];
135
+
136
+    /**
137
+     * Define a contextual binding.
138
+     *
139
+     * @param  array|string  $concrete
140
+     * @return \Illuminate\Contracts\Container\ContextualBindingBuilder
141
+     */
142
+    public function when($concrete)
143
+    {
144
+        $aliases = [];
145
+
146
+        foreach (Arr::wrap($concrete) as $c) {
147
+            $aliases[] = $this->getAlias($c);
148
+        }
149
+
150
+        return new ContextualBindingBuilder($this, $aliases);
151
+    }
152
+
153
+    /**
154
+     * Determine if the given abstract type has been bound.
155
+     *
156
+     * @param  string  $abstract
157
+     * @return bool
158
+     */
159
+    public function bound($abstract)
160
+    {
161
+        return isset($this->bindings[$abstract]) ||
162
+               isset($this->instances[$abstract]) ||
163
+               $this->isAlias($abstract);
164
+    }
165
+
166
+    /**
167
+     *  {@inheritdoc}
168
+     */
169
+    public function has($id)
170
+    {
171
+        return $this->bound($id);
172
+    }
173
+
174
+    /**
175
+     * Determine if the given abstract type has been resolved.
176
+     *
177
+     * @param  string  $abstract
178
+     * @return bool
179
+     */
180
+    public function resolved($abstract)
181
+    {
182
+        if ($this->isAlias($abstract)) {
183
+            $abstract = $this->getAlias($abstract);
184
+        }
185
+
186
+        return isset($this->resolved[$abstract]) ||
187
+               isset($this->instances[$abstract]);
188
+    }
189
+
190
+    /**
191
+     * Determine if a given type is shared.
192
+     *
193
+     * @param  string  $abstract
194
+     * @return bool
195
+     */
196
+    public function isShared($abstract)
197
+    {
198
+        return isset($this->instances[$abstract]) ||
199
+               (isset($this->bindings[$abstract]['shared']) &&
200
+               $this->bindings[$abstract]['shared'] === true);
201
+    }
202
+
203
+    /**
204
+     * Determine if a given string is an alias.
205
+     *
206
+     * @param  string  $name
207
+     * @return bool
208
+     */
209
+    public function isAlias($name)
210
+    {
211
+        return isset($this->aliases[$name]);
212
+    }
213
+
214
+    /**
215
+     * Register a binding with the container.
216
+     *
217
+     * @param  string  $abstract
218
+     * @param  \Closure|string|null  $concrete
219
+     * @param  bool  $shared
220
+     * @return void
221
+     */
222
+    public function bind($abstract, $concrete = null, $shared = false)
223
+    {
224
+        $this->dropStaleInstances($abstract);
225
+
226
+        // If no concrete type was given, we will simply set the concrete type to the
227
+        // abstract type. After that, the concrete type to be registered as shared
228
+        // without being forced to state their classes in both of the parameters.
229
+        if (is_null($concrete)) {
230
+            $concrete = $abstract;
231
+        }
232
+
233
+        // If the factory is not a Closure, it means it is just a class name which is
234
+        // bound into this container to the abstract type and we will just wrap it
235
+        // up inside its own Closure to give us more convenience when extending.
236
+        if (! $concrete instanceof Closure) {
237
+            $concrete = $this->getClosure($abstract, $concrete);
238
+        }
239
+
240
+        $this->bindings[$abstract] = compact('concrete', 'shared');
241
+
242
+        // If the abstract type was already resolved in this container we'll fire the
243
+        // rebound listener so that any objects which have already gotten resolved
244
+        // can have their copy of the object updated via the listener callbacks.
245
+        if ($this->resolved($abstract)) {
246
+            $this->rebound($abstract);
247
+        }
248
+    }
249
+
250
+    /**
251
+     * Get the Closure to be used when building a type.
252
+     *
253
+     * @param  string  $abstract
254
+     * @param  string  $concrete
255
+     * @return \Closure
256
+     */
257
+    protected function getClosure($abstract, $concrete)
258
+    {
259
+        return function ($container, $parameters = []) use ($abstract, $concrete) {
260
+            if ($abstract == $concrete) {
261
+                return $container->build($concrete);
262
+            }
263
+
264
+            return $container->resolve(
265
+                $concrete, $parameters, $raiseEvents = false
266
+            );
267
+        };
268
+    }
269
+
270
+    /**
271
+     * Determine if the container has a method binding.
272
+     *
273
+     * @param  string  $method
274
+     * @return bool
275
+     */
276
+    public function hasMethodBinding($method)
277
+    {
278
+        return isset($this->methodBindings[$method]);
279
+    }
280
+
281
+    /**
282
+     * Bind a callback to resolve with Container::call.
283
+     *
284
+     * @param  array|string  $method
285
+     * @param  \Closure  $callback
286
+     * @return void
287
+     */
288
+    public function bindMethod($method, $callback)
289
+    {
290
+        $this->methodBindings[$this->parseBindMethod($method)] = $callback;
291
+    }
292
+
293
+    /**
294
+     * Get the method to be bound in class@method format.
295
+     *
296
+     * @param  array|string $method
297
+     * @return string
298
+     */
299
+    protected function parseBindMethod($method)
300
+    {
301
+        if (is_array($method)) {
302
+            return $method[0].'@'.$method[1];
303
+        }
304
+
305
+        return $method;
306
+    }
307
+
308
+    /**
309
+     * Get the method binding for the given method.
310
+     *
311
+     * @param  string  $method
312
+     * @param  mixed  $instance
313
+     * @return mixed
314
+     */
315
+    public function callMethodBinding($method, $instance)
316
+    {
317
+        return call_user_func($this->methodBindings[$method], $instance, $this);
318
+    }
319
+
320
+    /**
321
+     * Add a contextual binding to the container.
322
+     *
323
+     * @param  string  $concrete
324
+     * @param  string  $abstract
325
+     * @param  \Closure|string  $implementation
326
+     * @return void
327
+     */
328
+    public function addContextualBinding($concrete, $abstract, $implementation)
329
+    {
330
+        $this->contextual[$concrete][$this->getAlias($abstract)] = $implementation;
331
+    }
332
+
333
+    /**
334
+     * Register a binding if it hasn't already been registered.
335
+     *
336
+     * @param  string  $abstract
337
+     * @param  \Closure|string|null  $concrete
338
+     * @param  bool  $shared
339
+     * @return void
340
+     */
341
+    public function bindIf($abstract, $concrete = null, $shared = false)
342
+    {
343
+        if (! $this->bound($abstract)) {
344
+            $this->bind($abstract, $concrete, $shared);
345
+        }
346
+    }
347
+
348
+    /**
349
+     * Register a shared binding in the container.
350
+     *
351
+     * @param  string  $abstract
352
+     * @param  \Closure|string|null  $concrete
353
+     * @return void
354
+     */
355
+    public function singleton($abstract, $concrete = null)
356
+    {
357
+        $this->bind($abstract, $concrete, true);
358
+    }
359
+
360
+    /**
361
+     * "Extend" an abstract type in the container.
362
+     *
363
+     * @param  string    $abstract
364
+     * @param  \Closure  $closure
365
+     * @return void
366
+     *
367
+     * @throws \InvalidArgumentException
368
+     */
369
+    public function extend($abstract, Closure $closure)
370
+    {
371
+        $abstract = $this->getAlias($abstract);
372
+
373
+        if (isset($this->instances[$abstract])) {
374
+            $this->instances[$abstract] = $closure($this->instances[$abstract], $this);
375
+
376
+            $this->rebound($abstract);
377
+        } else {
378
+            $this->extenders[$abstract][] = $closure;
379
+
380
+            if ($this->resolved($abstract)) {
381
+                $this->rebound($abstract);
382
+            }
383
+        }
384
+    }
385
+
386
+    /**
387
+     * Register an existing instance as shared in the container.
388
+     *
389
+     * @param  string  $abstract
390
+     * @param  mixed   $instance
391
+     * @return mixed
392
+     */
393
+    public function instance($abstract, $instance)
394
+    {
395
+        $this->removeAbstractAlias($abstract);
396
+
397
+        $isBound = $this->bound($abstract);
398
+
399
+        unset($this->aliases[$abstract]);
400
+
401
+        // We'll check to determine if this type has been bound before, and if it has
402
+        // we will fire the rebound callbacks registered with the container and it
403
+        // can be updated with consuming classes that have gotten resolved here.
404
+        $this->instances[$abstract] = $instance;
405
+
406
+        if ($isBound) {
407
+            $this->rebound($abstract);
408
+        }
409
+
410
+        return $instance;
411
+    }
412
+
413
+    /**
414
+     * Remove an alias from the contextual binding alias cache.
415
+     *
416
+     * @param  string  $searched
417
+     * @return void
418
+     */
419
+    protected function removeAbstractAlias($searched)
420
+    {
421
+        if (! isset($this->aliases[$searched])) {
422
+            return;
423
+        }
424
+
425
+        foreach ($this->abstractAliases as $abstract => $aliases) {
426
+            foreach ($aliases as $index => $alias) {
427
+                if ($alias == $searched) {
428
+                    unset($this->abstractAliases[$abstract][$index]);
429
+                }
430
+            }
431
+        }
432
+    }
433
+
434
+    /**
435
+     * Assign a set of tags to a given binding.
436
+     *
437
+     * @param  array|string  $abstracts
438
+     * @param  array|mixed   ...$tags
439
+     * @return void
440
+     */
441
+    public function tag($abstracts, $tags)
442
+    {
443
+        $tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1);
444
+
445
+        foreach ($tags as $tag) {
446
+            if (! isset($this->tags[$tag])) {
447
+                $this->tags[$tag] = [];
448
+            }
449
+
450
+            foreach ((array) $abstracts as $abstract) {
451
+                $this->tags[$tag][] = $abstract;
452
+            }
453
+        }
454
+    }
455
+
456
+    /**
457
+     * Resolve all of the bindings for a given tag.
458
+     *
459
+     * @param  string  $tag
460
+     * @return iterable
461
+     */
462
+    public function tagged($tag)
463
+    {
464
+        if (! isset($this->tags[$tag])) {
465
+            return [];
466
+        }
467
+
468
+        return new RewindableGenerator(function () use ($tag) {
469
+            foreach ($this->tags[$tag] as $abstract) {
470
+                yield $this->make($abstract);
471
+            }
472
+        }, count($this->tags[$tag]));
473
+    }
474
+
475
+    /**
476
+     * Alias a type to a different name.
477
+     *
478
+     * @param  string  $abstract
479
+     * @param  string  $alias
480
+     * @return void
481
+     *
482
+     * @throws \LogicException
483
+     */
484
+    public function alias($abstract, $alias)
485
+    {
486
+        if ($alias === $abstract) {
487
+            throw new LogicException("[{$abstract}] is aliased to itself.");
488
+        }
489
+
490
+        $this->aliases[$alias] = $abstract;
491
+
492
+        $this->abstractAliases[$abstract][] = $alias;
493
+    }
494
+
495
+    /**
496
+     * Bind a new callback to an abstract's rebind event.
497
+     *
498
+     * @param  string    $abstract
499
+     * @param  \Closure  $callback
500
+     * @return mixed
501
+     */
502
+    public function rebinding($abstract, Closure $callback)
503
+    {
504
+        $this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
505
+
506
+        if ($this->bound($abstract)) {
507
+            return $this->make($abstract);
508
+        }
509
+    }
510
+
511
+    /**
512
+     * Refresh an instance on the given target and method.
513
+     *
514
+     * @param  string  $abstract
515
+     * @param  mixed   $target
516
+     * @param  string  $method
517
+     * @return mixed
518
+     */
519
+    public function refresh($abstract, $target, $method)
520
+    {
521
+        return $this->rebinding($abstract, function ($app, $instance) use ($target, $method) {
522
+            $target->{$method}($instance);
523
+        });
524
+    }
525
+
526
+    /**
527
+     * Fire the "rebound" callbacks for the given abstract type.
528
+     *
529
+     * @param  string  $abstract
530
+     * @return void
531
+     */
532
+    protected function rebound($abstract)
533
+    {
534
+        $instance = $this->make($abstract);
535
+
536
+        foreach ($this->getReboundCallbacks($abstract) as $callback) {
537
+            call_user_func($callback, $this, $instance);
538
+        }
539
+    }
540
+
541
+    /**
542
+     * Get the rebound callbacks for a given type.
543
+     *
544
+     * @param  string  $abstract
545
+     * @return array
546
+     */
547
+    protected function getReboundCallbacks($abstract)
548
+    {
549
+        return $this->reboundCallbacks[$abstract] ?? [];
550
+    }
551
+
552
+    /**
553
+     * Wrap the given closure such that its dependencies will be injected when executed.
554
+     *
555
+     * @param  \Closure  $callback
556
+     * @param  array  $parameters
557
+     * @return \Closure
558
+     */
559
+    public function wrap(Closure $callback, array $parameters = [])
560
+    {
561
+        return function () use ($callback, $parameters) {
562
+            return $this->call($callback, $parameters);
563
+        };
564
+    }
565
+
566
+    /**
567
+     * Call the given Closure / class@method and inject its dependencies.
568
+     *
569
+     * @param  callable|string  $callback
570
+     * @param  array  $parameters
571
+     * @param  string|null  $defaultMethod
572
+     * @return mixed
573
+     */
574
+    public function call($callback, array $parameters = [], $defaultMethod = null)
575
+    {
576
+        return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
577
+    }
578
+
579
+    /**
580
+     * Get a closure to resolve the given type from the container.
581
+     *
582
+     * @param  string  $abstract
583
+     * @return \Closure
584
+     */
585
+    public function factory($abstract)
586
+    {
587
+        return function () use ($abstract) {
588
+            return $this->make($abstract);
589
+        };
590
+    }
591
+
592
+    /**
593
+     * An alias function name for make().
594
+     *
595
+     * @param  string  $abstract
596
+     * @param  array  $parameters
597
+     * @return mixed
598
+     */
599
+    public function makeWith($abstract, array $parameters = [])
600
+    {
601
+        return $this->make($abstract, $parameters);
602
+    }
603
+
604
+    /**
605
+     * Resolve the given type from the container.
606
+     *
607
+     * @param  string  $abstract
608
+     * @param  array  $parameters
609
+     * @return mixed
610
+     *
611
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
612
+     */
613
+    public function make($abstract, array $parameters = [])
614
+    {
615
+        return $this->resolve($abstract, $parameters);
616
+    }
617
+
618
+    /**
619
+     *  {@inheritdoc}
620
+     */
621
+    public function get($id)
622
+    {
623
+        try {
624
+            return $this->resolve($id);
625
+        } catch (Exception $e) {
626
+            if ($this->has($id)) {
627
+                throw $e;
628
+            }
629
+
630
+            throw new EntryNotFoundException($id);
631
+        }
632
+    }
633
+
634
+    /**
635
+     * Resolve the given type from the container.
636
+     *
637
+     * @param  string  $abstract
638
+     * @param  array  $parameters
639
+     * @param  bool   $raiseEvents
640
+     * @return mixed
641
+     *
642
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
643
+     */
644
+    protected function resolve($abstract, $parameters = [], $raiseEvents = true)
645
+    {
646
+        $abstract = $this->getAlias($abstract);
647
+
648
+        $needsContextualBuild = ! empty($parameters) || ! is_null(
649
+            $this->getContextualConcrete($abstract)
650
+        );
651
+
652
+        // If an instance of the type is currently being managed as a singleton we'll
653
+        // just return an existing instance instead of instantiating new instances
654
+        // so the developer can keep using the same objects instance every time.
655
+        if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
656
+            return $this->instances[$abstract];
657
+        }
658
+
659
+        $this->with[] = $parameters;
660
+
661
+        $concrete = $this->getConcrete($abstract);
662
+
663
+        // We're ready to instantiate an instance of the concrete type registered for
664
+        // the binding. This will instantiate the types, as well as resolve any of
665
+        // its "nested" dependencies recursively until all have gotten resolved.
666
+        if ($this->isBuildable($concrete, $abstract)) {
667
+            $object = $this->build($concrete);
668
+        } else {
669
+            $object = $this->make($concrete);
670
+        }
671
+
672
+        // If we defined any extenders for this type, we'll need to spin through them
673
+        // and apply them to the object being built. This allows for the extension
674
+        // of services, such as changing configuration or decorating the object.
675
+        foreach ($this->getExtenders($abstract) as $extender) {
676
+            $object = $extender($object, $this);
677
+        }
678
+
679
+        // If the requested type is registered as a singleton we'll want to cache off
680
+        // the instances in "memory" so we can return it later without creating an
681
+        // entirely new instance of an object on each subsequent request for it.
682
+        if ($this->isShared($abstract) && ! $needsContextualBuild) {
683
+            $this->instances[$abstract] = $object;
684
+        }
685
+
686
+        if ($raiseEvents) {
687
+            $this->fireResolvingCallbacks($abstract, $object);
688
+        }
689
+
690
+        // Before returning, we will also set the resolved flag to "true" and pop off
691
+        // the parameter overrides for this build. After those two things are done
692
+        // we will be ready to return back the fully constructed class instance.
693
+        $this->resolved[$abstract] = true;
694
+
695
+        array_pop($this->with);
696
+
697
+        return $object;
698
+    }
699
+
700
+    /**
701
+     * Get the concrete type for a given abstract.
702
+     *
703
+     * @param  string  $abstract
704
+     * @return mixed   $concrete
705
+     */
706
+    protected function getConcrete($abstract)
707
+    {
708
+        if (! is_null($concrete = $this->getContextualConcrete($abstract))) {
709
+            return $concrete;
710
+        }
711
+
712
+        // If we don't have a registered resolver or concrete for the type, we'll just
713
+        // assume each type is a concrete name and will attempt to resolve it as is
714
+        // since the container should be able to resolve concretes automatically.
715
+        if (isset($this->bindings[$abstract])) {
716
+            return $this->bindings[$abstract]['concrete'];
717
+        }
718
+
719
+        return $abstract;
720
+    }
721
+
722
+    /**
723
+     * Get the contextual concrete binding for the given abstract.
724
+     *
725
+     * @param  string  $abstract
726
+     * @return \Closure|string|null
727
+     */
728
+    protected function getContextualConcrete($abstract)
729
+    {
730
+        if (! is_null($binding = $this->findInContextualBindings($abstract))) {
731
+            return $binding;
732
+        }
733
+
734
+        // Next we need to see if a contextual binding might be bound under an alias of the
735
+        // given abstract type. So, we will need to check if any aliases exist with this
736
+        // type and then spin through them and check for contextual bindings on these.
737
+        if (empty($this->abstractAliases[$abstract])) {
738
+            return;
739
+        }
740
+
741
+        foreach ($this->abstractAliases[$abstract] as $alias) {
742
+            if (! is_null($binding = $this->findInContextualBindings($alias))) {
743
+                return $binding;
744
+            }
745
+        }
746
+    }
747
+
748
+    /**
749
+     * Find the concrete binding for the given abstract in the contextual binding array.
750
+     *
751
+     * @param  string  $abstract
752
+     * @return \Closure|string|null
753
+     */
754
+    protected function findInContextualBindings($abstract)
755
+    {
756
+        if (isset($this->contextual[end($this->buildStack)][$abstract])) {
757
+            return $this->contextual[end($this->buildStack)][$abstract];
758
+        }
759
+    }
760
+
761
+    /**
762
+     * Determine if the given concrete is buildable.
763
+     *
764
+     * @param  mixed   $concrete
765
+     * @param  string  $abstract
766
+     * @return bool
767
+     */
768
+    protected function isBuildable($concrete, $abstract)
769
+    {
770
+        return $concrete === $abstract || $concrete instanceof Closure;
771
+    }
772
+
773
+    /**
774
+     * Instantiate a concrete instance of the given type.
775
+     *
776
+     * @param  string  $concrete
777
+     * @return mixed
778
+     *
779
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
780
+     */
781
+    public function build($concrete)
782
+    {
783
+        // If the concrete type is actually a Closure, we will just execute it and
784
+        // hand back the results of the functions, which allows functions to be
785
+        // used as resolvers for more fine-tuned resolution of these objects.
786
+        if ($concrete instanceof Closure) {
787
+            return $concrete($this, $this->getLastParameterOverride());
788
+        }
789
+
790
+        $reflector = new ReflectionClass($concrete);
791
+
792
+        // If the type is not instantiable, the developer is attempting to resolve
793
+        // an abstract type such as an Interface or Abstract Class and there is
794
+        // no binding registered for the abstractions so we need to bail out.
795
+        if (! $reflector->isInstantiable()) {
796
+            return $this->notInstantiable($concrete);
797
+        }
798
+
799
+        $this->buildStack[] = $concrete;
800
+
801
+        $constructor = $reflector->getConstructor();
802
+
803
+        // If there are no constructors, that means there are no dependencies then
804
+        // we can just resolve the instances of the objects right away, without
805
+        // resolving any other types or dependencies out of these containers.
806
+        if (is_null($constructor)) {
807
+            array_pop($this->buildStack);
808
+
809
+            return new $concrete;
810
+        }
811
+
812
+        $dependencies = $constructor->getParameters();
813
+
814
+        // Once we have all the constructor's parameters we can create each of the
815
+        // dependency instances and then use the reflection instances to make a
816
+        // new instance of this class, injecting the created dependencies in.
817
+        try {
818
+            $instances = $this->resolveDependencies($dependencies);
819
+        } catch (BindingResolutionException $e) {
820
+            array_pop($this->buildStack);
821
+
822
+            throw $e;
823
+        }
824
+
825
+        array_pop($this->buildStack);
826
+
827
+        return $reflector->newInstanceArgs($instances);
828
+    }
829
+
830
+    /**
831
+     * Resolve all of the dependencies from the ReflectionParameters.
832
+     *
833
+     * @param  array  $dependencies
834
+     * @return array
835
+     *
836
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
837
+     */
838
+    protected function resolveDependencies(array $dependencies)
839
+    {
840
+        $results = [];
841
+
842
+        foreach ($dependencies as $dependency) {
843
+            // If this dependency has a override for this particular build we will use
844
+            // that instead as the value. Otherwise, we will continue with this run
845
+            // of resolutions and let reflection attempt to determine the result.
846
+            if ($this->hasParameterOverride($dependency)) {
847
+                $results[] = $this->getParameterOverride($dependency);
848
+
849
+                continue;
850
+            }
851
+
852
+            // If the class is null, it means the dependency is a string or some other
853
+            // primitive type which we can not resolve since it is not a class and
854
+            // we will just bomb out with an error since we have no-where to go.
855
+            $results[] = is_null($dependency->getClass())
856
+                            ? $this->resolvePrimitive($dependency)
857
+                            : $this->resolveClass($dependency);
858
+        }
859
+
860
+        return $results;
861
+    }
862
+
863
+    /**
864
+     * Determine if the given dependency has a parameter override.
865
+     *
866
+     * @param  \ReflectionParameter  $dependency
867
+     * @return bool
868
+     */
869
+    protected function hasParameterOverride($dependency)
870
+    {
871
+        return array_key_exists(
872
+            $dependency->name, $this->getLastParameterOverride()
873
+        );
874
+    }
875
+
876
+    /**
877
+     * Get a parameter override for a dependency.
878
+     *
879
+     * @param  \ReflectionParameter  $dependency
880
+     * @return mixed
881
+     */
882
+    protected function getParameterOverride($dependency)
883
+    {
884
+        return $this->getLastParameterOverride()[$dependency->name];
885
+    }
886
+
887
+    /**
888
+     * Get the last parameter override.
889
+     *
890
+     * @return array
891
+     */
892
+    protected function getLastParameterOverride()
893
+    {
894
+        return count($this->with) ? end($this->with) : [];
895
+    }
896
+
897
+    /**
898
+     * Resolve a non-class hinted primitive dependency.
899
+     *
900
+     * @param  \ReflectionParameter  $parameter
901
+     * @return mixed
902
+     *
903
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
904
+     */
905
+    protected function resolvePrimitive(ReflectionParameter $parameter)
906
+    {
907
+        if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
908
+            return $concrete instanceof Closure ? $concrete($this) : $concrete;
909
+        }
910
+
911
+        if ($parameter->isDefaultValueAvailable()) {
912
+            return $parameter->getDefaultValue();
913
+        }
914
+
915
+        $this->unresolvablePrimitive($parameter);
916
+    }
917
+
918
+    /**
919
+     * Resolve a class based dependency from the container.
920
+     *
921
+     * @param  \ReflectionParameter  $parameter
922
+     * @return mixed
923
+     *
924
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
925
+     */
926
+    protected function resolveClass(ReflectionParameter $parameter)
927
+    {
928
+        try {
929
+            return $this->make($parameter->getClass()->name);
930
+        }
931
+
932
+        // If we can not resolve the class instance, we will check to see if the value
933
+        // is optional, and if it is we will return the optional parameter value as
934
+        // the value of the dependency, similarly to how we do this with scalars.
935
+        catch (BindingResolutionException $e) {
936
+            if ($parameter->isOptional()) {
937
+                return $parameter->getDefaultValue();
938
+            }
939
+
940
+            throw $e;
941
+        }
942
+    }
943
+
944
+    /**
945
+     * Throw an exception that the concrete is not instantiable.
946
+     *
947
+     * @param  string  $concrete
948
+     * @return void
949
+     *
950
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
951
+     */
952
+    protected function notInstantiable($concrete)
953
+    {
954
+        if (! empty($this->buildStack)) {
955
+            $previous = implode(', ', $this->buildStack);
956
+
957
+            $message = "Target [$concrete] is not instantiable while building [$previous].";
958
+        } else {
959
+            $message = "Target [$concrete] is not instantiable.";
960
+        }
961
+
962
+        throw new BindingResolutionException($message);
963
+    }
964
+
965
+    /**
966
+     * Throw an exception for an unresolvable primitive.
967
+     *
968
+     * @param  \ReflectionParameter  $parameter
969
+     * @return void
970
+     *
971
+     * @throws \Illuminate\Contracts\Container\BindingResolutionException
972
+     */
973
+    protected function unresolvablePrimitive(ReflectionParameter $parameter)
974
+    {
975
+        $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";
976
+
977
+        throw new BindingResolutionException($message);
978
+    }
979
+
980
+    /**
981
+     * Register a new resolving callback.
982
+     *
983
+     * @param  \Closure|string  $abstract
984
+     * @param  \Closure|null  $callback
985
+     * @return void
986
+     */
987
+    public function resolving($abstract, Closure $callback = null)
988
+    {
989
+        if (is_string($abstract)) {
990
+            $abstract = $this->getAlias($abstract);
991
+        }
992
+
993
+        if (is_null($callback) && $abstract instanceof Closure) {
994
+            $this->globalResolvingCallbacks[] = $abstract;
995
+        } else {
996
+            $this->resolvingCallbacks[$abstract][] = $callback;
997
+        }
998
+    }
999
+
1000
+    /**
1001
+     * Register a new after resolving callback for all types.
1002
+     *
1003
+     * @param  \Closure|string  $abstract
1004
+     * @param  \Closure|null  $callback
1005
+     * @return void
1006
+     */
1007
+    public function afterResolving($abstract, Closure $callback = null)
1008
+    {
1009
+        if (is_string($abstract)) {
1010
+            $abstract = $this->getAlias($abstract);
1011
+        }
1012
+
1013
+        if ($abstract instanceof Closure && is_null($callback)) {
1014
+            $this->globalAfterResolvingCallbacks[] = $abstract;
1015
+        } else {
1016
+            $this->afterResolvingCallbacks[$abstract][] = $callback;
1017
+        }
1018
+    }
1019
+
1020
+    /**
1021
+     * Fire all of the resolving callbacks.
1022
+     *
1023
+     * @param  string  $abstract
1024
+     * @param  mixed   $object
1025
+     * @return void
1026
+     */
1027
+    protected function fireResolvingCallbacks($abstract, $object)
1028
+    {
1029
+        $this->fireCallbackArray($object, $this->globalResolvingCallbacks);
1030
+
1031
+        $this->fireCallbackArray(
1032
+            $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
1033
+        );
1034
+
1035
+        $this->fireAfterResolvingCallbacks($abstract, $object);
1036
+    }
1037
+
1038
+    /**
1039
+     * Fire all of the after resolving callbacks.
1040
+     *
1041
+     * @param  string  $abstract
1042
+     * @param  mixed   $object
1043
+     * @return void
1044
+     */
1045
+    protected function fireAfterResolvingCallbacks($abstract, $object)
1046
+    {
1047
+        $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);
1048
+
1049
+        $this->fireCallbackArray(
1050
+            $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
1051
+        );
1052
+    }
1053
+
1054
+    /**
1055
+     * Get all callbacks for a given type.
1056
+     *
1057
+     * @param  string  $abstract
1058
+     * @param  object  $object
1059
+     * @param  array   $callbacksPerType
1060
+     *
1061
+     * @return array
1062
+     */
1063
+    protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
1064
+    {
1065
+        $results = [];
1066
+
1067
+        foreach ($callbacksPerType as $type => $callbacks) {
1068
+            if ($type === $abstract || $object instanceof $type) {
1069
+                $results = array_merge($results, $callbacks);
1070
+            }
1071
+        }
1072
+
1073
+        return $results;
1074
+    }
1075
+
1076
+    /**
1077
+     * Fire an array of callbacks with an object.
1078
+     *
1079
+     * @param  mixed  $object
1080
+     * @param  array  $callbacks
1081
+     * @return void
1082
+     */
1083
+    protected function fireCallbackArray($object, array $callbacks)
1084
+    {
1085
+        foreach ($callbacks as $callback) {
1086
+            $callback($object, $this);
1087
+        }
1088
+    }
1089
+
1090
+    /**
1091
+     * Get the container's bindings.
1092
+     *
1093
+     * @return array
1094
+     */
1095
+    public function getBindings()
1096
+    {
1097
+        return $this->bindings;
1098
+    }
1099
+
1100
+    /**
1101
+     * Get the alias for an abstract if available.
1102
+     *
1103
+     * @param  string  $abstract
1104
+     * @return string
1105
+     */
1106
+    public function getAlias($abstract)
1107
+    {
1108
+        if (! isset($this->aliases[$abstract])) {
1109
+            return $abstract;
1110
+        }
1111
+
1112
+        return $this->getAlias($this->aliases[$abstract]);
1113
+    }
1114
+
1115
+    /**
1116
+     * Get the extender callbacks for a given type.
1117
+     *
1118
+     * @param  string  $abstract
1119
+     * @return array
1120
+     */
1121
+    protected function getExtenders($abstract)
1122
+    {
1123
+        $abstract = $this->getAlias($abstract);
1124
+
1125
+        return $this->extenders[$abstract] ?? [];
1126
+    }
1127
+
1128
+    /**
1129
+     * Remove all of the extender callbacks for a given type.
1130
+     *
1131
+     * @param  string  $abstract
1132
+     * @return void
1133
+     */
1134
+    public function forgetExtenders($abstract)
1135
+    {
1136
+        unset($this->extenders[$this->getAlias($abstract)]);
1137
+    }
1138
+
1139
+    /**
1140
+     * Drop all of the stale instances and aliases.
1141
+     *
1142
+     * @param  string  $abstract
1143
+     * @return void
1144
+     */
1145
+    protected function dropStaleInstances($abstract)
1146
+    {
1147
+        unset($this->instances[$abstract], $this->aliases[$abstract]);
1148
+    }
1149
+
1150
+    /**
1151
+     * Remove a resolved instance from the instance cache.
1152
+     *
1153
+     * @param  string  $abstract
1154
+     * @return void
1155
+     */
1156
+    public function forgetInstance($abstract)
1157
+    {
1158
+        unset($this->instances[$abstract]);
1159
+    }
1160
+
1161
+    /**
1162
+     * Clear all of the instances from the container.
1163
+     *
1164
+     * @return void
1165
+     */
1166
+    public function forgetInstances()
1167
+    {
1168
+        $this->instances = [];
1169
+    }
1170
+
1171
+    /**
1172
+     * Flush the container of all bindings and resolved instances.
1173
+     *
1174
+     * @return void
1175
+     */
1176
+    public function flush()
1177
+    {
1178
+        $this->aliases = [];
1179
+        $this->resolved = [];
1180
+        $this->bindings = [];
1181
+        $this->instances = [];
1182
+        $this->abstractAliases = [];
1183
+    }
1184
+
1185
+    /**
1186
+     * Set the globally available instance of the container.
1187
+     *
1188
+     * @return static
1189
+     */
1190
+    public static function getInstance()
1191
+    {
1192
+        if (is_null(static::$instance)) {
1193
+            static::$instance = new static;
1194
+        }
1195
+
1196
+        return static::$instance;
1197
+    }
1198
+
1199
+    /**
1200
+     * Set the shared instance of the container.
1201
+     *
1202
+     * @param  \Illuminate\Contracts\Container\Container|null  $container
1203
+     * @return \Illuminate\Contracts\Container\Container|static
1204
+     */
1205
+    public static function setInstance(ContainerContract $container = null)
1206
+    {
1207
+        return static::$instance = $container;
1208
+    }
1209
+
1210
+    /**
1211
+     * Determine if a given offset exists.
1212
+     *
1213
+     * @param  string  $key
1214
+     * @return bool
1215
+     */
1216
+    public function offsetExists($key)
1217
+    {
1218
+        return $this->bound($key);
1219
+    }
1220
+
1221
+    /**
1222
+     * Get the value at a given offset.
1223
+     *
1224
+     * @param  string  $key
1225
+     * @return mixed
1226
+     */
1227
+    public function offsetGet($key)
1228
+    {
1229
+        return $this->make($key);
1230
+    }
1231
+
1232
+    /**
1233
+     * Set the value at a given offset.
1234
+     *
1235
+     * @param  string  $key
1236
+     * @param  mixed   $value
1237
+     * @return void
1238
+     */
1239
+    public function offsetSet($key, $value)
1240
+    {
1241
+        $this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
1242
+            return $value;
1243
+        });
1244
+    }
1245
+
1246
+    /**
1247
+     * Unset the value at a given offset.
1248
+     *
1249
+     * @param  string  $key
1250
+     * @return void
1251
+     */
1252
+    public function offsetUnset($key)
1253
+    {
1254
+        unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
1255
+    }
1256
+
1257
+    /**
1258
+     * Dynamically access container services.
1259
+     *
1260
+     * @param  string  $key
1261
+     * @return mixed
1262
+     */
1263
+    public function __get($key)
1264
+    {
1265
+        return $this[$key];
1266
+    }
1267
+
1268
+    /**
1269
+     * Dynamically set container services.
1270
+     *
1271
+     * @param  string  $key
1272
+     * @param  mixed   $value
1273
+     * @return void
1274
+     */
1275
+    public function __set($key, $value)
1276
+    {
1277
+        $this[$key] = $value;
1278
+    }
1279
+}