Completed
Push — develop ( b8f7b1...cea6ad )
by
unknown
07:05
created

OptionsAbstractFactory::canCreate()   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 2
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 Interop\Container\Exception\ContainerException;
15
use Zend\ServiceManager\AbstractFactoryInterface;
16
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
17
use Zend\ServiceManager\Exception\ServiceNotFoundException;
18
use Zend\ServiceManager\ServiceLocatorInterface;
19
use Zend\Stdlib\AbstractOptions;
20
21
/**
22
 * Creates options instances from configuration specifications.
23
 *
24
 * @author Mathias Gelhausen <[email protected]>
25
 * @since  0.23
26
 */
27
class OptionsAbstractFactory implements AbstractFactoryInterface
28
{
29
30
    /**
31
     * Simple mode handles only skalar values, arrays and POPOs.
32
     */
33
    const MODE_SIMPLE = 'simple';
34
35
    /**
36
     * Nested mode is able to handle other options instances as an option value.
37
     */
38
    const MODE_NESTED = 'nested';
39
40
    /**
41
     * The configuration specification of all creatable options instances.
42
     *
43
     * The format is
44
     * <pre>
45
     * [
46
     *      'ServiceNameOfTheOptionsInstance' => [
47
     *          'class' => 'FQCN of the options class.',
48
     *          'mode' => SIMPLE or NESTED (optional, default SIMPLE)
49
     *          'options' => [
50
     *              'simpleSkalar' => 'value',
51
     *              'simpleArray' => [ 'someArray' ],
52
     *              'nestedOptions' => [
53
     *                  '__class__' => 'FQCN of the nested options class.',
54
     *                  'someValue' => 'skalar'
55
     *              ],
56
     *          ],
57
     *      ],
58
     * ];
59
     *
60
     * @var array
61
     */
62
    protected $optionsConfig;
63
64
    /**
65
     * Create an object
66
     *
67
     * @param  ContainerInterface $container
68
     * @param  string             $requestedName
69
     * @param  null|array         $options
70
     *
71
     * @return object
72
     * @throws ServiceNotFoundException if unable to resolve the service.
73
     * @throws ServiceNotCreatedException if an exception is raised when
74
     *     creating a service.
75
     * @throws ContainerException if any other error occurs
76
     */
77
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
78
    {
79
        return new $requestedName();
80
    }
81
82
    /**
83
     * Can the factory create an instance for the service?
84
     *
85
     * @param  ContainerInterface $container
86
     * @param  string             $requestedName
87
     *
88
     * @return bool
89
     */
90
    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...
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
    {
92
        return class_exists($requestedName);
93
    }
94
95
96
    /**
97
     * Determines if we can create an options instance with name.
98
     *
99
     * @param ServiceLocatorInterface $serviceLocator
100
     * @param string                  $name
101
     * @param string                  $requestedName
102
     *
103
     * @return bool
104
     */
105
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
106
    {
107
        // Load options config specifications the first time this method is called.
108
        if (null === $this->optionsConfig) {
109
            $mainConfig          = $serviceLocator->get('config');
110
            $this->optionsConfig = isset($mainConfig['options']) ? $mainConfig['options'] : [];
111
        }
112
113
        return false !== $this->getOptionsConfig($requestedName, $name);
114
    }
115
116
    /**
117
     * Creates an options instance  with name.
118
     *
119
     * @param ServiceLocatorInterface $serviceLocator
120
     * @param string                  $name
121
     * @param string                  $requestedName
122
     *
123
     * @return AbstractOptions
124
     * @throws \InvalidArgumentException
125
     */
126
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
127
    {
128
        $config = $this->getOptionsConfig($requestedName, $name);
129
130
        if (!isset($config['class'])) {
131
            throw new \InvalidArgumentException(sprintf(
132
                                                    'Missing index "class" from the config array for options "%s"',
133
                                                    $requestedName
134
                                                ));
135
        }
136
137
        $className = $config['class'];
138
        $mode      = isset($config['mode']) ? $config['mode'] : self::MODE_SIMPLE;
139
        $options   = isset($config['options']) ? $config['options'] : [];
140
141
        if (self::MODE_SIMPLE == $mode) {
142
            return new $className($options);
143
        }
144
145
        if (self::MODE_NESTED == $mode) {
146
            return $this->createNestedOptions($className, $options);
147
148
        }
149
150
        throw new \InvalidArgumentException(sprintf('Unknown mode "%s".', $mode));
151
    }
152
153
154
    /**
155
     * Creates a nested options instance.
156
     *
157
     * @param string $className
158
     * @param array  $options
159
     *
160
     * @return AbstractOptions
161
     */
162
    protected function createNestedOptions($className, $options)
163
    {
164
        $class = new $className();
165
166
        foreach ($options as $key => $spec) {
167
            if (is_array($spec) && array_key_exists('__class__', $spec)) {
168
                $nestedClassName = $spec['__class__'];
169
                unset($spec['__class__']);
170
                $spec = $this->createNestedOptions($nestedClassName, $spec);
171
            }
172
173
            $class->{$key} = $spec;
174
        }
175
176
        return $class;
177
    }
178
179
    /**
180
     * Gets the configuration for a specific options instance.
181
     *
182
     * Returns FALSE if configuration cannot be found.
183
     *
184
     * @param string $fullName
185
     * @param string $normalizedName
186
     *
187
     * @return array|bool
188
     */
189
    protected function getOptionsConfig($fullName, $normalizedName)
190
    {
191
        if (array_key_exists($fullName, $this->optionsConfig)) {
192
            return $this->optionsConfig[$fullName];
193
        }
194
195
        if (array_key_exists($normalizedName, $this->optionsConfig)) {
196
            return $this->optionsConfig[$normalizedName];
197
        }
198
199
        return false;
200
    }
201
}