GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

PimpleTest   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 548
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 238
c 0
b 0
f 0
dl 0
loc 548
rs 8.8798
wmc 44

43 Methods

Rating   Name   Duplication   Size   Complexity  
A testLegacyExtendFailsForKeysNotContainingServiceDefinitions() 0 8 1
A testIsset() 0 14 1
A badServiceDefinitionProvider() 0 5 1
A testExtendFailsForInvalidServiceDefinitions() 0 6 1
A settingNonInvokableObjectShouldTreatItAsParameter() 0 6 1
A settingAnInvokableObjectShouldTreatItAsFactory() 0 6 1
A testExtend() 0 25 1
A testExtendValidatesKeyIsPresent() 0 7 1
A testExtendingProtectedClosureDeprecation() 0 12 1
A testLegacyProtectFailsForInvalidServiceDefinitions() 0 5 1
A testUnset() 0 11 1
A testWithString() 0 6 1
A testLegacyOffsetGetValidatesKeyIsPresent() 0 7 1
A testRawHonorsNullValues() 0 5 1
A serviceDefinitionProvider() 0 10 1
A testExtendingServiceAfterOtherServiceFreeze() 0 15 1
A testLegacyExtendValidatesKeyIsPresent() 0 7 1
A testConstructorInjection() 0 6 1
A testExtendDoesNotLeakWithFactories() 0 22 2
A testShouldPassContainerAsParameter() 0 12 1
A testShare() 0 12 1
A testLegacyExtendFailsForInvalidServiceDefinitions() 0 6 1
A testWithClosure() 0 8 1
A testRaw() 0 7 1
A testGlobalFunctionNameAsParameterValue() 0 5 1
A testServicesShouldBeDifferent() 0 14 1
A testExtendFailsForKeysNotContainingServiceDefinitions() 0 8 1
A testFactoryFailsForInvalidServiceDefinitions() 0 5 1
A testRawValidatesKeyIsPresent() 0 7 1
A testLegacyOverridingServiceAfterFreeze() 0 13 1
A testOffsetGetHonorsNullValues() 0 5 1
A testOffsetGetValidatesKeyIsPresent() 0 7 1
A testOverridingServiceAfterFreeze() 0 13 1
A testLegacyFactoryFailsForInvalidServiceDefinitions() 0 5 1
A testProtect() 0 6 1
A testLegacyRawValidatesKeyIsPresent() 0 7 1
A testKeys() 0 7 1
A testExtendFailsIfFrozenServiceIsInvokable() 0 12 1
A testRemovingServiceAfterFreeze() 0 13 1
A testDefiningNewServiceAfterFreeze() 0 12 1
A testProtectFailsForInvalidServiceDefinitions() 0 5 1
A testExtendingService() 0 13 1
A testExtendFailsIfFrozenServiceIsNonInvokable() 0 12 1

How to fix   Complexity   

Complex Class

Complex classes like PimpleTest 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 PimpleTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
/* (c) Anton Medvedev <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Deployer\Component\Pimple;
11
12
use Deployer\Component\Pimple\Exception\FrozenServiceException;
13
use Deployer\Component\Pimple\Exception\InvalidServiceIdentifierException;
14
use Deployer\Component\Pimple\Exception\UnknownIdentifierException;
15
use InvalidArgumentException;
16
use PHPUnit\Framework\TestCase;
17
use ReflectionProperty;
18
use RuntimeException;
19
20
use function extension_loaded;
21
22
class PimpleTest extends TestCase
23
{
24
    public function testWithString()
25
    {
26
        $pimple = new Container();
27
        $pimple['param'] = 'value';
28
29
        $this->assertEquals('value', $pimple['param']);
30
    }
31
32
    public function testWithClosure()
33
    {
34
        $pimple = new Container();
35
        $pimple['service'] = function () {
36
            return new Service();
37
        };
38
39
        $this->assertInstanceOf(Service::class, $pimple['service']);
40
    }
41
42
    public function testServicesShouldBeDifferent()
43
    {
44
        $pimple = new Container();
45
        $pimple['service'] = $pimple->factory(function () {
46
            return new Service();
47
        });
48
49
        $serviceOne = $pimple['service'];
50
        $this->assertInstanceOf(Service::class, $serviceOne);
51
52
        $serviceTwo = $pimple['service'];
53
        $this->assertInstanceOf(Service::class, $serviceTwo);
54
55
        $this->assertNotSame($serviceOne, $serviceTwo);
56
    }
57
58
    public function testShouldPassContainerAsParameter()
59
    {
60
        $pimple = new Container();
61
        $pimple['service'] = function () {
62
            return new Service();
63
        };
64
        $pimple['container'] = function ($container) {
65
            return $container;
66
        };
67
68
        $this->assertNotSame($pimple, $pimple['service']);
69
        $this->assertSame($pimple, $pimple['container']);
70
    }
71
72
    public function testIsset()
73
    {
74
        $pimple = new Container();
75
        $pimple['param'] = 'value';
76
        $pimple['service'] = function () {
77
            return new Service();
78
        };
79
80
        $pimple['null'] = null;
81
82
        $this->assertTrue(isset($pimple['param']));
83
        $this->assertTrue(isset($pimple['service']));
84
        $this->assertTrue(isset($pimple['null']));
85
        $this->assertFalse(isset($pimple['non_existent']));
86
    }
87
88
    public function testConstructorInjection()
89
    {
90
        $params = ['param' => 'value'];
91
        $pimple = new Container($params);
92
93
        $this->assertSame($params['param'], $pimple['param']);
94
    }
95
96
    public function testOffsetGetValidatesKeyIsPresent()
97
    {
98
        $this->expectException(UnknownIdentifierException::class);
99
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
100
101
        $pimple = new Container();
102
        echo $pimple['foo'];
103
    }
104
105
    /**
106
     * @group legacy
107
     */
108
    public function testLegacyOffsetGetValidatesKeyIsPresent()
109
    {
110
        $this->expectException(InvalidArgumentException::class);
111
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
112
113
        $pimple = new Container();
114
        echo $pimple['foo'];
115
    }
116
117
    public function testOffsetGetHonorsNullValues()
118
    {
119
        $pimple = new Container();
120
        $pimple['foo'] = null;
121
        $this->assertNull($pimple['foo']);
122
    }
123
124
    public function testUnset()
125
    {
126
        $pimple = new Container();
127
        $pimple['param'] = 'value';
128
        $pimple['service'] = function () {
129
            return new Service();
130
        };
131
132
        unset($pimple['param'], $pimple['service']);
133
        $this->assertFalse(isset($pimple['param']));
134
        $this->assertFalse(isset($pimple['service']));
135
    }
136
137
    /**
138
     * @dataProvider serviceDefinitionProvider
139
     */
140
    public function testShare($service)
141
    {
142
        $pimple = new Container();
143
        $pimple['shared_service'] = $service;
144
145
        $serviceOne = $pimple['shared_service'];
146
        $this->assertInstanceOf(Service::class, $serviceOne);
147
148
        $serviceTwo = $pimple['shared_service'];
149
        $this->assertInstanceOf(Service::class, $serviceTwo);
150
151
        $this->assertSame($serviceOne, $serviceTwo);
152
    }
153
154
    /**
155
     * @dataProvider serviceDefinitionProvider
156
     */
157
    public function testProtect($service)
158
    {
159
        $pimple = new Container();
160
        $pimple['protected'] = $pimple->protect($service);
161
162
        $this->assertSame($service, $pimple['protected']);
163
    }
164
165
    public function testGlobalFunctionNameAsParameterValue()
166
    {
167
        $pimple = new Container();
168
        $pimple['global_function'] = 'strlen';
169
        $this->assertSame('strlen', $pimple['global_function']);
170
    }
171
172
    public function testRaw()
173
    {
174
        $pimple = new Container();
175
        $pimple['service'] = $definition = $pimple->factory(function () {
176
            return 'foo';
177
        });
178
        $this->assertSame($definition, $pimple->raw('service'));
179
    }
180
181
    public function testRawHonorsNullValues()
182
    {
183
        $pimple = new Container();
184
        $pimple['foo'] = null;
185
        $this->assertNull($pimple->raw('foo'));
186
    }
187
188
    public function testRawValidatesKeyIsPresent()
189
    {
190
        $this->expectException(UnknownIdentifierException::class);
191
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
192
193
        $pimple = new Container();
194
        $pimple->raw('foo');
195
    }
196
197
    /**
198
     * @group legacy
199
     */
200
    public function testLegacyRawValidatesKeyIsPresent()
201
    {
202
        $this->expectException(InvalidArgumentException::class);
203
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
204
205
        $pimple = new Container();
206
        $pimple->raw('foo');
207
    }
208
209
    /**
210
     * @dataProvider serviceDefinitionProvider
211
     */
212
    public function testExtend($service)
213
    {
214
        $pimple = new Container();
215
        $pimple['shared_service'] = function () {
216
            return new Service();
217
        };
218
        $pimple['factory_service'] = $pimple->factory(function () {
219
            return new Service();
220
        });
221
222
        $pimple->extend('shared_service', $service);
223
        $serviceOne = $pimple['shared_service'];
224
        $this->assertInstanceOf(Service::class, $serviceOne);
225
        $serviceTwo = $pimple['shared_service'];
226
        $this->assertInstanceOf(Service::class, $serviceTwo);
227
        $this->assertSame($serviceOne, $serviceTwo);
228
        $this->assertSame($serviceOne->value, $serviceTwo->value);
229
230
        $pimple->extend('factory_service', $service);
0 ignored issues
show
Bug introduced by
$service of type object is incompatible with the type callable expected by parameter $callable of Deployer\Component\Pimple\Container::extend(). ( Ignorable by Annotation )

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

230
        $pimple->extend('factory_service', /** @scrutinizer ignore-type */ $service);
Loading history...
231
        $serviceOne = $pimple['factory_service'];
232
        $this->assertInstanceOf(Service::class, $serviceOne);
233
        $serviceTwo = $pimple['factory_service'];
234
        $this->assertInstanceOf(Service::class, $serviceTwo);
235
        $this->assertNotSame($serviceOne, $serviceTwo);
236
        $this->assertNotSame($serviceOne->value, $serviceTwo->value);
237
    }
238
239
    public function testExtendDoesNotLeakWithFactories()
240
    {
241
        if (extension_loaded('pimple')) {
242
            $this->markTestSkipped('Pimple extension does not support this test');
243
        }
244
        $pimple = new Container();
245
246
        $pimple['foo'] = $pimple->factory(function () {
247
            return;
248
        });
249
        $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) {
0 ignored issues
show
Unused Code introduced by
The parameter $foo is not used and could be removed. ( Ignorable by Annotation )

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

249
        $pimple['foo'] = $pimple->extend('foo', function (/** @scrutinizer ignore-unused */ $foo, $pimple) {

This check looks for 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 $pimple is not used and could be removed. ( Ignorable by Annotation )

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

249
        $pimple['foo'] = $pimple->extend('foo', function ($foo, /** @scrutinizer ignore-unused */ $pimple) {

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

Loading history...
250
            return;
251
        });
252
        unset($pimple['foo']);
253
254
        $p = new ReflectionProperty($pimple, 'values');
255
        $p->setAccessible(true);
256
        $this->assertEmpty($p->getValue($pimple));
257
258
        $p = new ReflectionProperty($pimple, 'factories');
259
        $p->setAccessible(true);
260
        $this->assertCount(0, $p->getValue($pimple));
261
    }
262
263
    public function testExtendValidatesKeyIsPresent()
264
    {
265
        $this->expectException(UnknownIdentifierException::class);
266
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
267
268
        $pimple = new Container();
269
        $pimple->extend('foo', function () {});
270
    }
271
272
    /**
273
     * @group legacy
274
     */
275
    public function testLegacyExtendValidatesKeyIsPresent()
276
    {
277
        $this->expectException(InvalidArgumentException::class);
278
        $this->expectExceptionMessage('Identifier "foo" is not defined.');
279
280
        $pimple = new Container();
281
        $pimple->extend('foo', function () {});
282
    }
283
284
    public function testKeys()
285
    {
286
        $pimple = new Container();
287
        $pimple['foo'] = 123;
288
        $pimple['bar'] = 123;
289
290
        $this->assertEquals(['foo', 'bar'], $pimple->keys());
291
    }
292
293
    /** @test */
294
    public function settingAnInvokableObjectShouldTreatItAsFactory()
295
    {
296
        $pimple = new Container();
297
        $pimple['invokable'] = new Invokable();
298
299
        $this->assertInstanceOf(Service::class, $pimple['invokable']);
300
    }
301
302
    /** @test */
303
    public function settingNonInvokableObjectShouldTreatItAsParameter()
304
    {
305
        $pimple = new Container();
306
        $pimple['non_invokable'] = new NonInvokable();
307
308
        $this->assertInstanceOf(NonInvokable::class, $pimple['non_invokable']);
309
    }
310
311
    /**
312
     * @dataProvider badServiceDefinitionProvider
313
     */
314
    public function testFactoryFailsForInvalidServiceDefinitions($service)
315
    {
316
        $this->expectException(\TypeError::class);
317
        $pimple = new Container();
318
        $pimple->factory($service);
319
    }
320
321
    /**
322
     * @group legacy
323
     * @dataProvider badServiceDefinitionProvider
324
     */
325
    public function testLegacyFactoryFailsForInvalidServiceDefinitions($service)
326
    {
327
        $this->expectException(\TypeError::class);
328
        $pimple = new Container();
329
        $pimple->factory($service);
330
    }
331
332
    /**
333
     * @dataProvider badServiceDefinitionProvider
334
     */
335
    public function testProtectFailsForInvalidServiceDefinitions($service)
336
    {
337
        $this->expectException(\TypeError::class);
338
        $pimple = new Container();
339
        $pimple->protect($service);
340
    }
341
342
    /**
343
     * @group legacy
344
     * @dataProvider badServiceDefinitionProvider
345
     */
346
    public function testLegacyProtectFailsForInvalidServiceDefinitions($service)
347
    {
348
        $this->expectException(\TypeError::class);
349
        $pimple = new Container();
350
        $pimple->protect($service);
351
    }
352
353
    /**
354
     * @dataProvider badServiceDefinitionProvider
355
     */
356
    public function testExtendFailsForKeysNotContainingServiceDefinitions($service)
357
    {
358
        $this->expectException(InvalidServiceIdentifierException::class);
359
        $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
360
361
        $pimple = new Container();
362
        $pimple['foo'] = $service;
363
        $pimple->extend('foo', function () {});
364
    }
365
366
    /**
367
     * @group legacy
368
     * @dataProvider badServiceDefinitionProvider
369
     */
370
    public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service)
371
    {
372
        $this->expectException(InvalidArgumentException::class);
373
        $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.');
374
375
        $pimple = new Container();
376
        $pimple['foo'] = $service;
377
        $pimple->extend('foo', function () {});
378
    }
379
380
    /**
381
     * @group legacy
382
     * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected?
383
     */
384
    public function testExtendingProtectedClosureDeprecation()
385
    {
386
        $pimple = new Container();
387
        $pimple['foo'] = $pimple->protect(function () {
388
            return 'bar';
389
        });
390
391
        $pimple->extend('foo', function ($value) {
392
            return $value . '-baz';
393
        });
394
395
        $this->assertSame('bar-baz', $pimple['foo']);
396
    }
397
398
    /**
399
     * @dataProvider badServiceDefinitionProvider
400
     */
401
    public function testExtendFailsForInvalidServiceDefinitions($service)
402
    {
403
        $this->expectException(\TypeError::class);
404
        $pimple = new Container();
405
        $pimple['foo'] = function () {};
406
        $pimple->extend('foo', $service);
407
    }
408
409
    /**
410
     * @group legacy
411
     * @dataProvider badServiceDefinitionProvider
412
     */
413
    public function testLegacyExtendFailsForInvalidServiceDefinitions($service)
414
    {
415
        $this->expectException(\TypeError::class);
416
        $pimple = new Container();
417
        $pimple['foo'] = function () {};
418
        $pimple->extend('foo', $service);
419
    }
420
421
    public function testExtendFailsIfFrozenServiceIsNonInvokable()
422
    {
423
        $this->expectException(FrozenServiceException::class);
424
        $this->expectExceptionMessage('Cannot override frozen service "foo".');
425
426
        $pimple = new Container();
427
        $pimple['foo'] = function () {
428
            return new NonInvokable();
429
        };
430
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
431
432
        $pimple->extend('foo', function () {});
433
    }
434
435
    public function testExtendFailsIfFrozenServiceIsInvokable()
436
    {
437
        $this->expectException(FrozenServiceException::class);
438
        $this->expectExceptionMessage('Cannot override frozen service "foo".');
439
440
        $pimple = new Container();
441
        $pimple['foo'] = function () {
442
            return new Invokable();
443
        };
444
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
445
446
        $pimple->extend('foo', function () {});
447
    }
448
449
    /**
450
     * Provider for invalid service definitions.
451
     */
452
    public static function badServiceDefinitionProvider()
453
    {
454
        return [
455
            [123],
456
            [new NonInvokable()],
457
        ];
458
    }
459
460
    /**
461
     * Provider for service definitions.
462
     */
463
    public static function serviceDefinitionProvider()
464
    {
465
        return [
466
            [function ($value) {
467
                $service = new Service();
468
                $service->value = $value;
469
470
                return $service;
471
            }],
472
            [new Invokable()],
473
        ];
474
    }
475
476
    public function testDefiningNewServiceAfterFreeze()
477
    {
478
        $pimple = new Container();
479
        $pimple['foo'] = function () {
480
            return 'foo';
481
        };
482
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
483
484
        $pimple['bar'] = function () {
485
            return 'bar';
486
        };
487
        $this->assertSame('bar', $pimple['bar']);
488
    }
489
490
    public function testOverridingServiceAfterFreeze()
491
    {
492
        $this->expectException(FrozenServiceException::class);
493
        $this->expectExceptionMessage('Cannot override frozen service "foo".');
494
495
        $pimple = new Container();
496
        $pimple['foo'] = function () {
497
            return 'foo';
498
        };
499
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
500
501
        $pimple['foo'] = function () {
502
            return 'bar';
503
        };
504
    }
505
506
    /**
507
     * @group legacy
508
     */
509
    public function testLegacyOverridingServiceAfterFreeze()
510
    {
511
        $this->expectException(RuntimeException::class);
512
        $this->expectExceptionMessage('Cannot override frozen service "foo".');
513
514
        $pimple = new Container();
515
        $pimple['foo'] = function () {
516
            return 'foo';
517
        };
518
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
519
520
        $pimple['foo'] = function () {
521
            return 'bar';
522
        };
523
    }
524
525
    public function testRemovingServiceAfterFreeze()
526
    {
527
        $pimple = new Container();
528
        $pimple['foo'] = function () {
529
            return 'foo';
530
        };
531
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
532
533
        unset($pimple['foo']);
534
        $pimple['foo'] = function () {
535
            return 'bar';
536
        };
537
        $this->assertSame('bar', $pimple['foo']);
538
    }
539
540
    public function testExtendingService()
541
    {
542
        $pimple = new Container();
543
        $pimple['foo'] = function () {
544
            return 'foo';
545
        };
546
        $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed. ( Ignorable by Annotation )

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

546
        $pimple['foo'] = $pimple->extend('foo', function ($foo, /** @scrutinizer ignore-unused */ $app) {

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

Loading history...
547
            return "$foo.bar";
548
        });
549
        $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed. ( Ignorable by Annotation )

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

549
        $pimple['foo'] = $pimple->extend('foo', function ($foo, /** @scrutinizer ignore-unused */ $app) {

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

Loading history...
550
            return "$foo.baz";
551
        });
552
        $this->assertSame('foo.bar.baz', $pimple['foo']);
553
    }
554
555
    public function testExtendingServiceAfterOtherServiceFreeze()
556
    {
557
        $pimple = new Container();
558
        $pimple['foo'] = function () {
559
            return 'foo';
560
        };
561
        $pimple['bar'] = function () {
562
            return 'bar';
563
        };
564
        $foo = $pimple['foo'];
0 ignored issues
show
Unused Code introduced by
The assignment to $foo is dead and can be removed.
Loading history...
565
566
        $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed. ( Ignorable by Annotation )

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

566
        $pimple['bar'] = $pimple->extend('bar', function ($bar, /** @scrutinizer ignore-unused */ $app) {

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

Loading history...
567
            return "$bar.baz";
568
        });
569
        $this->assertSame('bar.baz', $pimple['bar']);
570
    }
571
}
572
573
class Invokable
574
{
575
    public function __invoke($value = null)
576
    {
577
        $service = new Service();
578
        $service->value = $value;
579
580
        return $service;
581
    }
582
}
583
584
class NonInvokable
585
{
586
    public function __call($a, $b) {}
587
}
588
589
class Service
590
{
591
    public $value;
592
}
593