Completed
Push — master ( d31eeb...9f210c )
by Walter
07:14 queued 05:01
created

EngineFactory::loadTest()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 23
rs 8.7972
cc 4
eloc 15
nc 8
nop 4
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\EventManager\EventManager;
22
use Zend\ServiceManager\FactoryInterface;
23
use Zend\ServiceManager\ServiceLocatorInterface;
24
25
class EngineFactory implements FactoryInterface
26
{
27
    public function createService(ServiceLocatorInterface $serviceLocator)
28
    {
29
        /** @var array $config */
30
        $config = $serviceLocator->get('Config');
31
32
        /** @var ParticipationManagerInterface $participationManager */
33
        $participationManager = $serviceLocator->get('phpab.participation_manager');
34
35
        /** @var DispatcherInterface $dispatcher */
36
        $dispatcher = $serviceLocator->get('phpab.dispatcher');
37
38
        $filter = $this->loadService($serviceLocator, $config['phpab']['default_filter']);
39
        $chooser = $this->loadService($serviceLocator, $config['phpab']['default_variant_chooser']);
40
41
        $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 38 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...ault_variant_chooser']) on line 39 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...
42
43
        $this->loadTests($engine, $serviceLocator, $config['phpab']);
44
45
        return $engine;
46
    }
47
48
    private function loadService(ServiceLocatorInterface $serviceLocator, $serviceName)
49
    {
50
        if (!$serviceLocator->has($serviceName)) {
51
            return null;
52
        }
53
54
        return $serviceLocator->get($serviceName);
55
    }
56
57
    private function loadTests(EngineInterface $engine, ServiceLocatorInterface $serviceLocator, $config)
58
    {
59
        foreach ($config['tests'] as $identifier => $testConfig) {
60
            $this->loadTest($serviceLocator, $engine, $identifier, $testConfig);
61
        }
62
    }
63
64
    private function loadTest(
65
        ServiceLocatorInterface $serviceLocator,
66
        EngineInterface $engine,
67
        $identifier,
68
        array $config
69
    ) {
70
        $filter = null;
71
        if (array_key_exists('filter', $config)) {
72
            $filter = $serviceLocator->get($config['filter']);
73
        }
74
75
        $variantChooser = null;
76
        if (array_key_exists('variant_chooser', $config)) {
77
            $variantChooser = $serviceLocator->get($config['variant_chooser']);
78
        }
79
80
        $variants = $this->loadTestVariants($serviceLocator, $config);
81
        $options = array_key_exists('options', $config) ? $config['options'] : [];
82
83
        $test = new Test($identifier, $variants);
84
85
        $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 72 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 77 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...
86
    }
87
88
    private function loadTestVariants(ServiceLocatorInterface $serviceLocator, $config)
89
    {
90
        $variants = [];
91
92
        foreach ($config['variants'] as $identifier => $variant) {
93
            // We also support shortcuts so that the user can specify a service name straight away.
94
            if (is_string($variant)) {
95
                $variant = [
96
                    'type' => $variant,
97
                ];
98
            }
99
100
            if (!array_key_exists('type', $variant)) {
101
                throw new RuntimeException('The type of the variant is missing.');
102
            }
103
104
            $options = empty($variant['options']) ? [] : $variant['options'];
105
106
            $variants[] = $this->loadTestVariant($serviceLocator, $variant['type'], $identifier, $options);
107
        }
108
109
        return $variants;
110
    }
111
112
    private function loadTestVariant(ServiceLocatorInterface $serviceLocator, $type, $identifier, array $options)
113
    {
114
        switch ($type) {
115
            case 'callback':
116
                $variant = $this->loadTestVariantCallback($serviceLocator, $identifier, $options);
117
                break;
118
119
            case 'event_manager':
120
                $variant = $this->loadTestVariantEventManager($serviceLocator, $identifier, $options);
121
                break;
122
123
            case 'simple':
124
                $variant = $this->loadTestVariantSimple($serviceLocator, $identifier, $options);
125
                break;
126
127
            case 'service_manager':
128
            default:
129
                $variant = $this->loadTestVariantFromServiceManager($serviceLocator, $type);
130
                break;
131
        }
132
133
        return $variant;
134
    }
135
136
    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...
137
    {
138
        if (!array_key_exists('callback', $options)) {
139
            throw new RuntimeException('Missing "callback" for callback variant.');
140
        }
141
142
        if (!is_callable($options['callback'])) {
143
            throw new RuntimeException('The "callback" for callback variant cannot be called.');
144
        }
145
146
        return new CallbackVariant($identifier, $options['callback']);
147
    }
148
149
    private function loadTestVariantEventManager(ServiceLocatorInterface $serviceLocator, $identifier, array $options)
150
    {
151
        if (empty($options['event_manager'])) {
152
            $eventManager = $serviceLocator->get('Application')->getEventManager();
153
        } else {
154
            $eventManager = $serviceLocator->get($options['event_manager']);
155
        }
156
157
        $callback = $options['callback'];
158
159
        if (!is_callable($callback) && $serviceLocator->has($callback)) {
160
            $callback = $serviceLocator->get($callback);
161
        }
162
163
        return new EventManagerVariant(
164
            $eventManager,
165
            $identifier,
166
            $options['event'],
167
            $callback,
168
            $options['priority']
169
        );
170
    }
171
172
    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...
173
    {
174
        return new SimpleVariant($identifier);
175
    }
176
177
    private function loadTestVariantFromServiceManager(ServiceLocatorInterface $serviceLocator, $type)
178
    {
179
        if (!$serviceLocator->has($type)) {
180
            throw new RuntimeException(sprintf('The variant "%s" is not a valid service manager name.', $type));
181
        }
182
183
        return $serviceLocator->get($type);
184
    }
185
}
186