Completed
Push — develop ( aae60d...6ebfe1 )
by Siad
03:51
created

CommonAdapterTest::testSetAndGetExpiredItem()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 34
Code Lines 19

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 34
rs 8.5806
cc 4
eloc 19
nc 6
nop 0
1
<?php
2
/**
3
 * Zend Framework (http://framework.zend.com/)
4
 *
5
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6
 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7
 * @license   http://framework.zend.com/license/new-bsd New BSD License
8
 */
9
10
namespace MehrAlsNix\Test\ZF\Cache\Storage\Adapter;
11
12
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
13
use Zend\Cache\Storage\IterableInterface;
14
use Zend\Cache\Storage\IteratorInterface;
15
use Zend\Cache\Storage\StorageInterface;
16
use Zend\Cache\Storage\ClearExpiredInterface;
17
use Zend\Cache\Storage\ClearByNamespaceInterface;
18
use Zend\Cache\Storage\ClearByPrefixInterface;
19
use Zend\Cache\Storage\FlushableInterface;
20
use Zend\Cache\Storage\OptimizableInterface;
21
use Zend\Cache\Storage\TaggableInterface;
22
use Zend\Cache\Storage\TotalSpaceCapableInterface;
23
use Zend\Stdlib\ErrorHandler;
24
25
/**
26
 * PHPUnit test case
27
 */
28
29
/**
30
 * @group      Zend_Cache
31
 */
32
abstract class CommonAdapterTest extends \PHPUnit_Framework_TestCase
33
{
34
    /**
35
     * @var \Zend\Cache\Storage\Adapter\AdapterOptions
36
     */
37
    protected $_options;
38
39
    /**
40
     * The storage adapter
41
     *
42
     * @var StorageInterface
43
     */
44
    protected $_storage;
45
46
    /**
47
     * All datatypes of PHP
48
     *
49
     * @var string[]
50
     */
51
    protected $_phpDatatypes = [
52
        'NULL', 'boolean', 'integer', 'double',
53
        'string', 'array', 'object', 'resource'
54
    ];
55
56
    public function setUp()
57
    {
58
        $this->assertInstanceOf(
59
            'Zend\Cache\Storage\StorageInterface',
60
            $this->_storage,
61
            'Storage adapter instance is needed for tests'
62
        );
63
        $this->assertInstanceOf(
64
            'Zend\Cache\Storage\Adapter\AdapterOptions',
65
            $this->_options,
66
            'Options instance is needed for tests'
67
        );
68
    }
69
70
    public function _tearDown()
71
    {
72
        // be sure the error handler has been stopped
73
        if (ErrorHandler::started()) {
74
            ErrorHandler::stop();
75
            $this->fail('ErrorHandler not stopped');
76
        }
77
    }
78
79
    public function testOptionNamesValid()
80
    {
81
        $options = $this->_storage->getOptions()->toArray();
82
        foreach ($options as $name => $value) {
83
            $this->assertRegExp(
84
                '/^[a-z]+[a-z0-9_]*[a-z0-9]+$/',
85
                $name,
86
                "Invalid option name '{$name}'"
87
            );
88
        }
89
    }
90
91
    public function testGettersAndSettersOfOptionsExists()
92
    {
93
        $options = $this->_storage->getOptions();
94
        foreach ($options->toArray() as $option => $value) {
95
            if ($option == 'adapter') {
96
                // Skip this, as it's a "special" value
97
                continue;
98
            }
99
            $method = ucwords(str_replace('_', ' ', $option));
100
            $method = str_replace(' ', '', $method);
101
102
            $this->assertTrue(
103
                method_exists($options, 'set' . $method),
104
                "Missing method 'set'{$method}"
105
            );
106
107
            $this->assertTrue(
108
                method_exists($options, 'get' . $method),
109
                "Missing method 'get'{$method}"
110
            );
111
        }
112
    }
113
114
    public function testOptionsGetAndSetDefault()
115
    {
116
        $options = $this->_storage->getOptions();
117
        $this->_storage->setOptions($options);
118
        $this->assertSame($options, $this->_storage->getOptions());
119
    }
120
121
    public function testOptionsFluentInterface()
122
    {
123
        $options = $this->_storage->getOptions();
124
        foreach ($options->toArray() as $option => $value) {
125
            $method = ucwords(str_replace('_', ' ', $option));
126
            $method = 'set' . str_replace(' ', '', $method);
127
            $this->assertSame(
128
                $options,
129
                $options->{$method}($value),
130
                "Method '{$method}' doesn't implement the fluent interface"
131
            );
132
        }
133
134
        $this->assertSame(
135
            $this->_storage,
136
            $this->_storage->setOptions($options),
137
            "Method 'setOptions' doesn't implement the fluent interface"
138
        );
139
    }
140
141
    public function testGetCapabilities()
142
    {
143
        $capabilities = $this->_storage->getCapabilities();
144
        $this->assertInstanceOf('Zend\Cache\Storage\Capabilities', $capabilities);
145
    }
146
147
    public function testDatatypesCapability()
148
    {
149
        $capabilities = $this->_storage->getCapabilities();
150
        $datatypes = $capabilities->getSupportedDatatypes();
151
        $this->assertInternalType('array', $datatypes);
152
153
        foreach ($datatypes as $sourceType => $targetType) {
154
            $this->assertContains(
155
                $sourceType, $this->_phpDatatypes,
156
                "Unknown source type '{$sourceType}'"
157
            );
158
            if (is_string($targetType)) {
159
                $this->assertContains(
160
                    $targetType, $this->_phpDatatypes,
161
                    "Unknown target type '{$targetType}'"
162
                );
163
            } else {
164
                $this->assertInternalType(
165
                    'bool', $targetType,
166
                    "Target type must be a string or boolean"
167
                );
168
            }
169
        }
170
    }
171
172
    public function testSupportedMetadataCapability()
173
    {
174
        $capabilities = $this->_storage->getCapabilities();
175
        $metadata = $capabilities->getSupportedMetadata();
176
        $this->assertInternalType('array', $metadata);
177
178
        foreach ($metadata as $property) {
179
            $this->assertInternalType('string', $property);
180
        }
181
    }
182
183
    public function testTtlCapabilities()
184
    {
185
        $capabilities = $this->_storage->getCapabilities();
186
187
        $this->assertInternalType('integer', $capabilities->getMaxTtl());
188
        $this->assertGreaterThanOrEqual(0, $capabilities->getMaxTtl());
189
190
        $this->assertInternalType('bool', $capabilities->getStaticTtl());
191
192
        $this->assertInternalType('numeric', $capabilities->getTtlPrecision());
193
        $this->assertGreaterThan(0, $capabilities->getTtlPrecision());
194
195
        $this->assertInternalType('bool', $capabilities->getExpiredRead());
196
    }
197
198
    public function testKeyCapabilities()
199
    {
200
        $capabilities = $this->_storage->getCapabilities();
201
202
        $this->assertInternalType('integer', $capabilities->getMaxKeyLength());
203
        $this->assertGreaterThanOrEqual(-1, $capabilities->getMaxKeyLength());
204
205
        $this->assertInternalType('bool', $capabilities->getNamespaceIsPrefix());
206
207
        $this->assertInternalType('string', $capabilities->getNamespaceSeparator());
208
    }
209
210
    public function testHasItemReturnsTrueOnValidItem()
211
    {
212
        $this->assertTrue($this->_storage->setItem('key', 'value'));
213
        $this->assertTrue($this->_storage->hasItem('key'));
214
    }
215
216
    public function testHasItemReturnsFalseOnMissingItem()
217
    {
218
        $this->assertFalse($this->_storage->hasItem('key'));
219
    }
220
221
    public function testHasItemReturnsFalseOnExpiredItem()
222
    {
223
        $capabilities = $this->_storage->getCapabilities();
224
225
        if ($capabilities->getMinTtl() === 0) {
226
            $this->markTestSkipped("Adapter doesn't support item expiration");
227
        }
228
229
        $ttl = $capabilities->getTtlPrecision();
230
        $this->_options->setTtl($ttl);
231
232
        $this->waitForFullSecond();
233
234
        $this->assertTrue($this->_storage->setItem('key', 'value'));
235
236
        // wait until the item expired
237
        $wait = $ttl + $capabilities->getTtlPrecision();
238
        usleep($wait * 2000000);
239
240
        if (!$capabilities->getUseRequestTime()) {
241
            $this->assertFalse($this->_storage->hasItem('key'));
242
        } else {
243
            $this->assertTrue($this->_storage->hasItem('key'));
244
        }
245
    }
246
247
    public function testHasItemNonReadable()
248
    {
249
        $this->assertTrue($this->_storage->setItem('key', 'value'));
250
251
        $this->_options->setReadable(false);
252
        $this->assertFalse($this->_storage->hasItem('key'));
253
    }
254
255
    public function testHasItemsReturnsKeysOfFoundItems()
256
    {
257
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
258
        $this->assertTrue($this->_storage->setItem('key2', 'value2'));
259
260
        $result = $this->_storage->hasItems(['missing', 'key1', 'key2']);
261
        sort($result);
262
263
        $exprectedResult = ['key1', 'key2'];
264
        $this->assertEquals($exprectedResult, $result);
265
    }
266
267
    public function testHasItemsReturnsEmptyArrayIfNonReadable()
268
    {
269
        $this->assertTrue($this->_storage->setItem('key', 'value'));
270
271
        $this->_options->setReadable(false);
272
        $this->assertEquals([], $this->_storage->hasItems(['key']));
273
    }
274
275
    public function testGetItemReturnsNullOnMissingItem()
276
    {
277
        $this->assertNull($this->_storage->getItem('unknwon'));
278
    }
279
280
    public function testGetItemSetsSuccessFlag()
281
    {
282
        $success = null;
283
284
        // $success = false on get missing item
285
        $this->_storage->getItem('unknown', $success);
286
        $this->assertFalse($success);
287
288
        // $success = true on get valid item
289
        $this->_storage->setItem('test', 'test');
290
        $this->_storage->getItem('test', $success);
291
        $this->assertTrue($success);
292
    }
293
294
    public function testGetItemReturnsNullOnExpiredItem()
295
    {
296
        $capabilities = $this->_storage->getCapabilities();
297
298
        if ($capabilities->getMinTtl() === 0) {
299
            $this->markTestSkipped("Adapter doesn't support item expiration");
300
        }
301
302
        if ($capabilities->getUseRequestTime()) {
303
            $this->markTestSkipped("Can't test get expired item if request time will be used");
304
        }
305
306
        $ttl = $capabilities->getTtlPrecision();
307
        $this->_options->setTtl($ttl);
308
309
        $this->waitForFullSecond();
310
311
        $this->_storage->setItem('key', 'value');
312
313
        // wait until expired
314
        $wait = $ttl + $capabilities->getTtlPrecision();
315
        usleep($wait * 2000000);
316
317
        $this->assertNull($this->_storage->getItem('key'));
318
    }
319
320
    public function testGetItemReturnsNullIfNonReadable()
321
    {
322
        $this->_options->setReadable(false);
323
324
        $this->assertTrue($this->_storage->setItem('key', 'value'));
325
        $this->assertNull($this->_storage->getItem('key'));
326
    }
327
328
    public function testGetItemsReturnsKeyValuePairsOfFoundItems()
329
    {
330
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
331
        $this->assertTrue($this->_storage->setItem('key2', 'value2'));
332
333
        $result = $this->_storage->getItems(['missing', 'key1', 'key2']);
334
        ksort($result);
335
336
        $exprectedResult = [
337
            'key1' => 'value1',
338
            'key2' => 'value2',
339
        ];
340
        $this->assertEquals($exprectedResult, $result);
341
    }
342
343
    public function testGetItemsReturnsEmptyArrayIfNonReadable()
344
    {
345
        $this->_options->setReadable(false);
346
347
        $this->assertTrue($this->_storage->setItem('key', 'value'));
348
        $this->assertEquals([], $this->_storage->getItems(['key']));
349
    }
350
351
    public function testGetMetadata()
352
    {
353
        $capabilities = $this->_storage->getCapabilities();
354
        $supportedMetadatas = $capabilities->getSupportedMetadata();
355
356
        $this->assertTrue($this->_storage->setItem('key', 'value'));
357
        $metadata = $this->_storage->getMetadata('key');
358
359
        $this->assertInternalType('array', $metadata);
360
        foreach ($supportedMetadatas as $supportedMetadata) {
361
            $this->assertArrayHasKey($supportedMetadata, $metadata);
362
        }
363
    }
364
365
    public function testGetMetadataReturnsFalseOnMissingItem()
366
    {
367
        $this->assertFalse($this->_storage->getMetadata('unknown'));
368
    }
369
370
    public function testGetMetadataReturnsFalseIfNonReadable()
371
    {
372
        $this->_options->setReadable(false);
373
374
        $this->assertTrue($this->_storage->setItem('key', 'value'));
375
        $this->assertFalse($this->_storage->getMetadata('key'));
376
    }
377
378
    public function testGetMetadatas()
379
    {
380
        $capabilities       = $this->_storage->getCapabilities();
381
        $supportedMetadatas = $capabilities->getSupportedMetadata();
382
383
        $items = [
384
            'key1' => 'value1',
385
            'key2' => 'value2'
386
        ];
387
        $this->assertSame([], $this->_storage->setItems($items));
388
389
        $metadatas = $this->_storage->getMetadatas(array_keys($items));
390
        $this->assertInternalType('array', $metadatas);
391
        $this->assertSame(count($items), count($metadatas));
392
        foreach ($metadatas as $k => $metadata) {
393
            $this->assertInternalType('array', $metadata);
394
            foreach ($supportedMetadatas as $supportedMetadata) {
395
                $this->assertArrayHasKey($supportedMetadata, $metadata);
396
            }
397
        }
398
    }
399
400
    /**
401
     * @group 7031
402
     * @group 7032
403
     */
404
    public function testGetMetadatasWithEmptyNamespace()
405
    {
406
        $this->_options->setNamespace('');
407
        $this->testGetMetadatas();
408
    }
409
410
    public function testGetMetadatasReturnsEmptyArrayIfNonReadable()
411
    {
412
        $this->_options->setReadable(false);
413
414
        $this->assertTrue($this->_storage->setItem('key', 'value'));
415
        $this->assertEquals([], $this->_storage->getMetadatas(['key']));
416
    }
417
418
    public function testSetGetHasAndRemoveItemWithoutNamespace()
419
    {
420
        $this->_storage->getOptions()->setNamespace('');
421
422
        $this->assertTrue($this->_storage->setItem('key', 'value'));
423
        $this->assertEquals('value', $this->_storage->getItem('key'));
424
        $this->assertTrue($this->_storage->hasItem('key'));
425
426
        $this->assertTrue($this->_storage->removeItem('key'));
427
        $this->assertFalse($this->_storage->hasItem('key'));
428
        $this->assertNull($this->_storage->getItem('key'));
429
    }
430
431
    public function testSetGetHasAndRemoveItemsWithoutNamespace()
432
    {
433
        $this->_storage->getOptions()->setNamespace('');
434
435
        $items = [
436
            'key1' => 'value1',
437
            'key2' => 'value2',
438
            'key3' => 'value3',
439
        ];
440
441
        $this->assertSame([], $this->_storage->setItems($items));
442
443
        $rs = $this->_storage->getItems(array_keys($items));
444
        $this->assertInternalType('array', $rs);
445
        foreach ($items as $key => $value) {
446
            $this->assertArrayHasKey($key, $rs);
447
            $this->assertEquals($value, $rs[$key]);
448
        }
449
450
        $rs = $this->_storage->hasItems(array_keys($items));
451
        $this->assertInternalType('array', $rs);
452
        $this->assertEquals(count($items), count($rs));
453
        foreach ($items as $key => $value) {
454
            $this->assertContains($key, $rs);
455
        }
456
457
        $this->assertSame(['missing'], $this->_storage->removeItems(['missing', 'key1', 'key3']));
458
        unset($items['key1'], $items['key3']);
459
460
        $rs = $this->_storage->getItems(array_keys($items));
461
        $this->assertInternalType('array', $rs);
462
        foreach ($items as $key => $value) {
463
            $this->assertArrayHasKey($key, $rs);
464
            $this->assertEquals($value, $rs[$key]);
465
        }
466
467
        $rs = $this->_storage->hasItems(array_keys($items));
468
        $this->assertInternalType('array', $rs);
469
        $this->assertEquals(count($items), count($rs));
470
        foreach ($items as $key => $value) {
471
            $this->assertContains($key, $rs);
472
        }
473
    }
474
475
    public function testSetGetHasAndRemoveItemWithNamespace()
476
    {
477
        // write "key" to default namespace
478
        $this->_options->setNamespace('defaultns1');
479
        $this->assertTrue($this->_storage->setItem('key', 'defaultns1'));
480
481
        // write "key" to an other default namespace
482
        $this->_options->setNamespace('defaultns2');
483
        $this->assertTrue($this->_storage->setItem('key', 'defaultns2'));
484
485
        // test value of defaultns2
486
        $this->assertTrue($this->_storage->hasItem('key'));
487
        $this->assertEquals('defaultns2', $this->_storage->getItem('key'));
488
489
        // test value of defaultns1
490
        $this->_options->setNamespace('defaultns1');
491
        $this->assertTrue($this->_storage->hasItem('key'));
492
        $this->assertEquals('defaultns1', $this->_storage->getItem('key'));
493
494
        // remove item of defaultns1
495
        $this->_options->setNamespace('defaultns1');
496
        $this->assertTrue($this->_storage->removeItem('key'));
497
        $this->assertFalse($this->_storage->hasItem('key'));
498
499
        // remove item of defaultns2
500
        $this->_options->setNamespace('defaultns2');
501
        $this->assertTrue($this->_storage->removeItem('key'));
502
        $this->assertFalse($this->_storage->hasItem('key'));
503
    }
504
505
    public function testSetGetHasAndRemoveItemsWithNamespace()
506
    {
507
        $items = [
508
            'key1' => 'value1',
509
            'key2' => 'value2',
510
            'key3' => 'value3',
511
        ];
512
513
        $this->_options->setNamespace('defaultns1');
514
        $this->assertSame([], $this->_storage->setItems($items));
515
516
        $this->_options->setNamespace('defaultns2');
517
        $this->assertSame([],  $this->_storage->hasItems(array_keys($items)));
0 ignored issues
show
Coding Style introduced by
Expected 1 space instead of 2 after comma in function call.
Loading history...
518
519
        $this->_options->setNamespace('defaultns1');
520
        $rs = $this->_storage->getItems(array_keys($items));
521
        $this->assertInternalType('array', $rs);
522
        foreach ($items as $key => $value) {
523
            $this->assertArrayHasKey($key, $rs);
524
            $this->assertEquals($value, $rs[$key]);
525
        }
526
527
        $rs = $this->_storage->hasItems(array_keys($items));
528
        $this->assertInternalType('array', $rs);
529
        $this->assertEquals(count($items), count($rs));
530
        foreach ($items as $key => $value) {
531
            $this->assertContains($key, $rs);
532
        }
533
534
        // remove the first and the last item
535
        $this->assertSame(['missing'], $this->_storage->removeItems(['missing', 'key1', 'key3']));
536
        unset($items['key1'], $items['key3']);
537
538
        $rs = $this->_storage->getItems(array_keys($items));
539
        $this->assertInternalType('array', $rs);
540
        foreach ($items as $key => $value) {
541
            $this->assertArrayHasKey($key, $rs);
542
            $this->assertEquals($value, $rs[$key]);
543
        }
544
545
        $rs = $this->_storage->hasItems(array_keys($items));
546
        $this->assertInternalType('array', $rs);
547
        $this->assertEquals(count($items), count($rs));
548
        foreach ($items as $key => $value) {
549
            $this->assertContains($key, $rs);
550
        }
551
    }
552
553
    public function testSetAndGetExpiredItem()
554
    {
555
        $capabilities = $this->_storage->getCapabilities();
556
557
        if ($capabilities->getMinTtl() === 0) {
558
            $this->markTestSkipped("Adapter doesn't support item expiration");
559
        }
560
561
        $ttl = $capabilities->getTtlPrecision();
562
        $this->_options->setTtl($ttl);
563
564
        $this->waitForFullSecond();
565
566
        $this->_storage->setItem('key', 'value');
567
568
        // wait until expired
569
        $wait = $ttl + $capabilities->getTtlPrecision();
570
        usleep($wait * 2000000);
571
572
        if ($capabilities->getUseRequestTime()) {
573
            // Can't test much more if the request time will be used
574
            $this->assertEquals('value', $this->_storage->getItem('key'));
575
            return;
576
        }
577
578
        $this->assertNull($this->_storage->getItem('key'));
579
580
        $this->_options->setTtl(0);
581
        if ($capabilities->getExpiredRead()) {
582
            $this->assertEquals('value', $this->_storage->getItem('key'));
583
        } else {
584
            $this->assertNull($this->_storage->getItem('key'));
585
        }
586
    }
587
588
    public function testSetAndGetExpiredItems()
589
    {
590
        $capabilities = $this->_storage->getCapabilities();
591
592
        if ($capabilities->getMinTtl() === 0) {
593
            $this->markTestSkipped("Adapter doesn't support item expiration");
594
        }
595
596
        // item definition
597
        $itemsHigh = [
598
            'keyHigh1' => 'valueHigh1',
599
            'keyHigh2' => 'valueHigh2',
600
            'keyHigh3' => 'valueHigh3'
601
        ];
602
        $itemsLow = [
603
            'keyLow1' => 'valueLow1',
604
            'keyLow2' => 'valueLow2',
605
            'keyLow3' => 'valueLow3'
606
        ];
607
        $items = $itemsHigh + $itemsLow;
608
609
        // set items with high TTL
610
        $this->_options->setTtl(123456);
611
        $this->assertSame([], $this->_storage->setItems($itemsHigh));
612
613
        // set items with low TTL
614
        $ttl = $capabilities->getTtlPrecision();
615
        $this->_options->setTtl($ttl);
616
        $this->waitForFullSecond();
617
        $this->assertSame([], $this->_storage->setItems($itemsLow));
618
619
        // wait until expired
620
        $wait = $ttl + $capabilities->getTtlPrecision();
621
        usleep($wait * 2000000);
622
623
        $rs = $this->_storage->getItems(array_keys($items));
624
        ksort($rs); // make comparable
625
626
        if ($capabilities->getExpiredRead()) {
627
            // if item expiration will be done on read there is no difference
628
            // between the previos set items in TTL.
629
            // -> all items will be expired
630
            $this->assertEquals([], $rs);
631
632
            // after disabling TTL all items will be available
633
            $this->_options->setTtl(0);
634
            $rs = $this->_storage->getItems(array_keys($items));
635
            ksort($rs); // make comparable
636
            $this->assertEquals($items, $rs);
637
        } elseif ($capabilities->getUseRequestTime()) {
638
            // if the request time will be used as current time all items will
639
            // be available as expiration doesn't work within the same process
640
            $this->assertEquals($items, $rs);
641
        } else {
642
            $this->assertEquals($itemsHigh, $rs);
643
        }
644
    }
645
646
    public function testSetAndGetItemOfDifferentTypes()
647
    {
648
        $capabilities = $this->_storage->getCapabilities();
649
650
        $types = [
651
            'NULL'     => null,
652
            'boolean'  => true,
653
            'integer'  => 12345,
654
            'double'   => 123.45,
655
            'string'   => 'string', // already tested
656
            'array'    => ['one', 'tow' => 'two', 'three' => ['four' => 'four']],
657
            'object'   => new \stdClass(),
658
            'resource' => fopen(__FILE__, 'r'),
659
        ];
660
        $types['object']->one = 'one';
661
        $types['object']->two = new \stdClass();
662
        $types['object']->two->three = 'three';
663
664
        foreach ($capabilities->getSupportedDatatypes() as $sourceType => $targetType) {
665
            if ($targetType === false) {
666
                continue;
667
            }
668
669
            $value = $types[$sourceType];
670
            $this->assertTrue($this->_storage->setItem('key', $value), "Failed to set type '{$sourceType}'");
671
672
            if ($targetType === true) {
673
                $this->assertSame($value, $this->_storage->getItem('key'));
674
            } elseif (is_string($targetType)) {
675
                settype($value, $targetType);
676
                $this->assertEquals($value, $this->_storage->getItem('key'));
677
            }
678
        }
679
    }
680
681
    public function testSetItemReturnsFalseIfNonWritable()
682
    {
683
        $this->_options->setWritable(false);
684
685
        $this->assertFalse($this->_storage->setItem('key', 'value'));
686
        $this->assertFalse($this->_storage->hasItem('key'));
687
    }
688
689
    public function testAddNewItem()
690
    {
691
        $this->assertTrue($this->_storage->addItem('key', 'value'));
692
        $this->assertTrue($this->_storage->hasItem('key'));
693
    }
694
695
    public function testAddItemReturnsFalseIfItemAlreadyExists()
696
    {
697
        $this->assertTrue($this->_storage->setItem('key', 'value'));
698
        $this->assertFalse($this->_storage->addItem('key', 'newValue'));
699
    }
700
701
    public function testAddItemReturnsFalseIfNonWritable()
702
    {
703
        $this->_options->setWritable(false);
704
705
        $this->assertFalse($this->_storage->addItem('key', 'value'));
706
        $this->assertFalse($this->_storage->hasItem('key'));
707
    }
708
709
    public function testAddItemsReturnsFailedKeys()
710
    {
711
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
712
713
        $failedKeys = $this->_storage->addItems([
714
            'key1' => 'XYZ',
715
            'key2' => 'value2',
716
        ]);
717
718
        $this->assertSame(['key1'], $failedKeys);
719
        $this->assertSame('value1', $this->_storage->getItem('key1'));
720
        $this->assertTrue($this->_storage->hasItem('key2'));
721
    }
722
723
    public function testAddItemSetsTTL()
724
    {
725
        $capabilities = $this->_storage->getCapabilities();
726
727
        if ($capabilities->getMinTtl() === 0) {
728
            $this->markTestSkipped("Adapter doesn't support item expiration");
729
        }
730
731
        $ttl = $capabilities->getTtlPrecision();
732
        $this->_options->setTtl($ttl);
733
734
        $this->waitForFullSecond();
735
736
        $this->assertTrue($this->_storage->addItem('key', 'value'));
737
738
        // wait until the item expired
739
        $wait = $ttl + $capabilities->getTtlPrecision();
740
        usleep($wait * 2000000);
741
742
        if (!$capabilities->getUseRequestTime()) {
743
            $this->assertFalse($this->_storage->hasItem('key'));
744
        } else {
745
            $this->assertTrue($this->_storage->hasItem('key'));
746
        }
747
    }
748
749
    public function testReplaceExistingItem()
750
    {
751
        $this->assertTrue($this->_storage->setItem('key', 'value'));
752
        $this->assertTrue($this->_storage->replaceItem('key', 'anOtherValue'));
753
        $this->assertEquals('anOtherValue', $this->_storage->getItem('key'));
754
    }
755
756
    public function testReplaceItemReturnsFalseOnMissingItem()
757
    {
758
        $this->assertFalse($this->_storage->replaceItem('missingKey', 'value'));
759
    }
760
761
    public function testReplaceItemReturnsFalseIfNonWritable()
762
    {
763
        $this->_storage->setItem('key', 'value');
764
        $this->_options->setWritable(false);
765
766
        $this->assertFalse($this->_storage->replaceItem('key', 'newvalue'));
767
        $this->assertEquals('value', $this->_storage->getItem('key'));
768
    }
769
770
    public function testReplaceItemsReturnsFailedKeys()
771
    {
772
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
773
774
        $failedKeys = $this->_storage->replaceItems([
775
            'key1' => 'XYZ',
776
            'key2' => 'value2',
777
        ]);
778
779
        $this->assertSame(['key2'], $failedKeys);
780
        $this->assertSame('XYZ', $this->_storage->getItem('key1'));
781
        $this->assertFalse($this->_storage->hasItem('key2'));
782
    }
783
784
    public function testRemoveItemReturnsFalseOnMissingItem()
785
    {
786
        $this->assertFalse($this->_storage->removeItem('missing'));
787
    }
788
789
    public function testRemoveItemsReturnsMissingKeys()
790
    {
791
        $this->_storage->setItem('key', 'value');
792
        $this->assertSame(['missing'], $this->_storage->removeItems(['key', 'missing']));
793
    }
794
795
    public function testCheckAndSetItem()
796
    {
797
        $this->assertTrue($this->_storage->setItem('key', 'value'));
798
799
        $success  = null;
800
        $casToken = null;
801
        $this->assertEquals('value', $this->_storage->getItem('key', $success, $casToken));
802
        $this->assertNotNull($casToken);
803
804
        $this->assertTrue($this->_storage->checkAndSetItem($casToken, 'key', 'newValue'));
805
        $this->assertFalse($this->_storage->checkAndSetItem($casToken, 'key', 'failedValue'));
806
        $this->assertEquals('newValue', $this->_storage->getItem('key'));
807
    }
808
809
    public function testIncrementItem()
810
    {
811
        $this->assertTrue($this->_storage->setItem('counter', 10));
812
        $this->assertEquals(15, $this->_storage->incrementItem('counter', 5));
813
        $this->assertEquals(15, $this->_storage->getItem('counter'));
814
    }
815
816
    public function testIncrementItemInitialValue()
817
    {
818
        $this->assertEquals(5, $this->_storage->incrementItem('counter', 5));
819
        $this->assertEquals(5, $this->_storage->getItem('counter'));
820
    }
821
822
    public function testIncrementItemReturnsFalseIfNonWritable()
823
    {
824
        $this->_storage->setItem('key', 10);
825
        $this->_options->setWritable(false);
826
827
        $this->assertFalse($this->_storage->incrementItem('key', 5));
828
        $this->assertEquals(10, $this->_storage->getItem('key'));
829
    }
830
831
    public function testIncrementItemsResturnsKeyValuePairsOfWrittenItems()
832
    {
833
        $this->assertTrue($this->_storage->setItem('key1', 10));
834
835
        $result = $this->_storage->incrementItems([
836
            'key1' => 10,
837
            'key2' => 10,
838
        ]);
839
        ksort($result);
840
841
        $this->assertSame([
842
            'key1' => 20,
843
            'key2' => 10,
844
        ], $result);
845
    }
846
847
    public function testIncrementItemsReturnsEmptyArrayIfNonWritable()
848
    {
849
        $this->_storage->setItem('key', 10);
850
        $this->_options->setWritable(false);
851
852
        $this->assertSame([], $this->_storage->incrementItems(['key' => 5]));
853
        $this->assertEquals(10, $this->_storage->getItem('key'));
854
    }
855
856
    public function testDecrementItem()
857
    {
858
        $this->assertTrue($this->_storage->setItem('counter', 30));
859
        $this->assertEquals(25, $this->_storage->decrementItem('counter', 5));
860
        $this->assertEquals(25, $this->_storage->getItem('counter'));
861
    }
862
863
    public function testDecrementItemInitialValue()
864
    {
865
        $this->assertEquals(-5, $this->_storage->decrementItem('counter', 5));
866
        $this->assertEquals(-5, $this->_storage->getItem('counter'));
867
    }
868
869
    public function testDecrementItemReturnsFalseIfNonWritable()
870
    {
871
        $this->_storage->setItem('key', 10);
872
        $this->_options->setWritable(false);
873
874
        $this->assertFalse($this->_storage->decrementItem('key', 5));
875
        $this->assertEquals(10, $this->_storage->getItem('key'));
876
    }
877
878
    public function testDecrementItemsReturnsEmptyArrayIfNonWritable()
879
    {
880
        $this->_storage->setItem('key', 10);
881
        $this->_options->setWritable(false);
882
883
        $this->assertSame([], $this->_storage->decrementItems(['key' => 5]));
884
        $this->assertEquals(10, $this->_storage->getItem('key'));
885
    }
886
887
    public function testTouchItem()
888
    {
889
        $capabilities = $this->_storage->getCapabilities();
890
891
        if ($capabilities->getMinTtl() === 0) {
892
            $this->markTestSkipped("Adapter doesn't support item expiration");
893
        }
894
895
        $this->_options->setTtl(2 * $capabilities->getTtlPrecision());
896
897
        $this->waitForFullSecond();
898
899
        $this->assertTrue($this->_storage->setItem('key', 'value'));
900
901
        // sleep 1 times before expire to touch the item
902
        usleep($capabilities->getTtlPrecision() * 1000000);
903
        $this->assertTrue($this->_storage->touchItem('key'));
904
905
        usleep($capabilities->getTtlPrecision() * 1000000);
906
        $this->assertTrue($this->_storage->hasItem('key'));
907
908
        if (!$capabilities->getUseRequestTime()) {
909
            usleep($capabilities->getTtlPrecision() * 2000000);
910
            $this->assertFalse($this->_storage->hasItem('key'));
911
        }
912
    }
913
914
    public function testTouchItemReturnsFalseOnMissingItem()
915
    {
916
        $this->assertFalse($this->_storage->touchItem('missing'));
917
    }
918
919
    public function testTouchItemReturnsFalseIfNonWritable()
920
    {
921
        $this->_options->setWritable(false);
922
923
        $this->assertFalse($this->_storage->touchItem('key'));
924
    }
925
926
    public function testTouchItemsReturnsGivenKeysIfNonWritable()
927
    {
928
        $this->_options->setWritable(false);
929
        $this->assertSame(['key'], $this->_storage->touchItems(['key']));
930
    }
931
932
    public function testOptimize()
933
    {
934
        if (!($this->_storage instanceof OptimizableInterface)) {
935
            $this->markTestSkipped("Storage doesn't implement OptimizableInterface");
936
        }
937
938
        $this->assertTrue($this->_storage->optimize());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method optimize() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
939
    }
940
941
    public function testIterator()
942
    {
943
        if (!$this->_storage instanceof IterableInterface) {
944
            $this->markTestSkipped("Storage doesn't implement IterableInterface");
945
        }
946
947
        $items = [
948
            'key1' => 'value1',
949
            'key2' => 'value2',
950
        ];
951
        $this->assertSame([], $this->_storage->setItems($items));
952
953
        // check iterator aggregate
954
        $iterator = $this->_storage->getIterator();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getIterator() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\XCache.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
955
        $this->assertInstanceOf('Zend\Cache\Storage\IteratorInterface', $iterator);
956
        $this->assertSame(IteratorInterface::CURRENT_AS_KEY, $iterator->getMode());
957
958
        // check mode CURRENT_AS_KEY
959
        $iterator = $this->_storage->getIterator();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getIterator() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\XCache.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
960
        $iterator->setMode(IteratorInterface::CURRENT_AS_KEY);
961
        $keys = iterator_to_array($iterator, false);
962
        sort($keys);
963
        $this->assertSame(array_keys($items), $keys);
964
965
        // check mode CURRENT_AS_VALUE
966
        $iterator = $this->_storage->getIterator();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getIterator() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\XCache.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
967
        $iterator->setMode(IteratorInterface::CURRENT_AS_VALUE);
968
        $result = iterator_to_array($iterator, true);
969
        ksort($result);
970
        $this->assertSame($items, $result);
971
    }
972
973
    public function testFlush()
974
    {
975
        if (!($this->_storage instanceof FlushableInterface)) {
976
            $this->markTestSkipped("Storage doesn't implement OptimizableInterface");
977
        }
978
979
        $this->assertSame([], $this->_storage->setItems([
980
            'key1' => 'value1',
981
            'key2' => 'value2',
982
        ]));
983
984
        $this->assertTrue($this->_storage->flush());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method flush() does only exist in the following implementations of said interface: MehrAlsNix\ZF\Cache\Storage\Adapter\Couchbase, Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memcache, Zend\Cache\Storage\Adapter\Memcached, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\MongoDb, Zend\Cache\Storage\Adapter\Redis, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\WinCache, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
985
        $this->assertFalse($this->_storage->hasItem('key1'));
986
        $this->assertFalse($this->_storage->hasItem('key2'));
987
    }
988
989
    public function testClearByPrefix()
990
    {
991
        if (!($this->_storage instanceof ClearByPrefixInterface)) {
992
            $this->markTestSkipped("Storage doesn't implement ClearByPrefixInterface");
993
        }
994
995
        $this->assertSame([], $this->_storage->setItems([
996
            'key1' => 'value1',
997
            'key2' => 'value2',
998
            'test' => 'value',
999
        ]));
1000
1001
        $this->assertTrue($this->_storage->clearByPrefix('key'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByPrefix() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Redis, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\XCache.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1002
        $this->assertFalse($this->_storage->hasItem('key1'));
1003
        $this->assertFalse($this->_storage->hasItem('key2'));
1004
        $this->assertTrue($this->_storage->hasItem('test'));
1005
    }
1006
1007
    public function testClearByPrefixThrowsInvalidArgumentExceptionOnEmptyPrefix()
1008
    {
1009
        if (!($this->_storage instanceof ClearByPrefixInterface)) {
1010
            $this->markTestSkipped("Storage doesn't implement ClearByPrefixInterface");
1011
        }
1012
1013
        $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException');
1014
        $this->_storage->clearByPrefix('');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByPrefix() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Redis, Zend\Cache\Storage\Adapter\Session, Zend\Cache\Storage\Adapter\XCache.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1015
    }
1016
1017
    public function testClearByNamespace()
1018
    {
1019
        if (!($this->_storage instanceof ClearByNamespaceInterface)) {
1020
            $this->markTestSkipped("Storage doesn't implement ClearByNamespaceInterface");
1021
        }
1022
1023
        // write 2 items of 2 different namespaces
1024
        $this->_options->setNamespace('ns1');
1025
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
1026
        $this->_options->setNamespace('ns2');
1027
        $this->assertTrue($this->_storage->setItem('key2', 'value2'));
1028
1029
        // clear unknown namespace should return true but clear nothing
1030
        $this->assertTrue($this->_storage->clearByNamespace('unknown'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByNamespace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1031
        $this->_options->setNamespace('ns1');
1032
        $this->assertTrue($this->_storage->hasItem('key1'));
1033
        $this->_options->setNamespace('ns2');
1034
        $this->assertTrue($this->_storage->hasItem('key2'));
1035
1036
        // clear "ns1"
1037
        $this->assertTrue($this->_storage->clearByNamespace('ns1'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByNamespace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1038
        $this->_options->setNamespace('ns1');
1039
        $this->assertFalse($this->_storage->hasItem('key1'));
1040
        $this->_options->setNamespace('ns2');
1041
        $this->assertTrue($this->_storage->hasItem('key2'));
1042
1043
        // clear "ns2"
1044
        $this->assertTrue($this->_storage->clearByNamespace('ns2'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByNamespace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1045
        $this->_options->setNamespace('ns1');
1046
        $this->assertFalse($this->_storage->hasItem('key1'));
1047
        $this->_options->setNamespace('ns2');
1048
        $this->assertFalse($this->_storage->hasItem('key2'));
1049
    }
1050
1051
    public function testClearByNamespaceThrowsInvalidArgumentExceptionOnEmptyNamespace()
1052
    {
1053
        if (!($this->_storage instanceof ClearByNamespaceInterface)) {
1054
            $this->markTestSkipped("Storage doesn't implement ClearByNamespaceInterface");
1055
        }
1056
1057
        $this->setExpectedException('Zend\Cache\Exception\InvalidArgumentException');
1058
        $this->_storage->clearByNamespace('');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByNamespace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1059
    }
1060
1061
    public function testClearExpired()
1062
    {
1063
        if (!($this->_storage instanceof ClearExpiredInterface)) {
1064
            $this->markTestSkipped("Storage doesn't implement ClearExpiredInterface");
1065
        }
1066
1067
        $capabilities = $this->_storage->getCapabilities();
1068
        $ttl = $capabilities->getTtlPrecision();
1069
        $this->_options->setTtl($ttl);
1070
1071
        $this->waitForFullSecond();
1072
1073
        $this->assertTrue($this->_storage->setItem('key1', 'value1'));
1074
1075
        // wait until the first item expired
1076
        $wait = $ttl + $capabilities->getTtlPrecision();
1077
        usleep($wait * 2000000);
1078
1079
        $this->assertTrue($this->_storage->setItem('key2', 'value2'));
1080
1081
        $this->assertTrue($this->_storage->clearExpired());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearExpired() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1082
1083
        if ($capabilities->getUseRequestTime()) {
1084
            $this->assertTrue($this->_storage->hasItem('key1'));
1085
        } else {
1086
            $this->assertFalse($this->_storage->hasItem('key1', ['ttl' => 0]));
0 ignored issues
show
Unused Code introduced by
The call to StorageInterface::hasItem() has too many arguments starting with array('ttl' => 0).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1087
        }
1088
1089
        $this->assertTrue($this->_storage->hasItem('key2'));
1090
    }
1091
1092
    public function testTaggable()
1093
    {
1094
        if (!($this->_storage instanceof TaggableInterface)) {
1095
            $this->markTestSkipped("Storage doesn't implement TaggableInterface");
1096
        }
1097
1098
        // store 3 items and register the current default namespace
1099
        $this->assertSame([], $this->_storage->setItems([
1100
            'key1' => 'value1',
1101
            'key2' => 'value2',
1102
            'key3' => 'value3',
1103
        ]));
1104
1105
        $this->assertTrue($this->_storage->setTags('key1', ['tag1a', 'tag1b']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method setTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1106
        $this->assertTrue($this->_storage->setTags('key2', ['tag2a', 'tag2b']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method setTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1107
        $this->assertTrue($this->_storage->setTags('key3', ['tag3a', 'tag3b']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method setTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1108
        $this->assertFalse($this->_storage->setTags('missing', ['tag']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method setTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1109
1110
        // return tags
1111
        $tags = $this->_storage->getTags('key1');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1112
        $this->assertInternalType('array', $tags);
1113
        sort($tags);
1114
        $this->assertSame(['tag1a', 'tag1b'], $tags);
1115
1116
        // this should remove nothing
1117
        $this->assertTrue($this->_storage->clearByTags(['tag1a', 'tag2a']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1118
        $this->assertTrue($this->_storage->hasItem('key1'));
1119
        $this->assertTrue($this->_storage->hasItem('key2'));
1120
        $this->assertTrue($this->_storage->hasItem('key3'));
1121
1122
        // this should remove key1 and key2
1123
        $this->assertTrue($this->_storage->clearByTags(['tag1a', 'tag2b'], true));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1124
        $this->assertFalse($this->_storage->hasItem('key1'));
1125
        $this->assertFalse($this->_storage->hasItem('key2'));
1126
        $this->assertTrue($this->_storage->hasItem('key3'));
1127
1128
        // this should remove key3
1129
        $this->assertTrue($this->_storage->clearByTags(['tag3a', 'tag3b'], true));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1130
        $this->assertFalse($this->_storage->hasItem('key1'));
1131
        $this->assertFalse($this->_storage->hasItem('key2'));
1132
        $this->assertFalse($this->_storage->hasItem('key3'));
1133
    }
1134
1135
    /**
1136
     * @group 6878
1137
     */
1138
    public function testTaggableFunctionsOnEmptyStorage()
1139
    {
1140
        if (!($this->_storage instanceof TaggableInterface)) {
1141
            $this->markTestSkipped("Storage doesn't implement TaggableInterface");
1142
        }
1143
1144
        $this->assertFalse($this->_storage->setTags('unknown', ['no']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method setTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1145
        $this->assertFalse($this->_storage->getTags('unknown'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1146
        $this->assertTrue($this->_storage->clearByTags(['unknown']));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method clearByTags() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memory.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1147
    }
1148
1149
    public function testGetTotalSpace()
1150
    {
1151
        if (!($this->_storage instanceof TotalSpaceCapableInterface)) {
1152
            $this->markTestSkipped("Storage doesn't implement TotalSpaceCapableInterface");
1153
        }
1154
1155
        $totalSpace = $this->_storage->getTotalSpace();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getTotalSpace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memcache, Zend\Cache\Storage\Adapter\Memcached, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\Redis, Zend\Cache\Storage\Adapter\WinCache, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk, Zend\Cache\Storage\Adapter\ZendServerShm.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1156
        $this->assertGreaterThanOrEqual(0, $totalSpace);
1157
1158
        if ($this->_storage instanceof AvailableSpaceCapableInterface) {
1159
            $availableSpace = $this->_storage->getAvailableSpace();
1160
            $this->assertGreaterThanOrEqual($availableSpace, $totalSpace);
1161
        }
1162
    }
1163
1164
    public function testGetAvailableSpace()
1165
    {
1166
        if (!($this->_storage instanceof AvailableSpaceCapableInterface)) {
1167
            $this->markTestSkipped("Storage doesn't implement AvailableSpaceCapableInterface");
1168
        }
1169
1170
        $availableSpace = $this->_storage->getAvailableSpace();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Zend\Cache\Storage\StorageInterface as the method getAvailableSpace() does only exist in the following implementations of said interface: Zend\Cache\Storage\Adapter\Apc, Zend\Cache\Storage\Adapter\BlackHole, Zend\Cache\Storage\Adapter\Dba, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\Memcache, Zend\Cache\Storage\Adapter\Memcached, Zend\Cache\Storage\Adapter\Memory, Zend\Cache\Storage\Adapter\WinCache, Zend\Cache\Storage\Adapter\XCache, Zend\Cache\Storage\Adapter\ZendServerDisk.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1171
        $this->assertGreaterThanOrEqual(0, $availableSpace);
1172
1173
        if ($this->_storage instanceof TotalSpaceCapableInterface) {
1174
            $totalSpace = $this->_storage->getTotalSpace();
1175
            $this->assertLessThanOrEqual($totalSpace, $availableSpace);
1176
        }
1177
    }
1178
1179
    /**
1180
     * This will wait for a full second started
1181
     * to reduce test failures on high load servers
1182
     * @see https://github.com/zendframework/zf2/issues/5144
1183
     */
1184
    protected function waitForFullSecond()
1185
    {
1186
        $interval = (microtime(true)-time()) * 1000000;
1187
        usleep((int) $interval);
1188
    }
1189
}
1190