GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 383204...57b219 )
by Hong
02:44
created

Container::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 8
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Di
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Di;
16
17
use Phossa2\Config\Config;
18
use Phossa2\Di\Message\Message;
19
use Phossa2\Di\Factory\Factory;
20
use Phossa2\Di\Resolver\Resolver;
21
use Phossa2\Di\Traits\ContainerTrait;
22
use Phossa2\Di\Traits\ArrayAccessTrait;
23
use Phossa2\Shared\Base\ObjectAbstract;
24
use Interop\Container\ContainerInterface;
25
use Phossa2\Di\Interfaces\ScopeInterface;
26
use Phossa2\Di\Exception\RuntimeException;
27
use Phossa2\Di\Exception\NotFoundException;
28
use Phossa2\Config\Interfaces\ConfigInterface;
29
use Phossa2\Shared\Reference\DelegatorInterface;
30
use Phossa2\Config\Interfaces\WritableInterface;
31
use Phossa2\Di\Interfaces\FactoryAwareInterface;
32
use Phossa2\Di\Interfaces\ResolverAwareInterface;
33
use Phossa2\Shared\Reference\DelegatorAwareTrait;
34
use Phossa2\Di\Interfaces\ExtendedContainerInterface;
35
use Phossa2\Shared\Reference\DelegatorAwareInterface;
36
37
/**
38
 * Container
39
 *
40
 * A writable, array accessable, delegator-aware and extended instance container.
41
 *
42
 * - writable:
43
 *
44
 *   ```php
45
 *   $container->set('cache', $cache);
46
 *   ```
47
 *
48
 * - array accessable:
49
 *
50
 *   ```php
51
 *   // get
52
 *   $cache = $container['cache'];
53
 *
54
 *   // set/replace
55
 *   $container['cache'] = $anotherCache;
56
 *   ```
57
 *
58
 * - delegator-aware: lookup dependent instances in the delegator
59
 *
60
 *   ```php
61
 *   $delegator->addRegistry($container);
62
 *   ```
63
 *
64
 * - extended container
65
 *
66
 *   ```php
67
 *   // get new instance
68
 *   $newCache = $container->one('cache');
69
 *
70
 *   // run callables
71
 *   $container->run(['${#logger}', 'warning'], ['A warning message from ${user}']);
72
 *   ```
73
 *
74
 * @package Phossa2\Di
75
 * @author  Hong Zhang <[email protected]>
76
 * @see     ObjectAbstract
77
 * @see     ScopeInterface
78
 * @see     ContainerInterface
79
 * @see     ResolverAwareInterface
80
 * @see     FactoryAwareInterface
81
 * @see     ExtendedContainerInterface
82
 * @see     DelegatorAwareInterface
83
 * @see     WritableInterface
84
 * @see     \ArrayAccess
85
 * @version 2.0.0
86
 * @since   2.0.0 added
87
 */
88
class Container extends ObjectAbstract implements ContainerInterface, ResolverAwareInterface, FactoryAwareInterface, ScopeInterface, ExtendedContainerInterface, DelegatorAwareInterface, \ArrayAccess, WritableInterface
89
{
90
    use ContainerTrait, ArrayAccessTrait, DelegatorAwareTrait;
91
92
    /**
93
     * Inject a Phossa2\Config\Config
94
     *
95
     * ```php
96
     * $configData = [
97
     *     // container class
98
     *     'di.class' => 'Phossa2\\Di\\Container',
99
     *
100
     *     // container service definitions
101
     *     'di.service' => [
102
     *         // ...
103
     *     ],
104
     *
105
     *     // interface/classname mappings
106
     *     'di.mapping' => [
107
     *     ],
108
     *
109
     *     // init methods to run after container created
110
     *     'di.init' => [
111
     *         'default' => [],
112
     *         'mystuff' => [ ... ],
113
     *     ],
114
     * ];
115
     *
116
     * // instantiate $config
117
     * $config = new Config(null, null, $configData);
118
     *
119
     * // instantiate container
120
     * $container = new $config['di.class']($config);
121
     * ```
122
     *
123
     * @param  ConfigInterface $config inject the config instance
124
     * @param  string $baseNode container's starting node in $config
125
     * @param  bool $writable able to inject object to the container
126
     * @access public
127
     */
128
    public function __construct(
129
        ConfigInterface $config = null,
130
        /*# string */ $baseNode = 'di',
131
        /*# bool */ $writable = true
132
    ) {
133
        // config injected ?
134
        if (null === $config) {
135
            $config = new Config();
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $config. This often makes code more readable.
Loading history...
136
        }
137
138
        // container writable ?
139
        if ($config instanceof WritableInterface) {
140
            $this->setWritable($writable);
141
            $config->setWritable($writable);
142
        }
143
144
        // setup the $resolver
145
        $this->setResolver(new Resolver($this, $config, $baseNode));
146
147
        // instance factory
148
        $this->setFactory(new Factory($this));
149
150
        // register $this as 'di.service.container' in the resolver
151
        $this->registerSelf();
152
153
        // execute init methods defined in 'di.init' node of the $config
154
        $this->initContainer();
155
    }
156
157
    /**
158
     * Extensions to the Interop\Container\ContainerInterface
159
     *
160
     * - Accepting second param as object constructor arguments
161
     * - Accpeting $id with scope appended, e.g. 'cache@myScope'
162
     *
163
     * {@inheritDoc}
164
     */
165
    public function get($id)
166
    {
167
        // not found
168
        if (!$this->has($id)) {
169
            throw new NotFoundException(
170
                Message::get(Message::DI_SERVICE_NOTFOUND, $id),
171
                Message::DI_SERVICE_NOTFOUND
172
            );
173
        }
174
175
        // get the instance, constructor args if any
176
        return $this->getInstance(
177
            $id, func_num_args() > 1 ? func_get_arg(1) : []
178
        );
179
    }
180
181
    /**
182
     * Extensions to the Interop\Container\ContainerInterface
183
     *
184
     * - Accpeting $id with scope appended, e.g. 'cache@myScope'
185
     *
186
     * {@inheritDoc}
187
     */
188
    public function has($id)
189
    {
190
        if (is_string($id)) {
191
            return $this->getResolver()->hasService(
192
                $this->idWithoutScope($id)
193
            );
194
        }
195
        return false;
196
    }
197
198
    /**
199
     * {@inheritDoc}
200
     */
201
    public function set(/*# string */ $id, $value)
202
    {
203
        if ($this->isWritable()) {
204
            // set in service definition
205
            $this->getResolver()->setService(
206
                $this->idWithoutScope($id),
207
                $value
208
            );
209
            return $this;
210
        } else {
211
            throw new RuntimeException(
212
                Message::get(Message::DI_CONTAINER_READONLY, $id),
213
                Message::DI_CONTAINER_READONLY
214
            );
215
        }
216
    }
217
218
    /**
219
     * {@inheritDoc}
220
     */
221
    public function one(/*# string */ $id, array $arguments = [])
222
    {
223
        // set in single scope
224
        return $this->get(
225
            $this->scopedId($id, self::SCOPE_SINGLE),
226
            $arguments
227
        );
228
    }
229
230
    /**
231
     * {@inheritDoc}
232
     */
233
    public function run($callable, array $arguments = [])
234
    {
235
        // resolve any references in the callable(array) and arguments
236
        $this->resolve($callable);
237
        $this->resolve($arguments);
238
239
        return $this->getFactory()->executeCallable($callable, $arguments);
240
    }
241
242
    /**
243
     * {@inheritDoc}
244
     */
245
    public function resolve(&$toResolve)
246
    {
247
        $this->getResolver()->resolve($toResolve);
248
        return $this;
249
    }
250
251
    /**
252
     * - Overwrite `setDelegator()` from DelegatorAwareTrait
253
     * - Update resolver $object_resolver
254
     *
255
     * {@inheritDoc}
256
     */
257
    public function setDelegator(DelegatorInterface $delegator)
258
    {
259
        $this->delegator = $delegator;
260
        $this->getResolver()->setObjectResolver();
261
        return $this;
262
    }
263
264
    /**
265
     * Register $this as 'di.service.container'
266
     *
267
     * - Later, $this can be referenced as '${#container}' anywhere
268
     *
269
     * - $skipCommon is to demonstrate skipping execute common methods for objects.
270
     *
271
     *   instead of just do
272
     *      `$container->set($name, $object)`
273
     *
274
     *   you may do
275
     *      $container->set($name, ['class' => $object, 'skip' => true]);
276
     *
277
     * @param  bool $skipCommon skip common methods normally after instantiation
278
     * @return $this
279
     * @access protected
280
     */
281
    protected function registerSelf(/*# bool */ $skipCommon = false)
282
    {
283
        $name = 'container';
284
        if (!$this->has($name) && $this->isWritable()) {
285
            $this->set(
286
                $name,
287
                ['class' => $this, 'skip' => $skipCommon]
288
            );
289
        }
290
    }
291
}
292