Objects::__construct()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 2
crap 3
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Caridea
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
 * use this file except in compliance with the License. You may obtain a copy of
8
 * the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
 * License for the specific language governing permissions and limitations under
16
 * the License.
17
 *
18
 * @copyright 2015-2018 LibreWorks contributors
19
 * @license   Apache-2.0
20
 */
21
namespace Caridea\Container;
22
23
/**
24
 * A concrete, immutable dependency injection container with event publishing capabilities.
25
 *
26
 * @copyright 2015-2018 LibreWorks contributors
27
 * @license   Apache-2.0
28
 */
29
class Objects extends AbstractContainer implements \Caridea\Event\Publisher
30
{
31
    /**
32
     * @var \Caridea\Container\Provider[] Associative array of string names to providers
33
     */
34
    protected $providers = [];
35
    /**
36
     * @var \SplObjectStorage A collection of event listeners
37
     */
38
    protected $listeners;
39
40
    /**
41
     * Creates a new Object container.
42
     *
43
     * You might find it easier to use the `Builder` instead of this
44
     * constructor. Compare this first example…
45
     *
46
     * ```php
47
     * $props = new \Caridea\Container\Properties([
48
     *     'mail.host' => 'mail.example.net'
49
     * ]);
50
     * $objects = new \Caridea\Container\Objects([
51
     *     'mailService' => new Provider('My\Mail\Service', function($c){
52
     *         return new \My\Mail\Service($c['mail.host']);
53
     *     }, true),
54
     *     'userService' => new Provider('My\User\Service', function($c){
55
     *         return new \My\User\Service($c['mailService']);
56
     *     }, false)
57
     * ], $props);
58
     * ```
59
     *
60
     * …to this one:
61
     *
62
     * ```php
63
     * $props = new \Caridea\Container\Properties([
64
     *     'mail.host' => 'mail.example.net'
65
     * ]);
66
     * $objects = \Caridea\Container\Objects::builder()
67
     *     ->lazy('mailService', 'My\Mail\Service', function($c){
68
     *         return new \My\Mail\Service($c['mail.host']);
69
     *     })
70
     *     ->proto('userService', 'My\User\Service', function($c){
71
     *         return new \My\User\Service($c['mailService']);
72
     *     })
73
     *     ->build($props);
74
     * ```
75
     *
76
     * @param \Caridea\Container\Provider[] $providers with names as keys
77
     * @param \Caridea\Container\Container $parent An optional parent container
78
     */
79 4
    public function __construct(array $providers, Container $parent = null)
80
    {
81 4
        $types = [];
82 4
        foreach ($providers as $k => $v) {
83 4
            if ($v instanceof Provider) {
84 4
                $this->providers[(string)$k] = $v;
85 4
                $types[(string)$k] = $v->getType();
86
            }
87
        }
88 4
        parent::__construct($types, $parent);
89 4
        $this->listeners = new \SplObjectStorage();
90 4
    }
91
92
    /**
93
     * Creates a new Builder.
94
     *
95
     * @return \Caridea\Container\Builder A new `Objects` builder
96
     */
97 1
    public static function builder(): Builder
98
    {
99 1
        return new Builder();
100
    }
101
102
    /**
103
     * Retrieves the value
104
     *
105
     * @param string $name The value name
106
     */
107 5
    protected function doGet(string $name)
108
    {
109 5
        $value = $this->providers[$name]->get($this);
110 5
        $type = $this->types[$name];
111 5
        if (!($value instanceof $type)) {
112 2
            throw new \UnexpectedValueException("The value that came from the "
113 2
                . "provider was supposed to be a $type, but it returned a "
114 2
                . (is_object($value) ? get_class($value) : gettype($value)));
115
        }
116 3
        if ($value instanceof ContainerAware) {
117 1
            $value->setContainer($this);
118
        }
119 3
        if ($value instanceof \Caridea\Event\PublisherAware) {
120 1
            $value->setPublisher($this);
121
        }
122 3
        if ($value instanceof \Caridea\Event\Listener) {
123
            // SplObjectStorage is a set; it will only ever contain uniques
124 2
            $this->listeners->attach($value);
125
        }
126 3
        return $value;
127
    }
128
129
    /**
130
     * Queues an event to be sent to Listeners.
131
     *
132
     * @param \Caridea\Event\Event $event The event to publish
133
     */
134 2
    public function publish(\Caridea\Event\Event $event)
135
    {
136 2
        foreach (iterator_to_array($this->listeners) as $listener) {
137 2
            $listener->notify($event);
138
        }
139 2
    }
140
}
141