Factory   B
last analyzed

Complexity

Total Complexity 45

Size/Duplication

Total Lines 297
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 130
c 1
b 1
f 0
dl 0
loc 297
rs 8.8
wmc 45

23 Methods

Rating   Name   Duplication   Size   Complexity  
A createFileExpectationsLoader() 0 15 2
A createRequestExpectationComparator() 0 13 2
A __construct() 0 5 1
A createDefault() 0 3 1
A createActionFactory() 0 10 2
A createRequestToExpectationMapper() 0 13 2
A createRequestsRouter() 0 10 2
A createRequestStorage() 0 10 2
A createHomePathService() 0 10 2
A createProxyResponseStrategy() 0 14 2
A createScenarioStorage() 0 10 2
A createLogger() 0 10 3
A createRegexReplacer() 0 10 2
A createExpectationBackup() 0 10 2
A createActionLocator() 0 10 2
A createRegexResponseStrategy() 0 14 2
A createResponseStrategyLocator() 0 10 2
A createHttpServer() 0 10 2
A createHttpClient() 0 7 2
A createHttpResponseStrategy() 0 13 2
A createFileSystemService() 0 7 2
A createRegexProxyResponseStrategy() 0 15 2
A createExpectationStorage() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like Factory often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Factory, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * This file is part of Phiremock.
4
 *
5
 * Phiremock is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Phiremock is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Phiremock.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace Mcustiel\Phiremock\Server\Factory;
20
21
use Exception;
22
use Mcustiel\Phiremock\Common\Utils\FileSystem;
23
use Mcustiel\Phiremock\Factory as PhiremockFactory;
24
use Mcustiel\Phiremock\Server\Actions\ActionLocator;
25
use Mcustiel\Phiremock\Server\Actions\ActionsFactory;
26
use Mcustiel\Phiremock\Server\Http\Implementation\FastRouterHandler;
27
use Mcustiel\Phiremock\Server\Http\Implementation\ReactPhpServer;
28
use Mcustiel\Phiremock\Server\Http\ServerInterface;
29
use Mcustiel\Phiremock\Server\Model\ExpectationStorage;
30
use Mcustiel\Phiremock\Server\Model\Implementation\ExpectationAutoStorage;
31
use Mcustiel\Phiremock\Server\Model\Implementation\RequestAutoStorage;
32
use Mcustiel\Phiremock\Server\Model\Implementation\ScenarioAutoStorage;
33
use Mcustiel\Phiremock\Server\Model\RequestStorage;
34
use Mcustiel\Phiremock\Server\Model\ScenarioStorage;
35
use Mcustiel\Phiremock\Server\Utils\Config\Config;
36
use Mcustiel\Phiremock\Server\Utils\DataStructures\StringObjectArrayMap;
37
use Mcustiel\Phiremock\Server\Utils\FileExpectationsLoader;
38
use Mcustiel\Phiremock\Server\Utils\GuzzlePsr18Client;
39
use Mcustiel\Phiremock\Server\Utils\HomePathService;
40
use Mcustiel\Phiremock\Server\Utils\RequestExpectationComparator;
41
use Mcustiel\Phiremock\Server\Utils\RequestToExpectationMapper;
42
use Mcustiel\Phiremock\Server\Utils\ResponseStrategyLocator;
43
use Mcustiel\Phiremock\Server\Utils\Strategies\HttpResponseStrategy;
44
use Mcustiel\Phiremock\Server\Utils\Strategies\ProxyResponseStrategy;
45
use Mcustiel\Phiremock\Server\Utils\Strategies\RegexProxyResponseStrategy;
46
use Mcustiel\Phiremock\Server\Utils\Strategies\RegexResponseStrategy;
47
use Mcustiel\Phiremock\Server\Utils\Strategies\Utils\RegexReplacer;
48
use Monolog\Handler\StreamHandler;
49
use Monolog\Logger;
50
use Psr\Http\Client\ClientInterface;
51
use Psr\Log\LoggerInterface;
52
53
class Factory
54
{
55
    /** @var PhiremockFactory */
56
    private $phiremockFactory;
57
58
    /** @var StringObjectArrayMap */
59
    private $factoryCache;
60
61
    /** @var Config */
62
    private $config;
63
64
    public function __construct(PhiremockFactory $factory, Config $config)
65
    {
66
        $this->phiremockFactory = $factory;
67
        $this->factoryCache = new StringObjectArrayMap();
68
        $this->config = $config;
69
    }
70
71
    public static function createDefault(Config $config): self
72
    {
73
        return new static(new PhiremockFactory(), $config);
74
    }
75
76
    public function createFileSystemService(): FileSystem
77
    {
78
        if (!$this->factoryCache->has('fileSystem')) {
79
            $this->factoryCache->set('fileSystem', new FileSystem());
80
        }
81
82
        return $this->factoryCache->get('fileSystem');
83
    }
84
85
    public function createLogger(): LoggerInterface
86
    {
87
        if (!$this->factoryCache->has('logger')) {
88
            $logger = new Logger('stdoutLogger');
89
            $logLevel = $this->config->isDebugMode() ? Logger::DEBUG : Logger::INFO;
0 ignored issues
show
Deprecated Code introduced by
The constant Monolog\Logger::INFO has been deprecated: Use \Monolog\Level::Info ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

89
            $logLevel = $this->config->isDebugMode() ? Logger::DEBUG : /** @scrutinizer ignore-deprecated */ Logger::INFO;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
Deprecated Code introduced by
The constant Monolog\Logger::DEBUG has been deprecated: Use \Monolog\Level::Debug ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

89
            $logLevel = $this->config->isDebugMode() ? /** @scrutinizer ignore-deprecated */ Logger::DEBUG : Logger::INFO;

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
90
            $logger->pushHandler(new StreamHandler(\STDOUT, $logLevel));
91
            $this->factoryCache->set('logger', $logger);
92
        }
93
94
        return $this->factoryCache->get('logger');
95
    }
96
97
    public function createHttpResponseStrategy(): HttpResponseStrategy
98
    {
99
        if (!$this->factoryCache->has('httpResponseStrategy')) {
100
            $this->factoryCache->set(
101
                'httpResponseStrategy',
102
                new HttpResponseStrategy(
103
                    $this->createScenarioStorage(),
104
                    $this->createLogger()
105
                )
106
            );
107
        }
108
109
        return $this->factoryCache->get('httpResponseStrategy');
110
    }
111
112
    public function createRegexResponseStrategy(): RegexResponseStrategy
113
    {
114
        if (!$this->factoryCache->has('regexResponseStrategy')) {
115
            $this->factoryCache->set(
116
                'regexResponseStrategy',
117
                new RegexResponseStrategy(
118
                    $this->createScenarioStorage(),
119
                    $this->createLogger(),
120
                    $this->createRegexReplacer()
121
                )
122
            );
123
        }
124
125
        return $this->factoryCache->get('regexResponseStrategy');
126
    }
127
128
    /** @throws Exception */
129
    public function createProxyResponseStrategy(): ProxyResponseStrategy
130
    {
131
        if (!$this->factoryCache->has('proxyResponseStrategy')) {
132
            $this->factoryCache->set(
133
                'proxyResponseStrategy',
134
                new ProxyResponseStrategy(
135
                    $this->createScenarioStorage(),
136
                    $this->createLogger(),
137
                    $this->createHttpClient()
138
                )
139
            );
140
        }
141
142
        return $this->factoryCache->get('proxyResponseStrategy');
143
    }
144
145
    /** @throws Exception */
146
    public function createRegexProxyResponseStrategy(): RegexProxyResponseStrategy
147
    {
148
        if (!$this->factoryCache->has('regexProxyResponseStrategy')) {
149
            $this->factoryCache->set(
150
                'regexProxyResponseStrategy',
151
                new RegexProxyResponseStrategy(
152
                    $this->createScenarioStorage(),
153
                    $this->createLogger(),
154
                    $this->createHttpClient(),
155
                    $this->createRegexReplacer()
156
                )
157
            );
158
        }
159
160
        return $this->factoryCache->get('regexProxyResponseStrategy');
161
    }
162
163
    public function createRegexReplacer(): RegexReplacer
164
    {
165
        if (!$this->factoryCache->has('regexReplacer')) {
166
            $this->factoryCache->set(
167
                'regexReplacer',
168
                new RegexReplacer()
169
            );
170
        }
171
172
        return $this->factoryCache->get('regexReplacer');
173
    }
174
175
    public function createResponseStrategyLocator(): ResponseStrategyLocator
176
    {
177
        if (!$this->factoryCache->has('responseStrategyLocator')) {
178
            $this->factoryCache->set(
179
                'responseStrategyLocator',
180
                new ResponseStrategyLocator($this)
181
            );
182
        }
183
184
        return $this->factoryCache->get('responseStrategyLocator');
185
    }
186
187
    public function createRequestsRouter(): FastRouterHandler
188
    {
189
        if (!$this->factoryCache->has('router')) {
190
            $this->factoryCache->set(
191
                'router',
192
                new FastRouterHandler($this->createActionLocator(), $this->config, $this->createLogger())
193
            );
194
        }
195
196
        return $this->factoryCache->get('router');
197
    }
198
199
    public function createHomePathService(): HomePathService
200
    {
201
        if (!$this->factoryCache->has('homePathService')) {
202
            $this->factoryCache->set(
203
                'homePathService',
204
                new HomePathService()
205
            );
206
        }
207
208
        return $this->factoryCache->get('homePathService');
209
    }
210
211
    public function createHttpServer(): ServerInterface
212
    {
213
        if (!$this->factoryCache->has('httpServer')) {
214
            $this->factoryCache->set(
215
                'httpServer',
216
                new ReactPhpServer($this->createRequestsRouter(), $this->createLogger())
217
            );
218
        }
219
220
        return $this->factoryCache->get('httpServer');
221
    }
222
223
    public function createExpectationStorage(): ExpectationStorage
224
    {
225
        if (!$this->factoryCache->has('expectationsStorage')) {
226
            $this->factoryCache->set(
227
                'expectationsStorage',
228
                new ExpectationAutoStorage()
229
            );
230
        }
231
232
        return $this->factoryCache->get('expectationsStorage');
233
    }
234
235
    public function createExpectationBackup(): ExpectationStorage
236
    {
237
        if (!$this->factoryCache->has('expectationsBackup')) {
238
            $this->factoryCache->set(
239
                'expectationsBackup',
240
                new ExpectationAutoStorage()
241
            );
242
        }
243
244
        return $this->factoryCache->get('expectationsBackup');
245
    }
246
247
    public function createRequestStorage(): RequestStorage
248
    {
249
        if (!$this->factoryCache->has('requestsStorage')) {
250
            $this->factoryCache->set(
251
                'requestsStorage',
252
                new RequestAutoStorage()
253
            );
254
        }
255
256
        return $this->factoryCache->get('requestsStorage');
257
    }
258
259
    public function createScenarioStorage(): ScenarioStorage
260
    {
261
        if (!$this->factoryCache->has('scenariosStorage')) {
262
            $this->factoryCache->set(
263
                'scenariosStorage',
264
                new ScenarioAutoStorage()
265
            );
266
        }
267
268
        return $this->factoryCache->get('scenariosStorage');
269
    }
270
271
    public function createRequestExpectationComparator(): RequestExpectationComparator
272
    {
273
        if (!$this->factoryCache->has('requestExpectationComparator')) {
274
            $this->factoryCache->set(
275
                'requestExpectationComparator',
276
                new RequestExpectationComparator(
277
                    $this->createScenarioStorage(),
278
                    $this->createLogger()
279
                )
280
            );
281
        }
282
283
        return $this->factoryCache->get('requestExpectationComparator');
284
    }
285
286
    public function createFileExpectationsLoader(): FileExpectationsLoader
287
    {
288
        if (!$this->factoryCache->has('fileExpectationsLoader')) {
289
            $this->factoryCache->set(
290
                'fileExpectationsLoader',
291
                new FileExpectationsLoader(
292
                    $this->phiremockFactory->createArrayToExpectationConverterLocator(),
293
                    $this->createExpectationStorage(),
294
                    $this->createExpectationBackup(),
295
                    $this->createLogger()
296
                )
297
            );
298
        }
299
300
        return $this->factoryCache->get('fileExpectationsLoader');
301
    }
302
303
    public function createActionLocator(): ActionLocator
304
    {
305
        if (!$this->factoryCache->has('actionLocator')) {
306
            $this->factoryCache->set(
307
                'actionLocator',
308
                new ActionLocator($this->createActionFactory())
309
            );
310
        }
311
312
        return $this->factoryCache->get('actionLocator');
313
    }
314
315
    public function createActionFactory(): ActionsFactory
316
    {
317
        if (!$this->factoryCache->has('actionFactory')) {
318
            $this->factoryCache->set(
319
                'actionFactory',
320
                new ActionsFactory($this, $this->phiremockFactory)
321
            );
322
        }
323
324
        return $this->factoryCache->get('actionFactory');
325
    }
326
327
    public function createRequestToExpectationMapper(): RequestToExpectationMapper
328
    {
329
        if (!$this->factoryCache->has('requestToExpectationMapper')) {
330
            $this->factoryCache->set(
331
                'requestToExpectationMapper',
332
                new RequestToExpectationMapper(
333
                    $this->phiremockFactory->createArrayToExpectationConverterLocator(),
334
                    $this->createLogger()
335
                )
336
            );
337
        }
338
339
        return $this->factoryCache->get('requestToExpectationMapper');
340
    }
341
342
    /** @throws Exception */
343
    public function createHttpClient(): ClientInterface
344
    {
345
        if (!class_exists('\GuzzleHttp\Client', true)) {
346
            throw new Exception('A default http client implementation is needed. ' . 'Please extend the factory to return a PSR18-compatible HttpClient or install Guzzle Http Client v6');
347
        }
348
349
        return new GuzzlePsr18Client();
350
    }
351
}
352