StateResetter   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 28
c 3
b 0
f 0
dl 0
loc 70
ccs 34
cts 34
cp 1
rs 10
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A reset() 0 8 3
B setResetters() 0 36 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Di;
6
7
use Closure;
8
use InvalidArgumentException;
9
use Psr\Container\ContainerInterface;
10
11
use function is_int;
12
use function is_object;
13
14
/**
15
 * State resetter allows resetting state of the services that are currently stored in the container and have "reset"
16
 * callback defined. The reset should be triggered after each request-response cycle in case you build long-running
17
 * applications with tools like [Swoole](https://www.swoole.co.uk/) or [RoadRunner](https://roadrunner.dev/).
18
 */
19
final class StateResetter
20
{
21
    /**
22
     * @var Closure[]|self[]
23
     */
24
    private array $resetters = [];
25
26
    /**
27
     * @param ContainerInterface $container Container to reset.
28
     */
29 13
    public function __construct(
30
        private ContainerInterface $container
31
    ) {
32 13
    }
33
34
    /**
35
     * Reset the container.
36
     */
37 10
    public function reset(): void
38
    {
39 10
        foreach ($this->resetters as $resetter) {
40 10
            if ($resetter instanceof self) {
41 4
                $resetter->reset();
42 4
                continue;
43
            }
44 10
            $resetter($this->container);
45
        }
46
    }
47
48
    /**
49
     * @param Closure[]|self[] $resetters Array of reset callbacks. Each callback has access to the private and
50
     * protected properties of the service instance, so you can set the initial state of the service efficiently
51
     * without creating a new instance.
52
     */
53 13
    public function setResetters(array $resetters): void
54
    {
55 13
        $this->resetters = [];
56 13
        foreach ($resetters as $serviceId => $callback) {
57 13
            if (is_int($serviceId)) {
58 5
                if (!$callback instanceof self) {
59 1
                    throw new InvalidArgumentException(sprintf(
60 1
                        'State resetter object should be instance of "%s", "%s" given.',
61 1
                        self::class,
62 1
                        get_debug_type($callback)
63 1
                    ));
64
                }
65 4
                $this->resetters[] = $callback;
66 4
                continue;
67
            }
68
69 12
            if (!$callback instanceof Closure) {
70 1
                throw new InvalidArgumentException(
71 1
                    'Callback for state resetter should be closure in format ' .
72 1
                    '`function (ContainerInterface $container): void`. ' .
73 1
                    'Got "' . get_debug_type($callback) . '".'
74 1
                );
75
            }
76
77
            /** @var mixed $instance */
78 11
            $instance = $this->container->get($serviceId);
79 11
            if (!is_object($instance)) {
80 1
                throw new InvalidArgumentException(
81 1
                    'State resetter supports resetting objects only. Container returned '
82 1
                    . get_debug_type($instance)
83 1
                    . '.'
84 1
                );
85
            }
86
87
            /** @var Closure */
88 10
            $this->resetters[] = $callback->bindTo($instance, $instance::class);
0 ignored issues
show
Bug introduced by
The property resetters does not seem to exist on Closure.
Loading history...
89
        }
90
    }
91
}
92