Completed
Push — master ( 0c48af...84ef19 )
by Johannes
02:34
created

ExpressiveAuraConfig::define()   C

Complexity

Conditions 11
Paths 49

Size

Total Lines 48
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 48
rs 5.2653
cc 11
eloc 20
nc 49
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Lichtenwallner  (https://lichtenwallner.at)
5
 *
6
 * @see https://github.com/jolicht/markdown-cms for the canonical source repository
7
 * @license https://github.com/jolicht/markdown-cms/blob/master/LICENSE MIT
8
 * @copyright Copyright (c) Johannes Lichtenwallner
9
 */
10
declare(strict_types = 1);
11
namespace JolichtTest\MarkdownCms;
12
13
use ArrayObject;
14
use Aura\Di\Container;
15
use Aura\Di\ContainerConfigInterface;
16
17
/**
18
 * Configuration for the Aura.Di container.
19
 *
20
 * This class provides functionality for the following service types:
21
 *
22
 * - Aliases
23
 * - Delegators
24
 * - Factories
25
 * - Invokable classes
26
 * - Services (known instances)
27
 */
28
class ExpressiveAuraConfig implements ContainerConfigInterface
29
{
30
    /**
31
     * @var array
32
     */
33
    private $config;
34
35
    /**
36
     * @param array $config
37
     */
38
    public function __construct(array $config)
39
    {
40
        $this->config = $config;
41
    }
42
43
    /**
44
     * Configure the container
45
     *
46
     * - Adds the 'config' service.
47
     * - If delegators are defined, maps the service to lazyGetCall an
48
     *   ExpressiveAuraDelegatorFactory::build invocation using the configured
49
     *   delegator and whatever factory was responsible for it.
50
     * - If factories are defined, maps each factory class as a lazily
51
     *   instantiable service, and the service to lazyGetCall the factory to
52
     *   create the instance.
53
     * - If invokables are defined, maps each to lazyNew the target.
54
     * - If aliases are defined, maps each to lazyGet the target.
55
     *
56
     * @param Container $container
57
     * @return void
58
     */
59
    public function define(Container $container)
60
    {
61
        // Convert config to an object and inject it
62
        $container->set('config', new ArrayObject($this->config, ArrayObject::ARRAY_AS_PROPS));
63
64
        if (empty($this->config['dependencies'])) {
65
            return;
66
        }
67
68
        $dependencies = $this->config['dependencies'];
69
70
        // Inject delegator factories
71
        // This is done early because Aura.Di does not allow modification of a
72
        // service after creation. As such, we need to create custom factories
73
        // for each service with delegators.
74
        if (isset($dependencies['delegators'])) {
75
            $dependencies = $this->marshalDelegators($container, $dependencies);
76
        }
77
78
        // Inject services
79
        if (isset($dependencies['services'])) {
80
            foreach ($dependencies['services'] as $name => $service) {
81
                $container->set($name, $service);
82
            }
83
        }
84
85
        // Inject factories
86
        if (isset($dependencies['factories'])) {
87
            foreach ($dependencies['factories'] as $service => $factory) {
88
                $container->set($factory, $container->lazyNew($factory));
89
                $container->set($service, $container->lazyGetCall($factory, '__invoke', $container));
90
            }
91
        }
92
93
        // Inject invokables
94
        if (isset($dependencies['invokables'])) {
95
            foreach ($dependencies['invokables'] as $service => $class) {
96
                $container->set($service, $container->lazyNew($class));
97
            }
98
        }
99
100
        // Inject aliases
101
        if (isset($dependencies['aliases'])) {
102
            foreach ($dependencies['aliases'] as $alias => $target) {
103
                $container->set($alias, $container->lazyGet($target));
104
            }
105
        }
106
    }
107
108
    /**
109
     * This method is purposely a no-op.
110
     *
111
     * @param Container $container
112
     * @return void
113
     */
114
    public function modify(Container $container)
115
    {
116
    }
117
118
    /**
119
     * Marshal all services with delegators.
120
     *
121
     * @param Container $container
122
     * @param array $dependencies
123
     * @return array List of dependencies minus any services, factories, or
124
     *     invokables that match services using delegator factories.
125
     */
126
    private function marshalDelegators(Container $container, array $dependencies)
127
    {
128
        foreach ($dependencies['delegators'] as $service => $delegatorNames) {
129
            $factory = null;
130
131
            if (isset($dependencies['services'][$service])) {
132
                // Marshal from service
133
                $instance = $dependencies['services'][$service];
134
                $factory = function () use ($instance) {
135
                    return $instance;
136
                };
137
                unset($dependencies['service'][$service]);
138
            }
139
140
            if (isset($dependencies['factories'][$service])) {
141
                // Marshal from factory
142
                $serviceFactory = $dependencies['factories'][$service];
143
                $factory = function () use ($service, $serviceFactory, $container) {
144
                    return $serviceFactory($container, $service);
145
                };
146
                unset($dependencies['factories'][$service]);
147
            }
148
149
            if (isset($dependencies['invokables'][$service])) {
150
                // Marshal from invokable
151
                $class = $dependencies['invokables'][$service];
152
                $factory = function () use ($class) {
153
                    return new $class();
154
                };
155
                unset($dependencies['invokables'][$service]);
156
            }
157
158
            if (! is_callable($factory)) {
159
                continue;
160
            }
161
162
            $delegatorFactory = new ExpressiveAuraDelegatorFactory($delegatorNames, $factory);
163
            $container->set(
164
                $service,
165
                $container->lazyGetCall($delegatorFactory, 'build', $container, $service)
166
            );
167
        }
168
169
        return $dependencies;
170
    }
171
}
172