Completed
Push — master ( e4e35c...27cf60 )
by Walter
03:25
created

EngineFactory   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 9
Bugs 1 Features 3
Metric Value
wmc 36
c 9
b 1
f 3
lcom 1
cbo 7
dl 0
loc 187
rs 8.8

10 Methods

Rating   Name   Duplication   Size   Complexity  
A createService() 0 20 1
A loadService() 0 12 3
A loadTests() 0 10 3
B loadTest() 0 23 4
B loadTestVariants() 0 27 6
B loadTestVariant() 0 23 5
A loadTestVariantCallback() 0 12 3
C loadTestVariantEventManager() 0 36 8
A loadTestVariantSimple() 0 4 1
A loadTestVariantFromServiceManager() 0 8 2
1
<?php
2
/**
3
 * This file is part of phpab/phpab-module. (https://github.com/phpab/phpab-module)
4
 *
5
 * @link https://github.com/phpab/phpab-module for the canonical source repository
6
 * @copyright Copyright (c) 2015-2016 phpab. (https://github.com/phpab/)
7
 * @license https://raw.githubusercontent.com/phpab/phpab-module/master/LICENSE MIT
8
 */
9
10
namespace PhpAbModule\Service;
11
12
use PhpAb\Engine\Engine;
13
use PhpAb\Engine\EngineInterface;
14
use PhpAb\Event\DispatcherInterface;
15
use PhpAb\Participation\ParticipationManagerInterface;
16
use PhpAb\Test\Test;
17
use PhpAb\Variant\CallbackVariant;
18
use PhpAb\Variant\SimpleVariant;
19
use PhpAbModule\Variant\EventManagerVariant;
20
use RuntimeException;
21
use Zend\ServiceManager\FactoryInterface;
22
use Zend\ServiceManager\ServiceLocatorInterface;
23
24
class EngineFactory implements FactoryInterface
25
{
26
    public function createService(ServiceLocatorInterface $serviceLocator)
27
    {
28
        /** @var array $config */
29
        $config = $serviceLocator->get('Config');
30
31
        /** @var ParticipationManagerInterface $participationManager */
32
        $participationManager = $serviceLocator->get('phpab.participation_manager');
33
34
        /** @var DispatcherInterface $dispatcher */
35
        $dispatcher = $serviceLocator->get('phpab.dispatcher');
36
37
        $filter = $this->loadService($serviceLocator, $config['phpab'], 'default_filter');
38
        $chooser = $this->loadService($serviceLocator, $config['phpab'], 'default_variant_chooser');
39
40
        $engine = new Engine($participationManager, $dispatcher, $filter, $chooser);
0 ignored issues
show
Bug introduced by
It seems like $filter defined by $this->loadService($serv...ab'], 'default_filter') on line 37 can also be of type array or object; however, PhpAb\Engine\Engine::__construct() does only seem to accept null|object<PhpAb\Participation\FilterInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $chooser defined by $this->loadService($serv...fault_variant_chooser') on line 38 can also be of type array or object; however, PhpAb\Engine\Engine::__construct() does only seem to accept null|object<PhpAb\Variant\ChooserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
41
42
        $this->loadTests($engine, $serviceLocator, $config['phpab']);
43
44
        return $engine;
45
    }
46
47
    private function loadService(ServiceLocatorInterface $serviceLocator, $config, $serviceName)
48
    {
49
        if (!array_key_exists($serviceName, $config)) {
50
            return null;
51
        }
52
53
        if (!$serviceLocator->has($config[$serviceName])) {
54
            return null;
55
        }
56
57
        return $serviceLocator->get($config[$serviceName]);
58
    }
59
60
    private function loadTests(EngineInterface $engine, ServiceLocatorInterface $serviceLocator, $config)
61
    {
62
        if (!array_key_exists('tests', $config)) {
63
            return;
64
        }
65
        
66
        foreach ($config['tests'] as $identifier => $testConfig) {
67
            $this->loadTest($serviceLocator, $engine, $identifier, $testConfig);
68
        }
69
    }
70
71
    private function loadTest(
72
        ServiceLocatorInterface $serviceLocator,
73
        EngineInterface $engine,
74
        $identifier,
75
        array $config
76
    ) {
77
        $filter = null;
78
        if (array_key_exists('filter', $config)) {
79
            $filter = $serviceLocator->get($config['filter']);
80
        }
81
82
        $variantChooser = null;
83
        if (array_key_exists('variant_chooser', $config)) {
84
            $variantChooser = $serviceLocator->get($config['variant_chooser']);
85
        }
86
87
        $variants = $this->loadTestVariants($serviceLocator, $config);
88
        $options = array_key_exists('options', $config) ? $config['options'] : [];
89
90
        $test = new Test($identifier, $variants);
91
92
        $engine->addTest($test, $options, $filter, $variantChooser);
0 ignored issues
show
Bug introduced by
It seems like $filter defined by $serviceLocator->get($config['filter']) on line 79 can also be of type array or object; however, PhpAb\Engine\EngineInterface::addTest() does only seem to accept null|object<PhpAb\Participation\FilterInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $variantChooser defined by $serviceLocator->get($config['variant_chooser']) on line 84 can also be of type array or object; however, PhpAb\Engine\EngineInterface::addTest() does only seem to accept null|object<PhpAb\Variant\ChooserInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
93
    }
94
95
    private function loadTestVariants(ServiceLocatorInterface $serviceLocator, $config)
96
    {
97
        $variants = [];
98
99
        if (!array_key_exists('variants', $config)) {
100
            return $variants;
101
        }
102
103
        foreach ($config['variants'] as $identifier => $variant) {
104
            // We also support shortcuts so that the user can specify a service name straight away.
105
            if (is_string($variant)) {
106
                $variant = [
107
                    'type' => $variant,
108
                ];
109
            }
110
111
            if (!array_key_exists('type', $variant)) {
112
                throw new RuntimeException('The type of the variant is missing.');
113
            }
114
115
            $options = empty($variant['options']) ? [] : $variant['options'];
116
117
            $variants[] = $this->loadTestVariant($serviceLocator, $variant['type'], $identifier, $options);
118
        }
119
120
        return $variants;
121
    }
122
123
    private function loadTestVariant(ServiceLocatorInterface $serviceLocator, $type, $identifier, array $options)
124
    {
125
        switch ($type) {
126
            case 'callback':
127
                $variant = $this->loadTestVariantCallback($serviceLocator, $identifier, $options);
128
                break;
129
130
            case 'event_manager':
131
                $variant = $this->loadTestVariantEventManager($serviceLocator, $identifier, $options);
132
                break;
133
134
            case 'simple':
135
                $variant = $this->loadTestVariantSimple($serviceLocator, $identifier, $options);
136
                break;
137
138
            case 'service_manager':
139
            default:
140
                $variant = $this->loadTestVariantFromServiceManager($serviceLocator, $type);
141
                break;
142
        }
143
144
        return $variant;
145
    }
146
147
    private function loadTestVariantCallback(ServiceLocatorInterface $serviceLocator, $identifier, array $options)
0 ignored issues
show
Unused Code introduced by
The parameter $serviceLocator 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...
148
    {
149
        if (!array_key_exists('callback', $options)) {
150
            throw new RuntimeException('Missing "callback" for callback variant.');
151
        }
152
153
        if (!is_callable($options['callback'])) {
154
            throw new RuntimeException('The "callback" for callback variant cannot be called.');
155
        }
156
157
        return new CallbackVariant($identifier, $options['callback']);
158
    }
159
160
    private function loadTestVariantEventManager(ServiceLocatorInterface $serviceLocator, $identifier, array $options)
161
    {
162
        if (!array_key_exists('callback', $options)) {
163
            throw new RuntimeException('Missing the "callback" option for event manager variant.');
164
        }
165
166
        if (!array_key_exists('event', $options)) {
167
            throw new RuntimeException('Missing the "event" option for event manager variant.');
168
        }
169
170
        if (!array_key_exists('priority', $options)) {
171
            $options['priority'] = 0;
172
        }
173
174
        if (empty($options['event_manager'])) {
175
            $eventManager = $serviceLocator->get('Application')->getEventManager();
176
        } else {
177
            $eventManager = $serviceLocator->get($options['event_manager']);
178
        }
179
180
        $callback = $options['callback'];
181
182
        if (!is_callable($callback) && $serviceLocator->has($callback)) {
183
            $callback = $serviceLocator->get($callback);
184
        } elseif (!is_callable($callback)) {
185
            throw new RuntimeException('The callback is not callable.');
186
        }
187
188
        return new EventManagerVariant(
189
            $eventManager,
190
            $identifier,
191
            $options['event'],
192
            $callback,
193
            $options['priority']
194
        );
195
    }
196
197
    private function loadTestVariantSimple(ServiceLocatorInterface $serviceLocator, $identifier, array $options)
0 ignored issues
show
Unused Code introduced by
The parameter $serviceLocator 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...
Unused Code introduced by
The parameter $options 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...
198
    {
199
        return new SimpleVariant($identifier);
200
    }
201
202
    private function loadTestVariantFromServiceManager(ServiceLocatorInterface $serviceLocator, $type)
203
    {
204
        if (!$serviceLocator->has($type)) {
205
            throw new RuntimeException(sprintf('The variant "%s" is not a valid service manager name.', $type));
206
        }
207
208
        return $serviceLocator->get($type);
209
    }
210
}
211