Completed
Push — develop ( ca20ca...7c50fe )
by
unknown
06:59
created

OptionsAbstractFactory::createServiceWithName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 3
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license    MIT
7
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
8
 */
9
10
/** */
11
namespace Core\Factory;
12
13
use Interop\Container\ContainerInterface;
14
use Zend\ServiceManager\AbstractFactoryInterface;
15
use Zend\ServiceManager\ServiceLocatorInterface;
16
use Zend\Stdlib\AbstractOptions;
17
18
/**
19
 * Creates options instances from configuration specifications.
20
 *
21
 * @author Mathias Gelhausen <[email protected]>
22
 * @since  0.23
23
 */
24
class OptionsAbstractFactory implements AbstractFactoryInterface
25
{
26
27
    /**
28
     * Simple mode handles only skalar values, arrays and POPOs.
29
     */
30
    const MODE_SIMPLE = 'simple';
31
32
    /**
33
     * Nested mode is able to handle other options instances as an option value.
34
     */
35
    const MODE_NESTED = 'nested';
36
37
    /**
38
     * The configuration specification of all creatable options instances.
39
     *
40
     * The format is
41
     * <pre>
42
     * [
43
     *      'ServiceNameOfTheOptionsInstance' => [
44
     *          'class' => 'FQCN of the options class.',
45
     *          'mode' => SIMPLE or NESTED (optional, default SIMPLE)
46
     *          'options' => [
47
     *              'simpleSkalar' => 'value',
48
     *              'simpleArray' => [ 'someArray' ],
49
     *              'nestedOptions' => [
50
     *                  '__class__' => 'FQCN of the nested options class.',
51
     *                  'someValue' => 'skalar'
52
     *              ],
53
     *          ],
54
     *      ],
55
     * ];
56
     *
57
     * @var array
58
     */
59
    protected $optionsConfig;
60
61
    /**
62
     * Create an object
63
     *
64
     * @param  ContainerInterface $container
65
     * @param  string             $requestedName
66
     * @param  null|array         $options
67
     *
68
     * @return object
69
     */
70
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
71
    {
72
        $config = $this->getOptionsConfig($requestedName);
73
74
        if (!isset($config['class']) && !class_exists($requestedName)) {
75
            throw new \InvalidArgumentException(sprintf(
76
                'Missing index "class" from the config array for options "%s"',
77
                $requestedName
78
            ));
79
        }
80
81
        $className = isset($config['class']) ? $config['class'] : $requestedName;
82
        $mode      = isset($config['mode']) ? $config['mode'] : self::MODE_SIMPLE;
83
        $options   = isset($config['options']) ? $config['options'] : (isset($config[0]) ? $config[0] : []);
84
85
        if (self::MODE_SIMPLE == $mode) {
86
            return new $className($options);
87
        }
88
89
        if (self::MODE_NESTED == $mode) {
90
            return $this->createNestedOptions($className, $options);
91
92
        }
93
94
        throw new \InvalidArgumentException(sprintf('Unknown mode "%s".', $mode));
95
    }
96
97
    /**
98
     * Can the factory create an instance for the service?
99
     *
100
     * @param  ContainerInterface $container
101
     * @param  string             $requestedName
102
     *
103
     * @return bool
104
     */
105
    public function canCreate(ContainerInterface $container, $requestedName)
0 ignored issues
show
Coding Style introduced by
function canCreate() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
106
    {
107
        // Load options config specifications the first time this method is called.
108
        if (null === $this->optionsConfig) {
109
            $mainConfig          = $container->get('config');
110
            $this->optionsConfig = isset($mainConfig['options']) ? $mainConfig['options'] : [];
111
        }
112
        return false !== $this->getOptionsConfig($requestedName);
113
    }
114
115
116
    /**
117
     * Determines if we can create an options instance with name.
118
     *
119
     * @param ServiceLocatorInterface $serviceLocator
120
     * @param string                  $name
121
     * @param string                  $requestedName
122
     *
123
     * @return bool
124
     */
125
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
126
    {
127
        return $this->canCreate($serviceLocator, $requestedName);
128
    }
129
130
    /**
131
     * Creates an options instance  with name.
132
     *
133
     * @param ServiceLocatorInterface $serviceLocator
134
     * @param string                  $name
135
     * @param string                  $requestedName
136
     *
137
     * @return AbstractOptions
138
     * @throws \InvalidArgumentException
139
     */
140
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
141
    {
142
        return $this($serviceLocator, $requestedName);
143
    }
144
145
146
    /**
147
     * Creates a nested options instance.
148
     *
149
     * @param string $className
150
     * @param array  $options
151
     *
152
     * @return AbstractOptions
153
     */
154
    protected function createNestedOptions($className, $options)
155
    {
156
        $class = new $className();
157
158
        foreach ($options as $key => $spec) {
159
            if (is_array($spec) && array_key_exists('__class__', $spec)) {
160
                $nestedClassName = $spec['__class__'];
161
                unset($spec['__class__']);
162
                $spec = $this->createNestedOptions($nestedClassName, $spec);
163
            }
164
165
            $class->{$key} = $spec;
166
        }
167
168
        return $class;
169
    }
170
171
    /**
172
     * Gets the configuration for a specific options instance.
173
     *
174
     * Returns FALSE if configuration cannot be found.
175
     *
176
     * @param string $fullName
177
     * @param string $normalizedName
0 ignored issues
show
Bug introduced by
There is no parameter named $normalizedName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
178
     *
179
     * @return array|bool
180
     */
181
    protected function getOptionsConfig($fullName)
182
    {
183
        if (array_key_exists($fullName, $this->optionsConfig)) {
184
            return $this->optionsConfig[$fullName];
185
        }
186
187
        return false;
188
    }
189
}