Completed
Push — master ( ba5e19...f8eb70 )
by Bogdan
01:57
created

ContainerHydrator::addDefinitionMethods()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 3
eloc 5
nc 3
nop 2
crap 3.0416
1
<?php
2
3
/*
4
  +----------------------------------------------------------------------+
5
  | This file is part of the pinepain/container-extras PHP library.      |
6
  |                                                                      |
7
  | Copyright (c) 2015-2016 Bogdan Padalko <[email protected]>          |
8
  |                                                                      |
9
  | Licensed under the MIT license: http://opensource.org/licenses/MIT   |
10
  |                                                                      |
11
  | For the full copyright and license information, please view the      |
12
  | LICENSE file that was distributed with this source or visit          |
13
  | http://opensource.org/licenses/MIT                                   |
14
  +----------------------------------------------------------------------+
15
*/
16
17
/* Based on League\Container\Container v1.x class (https://github.com/thephpleague/container/blob/1.x/src/Container.php)
18
 * which is authored by Phil Bennett (https://github.com/philipobenito)
19
 * and other contributors (https://github.com/thephpleague/container/contributors).
20
 */
21
22
23
namespace Pinepain\Container\Extras;
24
25
26
use League\Container\ContainerInterface;
27
use League\Container\Definition\ClassDefinition;
28
use League\Container\Definition\DefinitionInterface;
29
use Traversable;
30
31
32
class ContainerHydrator
33
{
34
    /**
35
     * Populate the container with items from config
36
     *
37
     * @param ContainerInterface $container
38
     * @param  array|Traversable $config
39
     */
40 12
    public function populate(ContainerInterface $container, $config)
41
    {
42 12
        if (!is_array($config) && !($config instanceof Traversable)) {
43 1
            throw new \InvalidArgumentException(
44
                'You can only load definitions from an array or an object that implements Traversable interface.'
45 1
            );
46
        }
47
48 11
        if (empty($config)) {
49 1
            return;
50
        }
51
52 10
        $this->populateFromTraversable($container, $config);
53 10
    }
54
55 10
    protected function populateFromTraversable($container, $traversable)
56
    {
57 10
        foreach ($traversable as $alias => $options) {
58 9
            $this->createDefinition($container, $options, $alias);
59 10
        }
60 10
    }
61
62
    /**
63
     * Create a definition from a config entry
64
     *
65
     * @param ContainerInterface $container
66
     * @param  mixed             $options
67
     * @param  string            $alias
68
     *
69
     */
70 9
    protected function createDefinition(ContainerInterface $container, $options, $alias)
71
    {
72 9
        $concrete = $this->resolveConcrete($options);
73
74 9
        $share = is_array($options) && !empty($options['share']);
75
76
        // define in the container, with constructor arguments and method calls
77 9
        $definition = $container->add($alias, $concrete, $share);
78
79 9
        if ($definition instanceof DefinitionInterface) {
80 3
            $this->addDefinitionArguments($definition, $options);
81 3
        }
82
83 9
        if ($definition instanceof ClassDefinition) {
84 2
            $this->addDefinitionMethods($definition, $options);
85 2
        }
86 9
    }
87
88 3
    protected function addDefinitionArguments(DefinitionInterface $definition, $options)
89
    {
90 3
        if (!is_array($options)) {
91
            return;
92
        }
93
94 3
        $arguments = (array_key_exists('arguments', $options)) ? (array)$options['arguments'] : [];
95
96 3
        $definition->withArguments($arguments);
97 3
    }
98
99 2
    protected function addDefinitionMethods(ClassDefinition $definition, $options)
100
    {
101 2
        if (!is_array($options)) {
102
            return;
103
        }
104
105 2
        $methods = (array_key_exists('methods', $options)) ? (array)$options['methods'] : [];
106
107 2
        $definition->withMethodCalls($methods);
108 2
    }
109
110
    /**
111
     * Resolves the concrete class
112
     *
113
     * @param mixed $concrete
114
     *
115
     * @return mixed
116
     */
117 9
    protected function resolveConcrete($concrete)
118
    {
119 9
        if (is_array($concrete)) {
120 6
            if (array_key_exists('definition', $concrete)) {
121 1
                $concrete = $concrete['definition'];
122 6
            } elseif (array_key_exists('class', $concrete)) {
123 4
                $concrete = $concrete['class'];
124 4
            } else {
125 1
                $concrete = null;
126
            }
127 6
        }
128
129
        // if the concrete doesn't have a class associated with it then it
130
        // must be either a Closure or arbitrary type so we just bind that
131 9
        return $concrete;
132
    }
133
}
134