Passed
Push — bump-dependencies ( 3eb1c7...418b80 )
by Mattia
15:26 queued 12:02
created

PatchManager::handleSubject()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.3332

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 10
ccs 4
cts 6
cp 0.6667
crap 3.3332
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cypress\PatchManager;
6
7
use Cypress\PatchManager\Event\PatchManagerEvent;
8
use Cypress\PatchManager\Event\PatchManagerEvents;
9
use Cypress\PatchManager\Exception\HandlerNotFoundException;
10
use PhpCollection\Sequence;
11
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
12
13
/**
14
 * The main entry point for the PatchManager bundle
15
 */
16
class PatchManager
17
{
18
    private OperationMatcher $operationMatcher;
0 ignored issues
show
Coding Style introduced by
Private member variable "operationMatcher" must contain a leading underscore
Loading history...
19
20
    private EventDispatcherInterface $eventDispatcherInterface;
0 ignored issues
show
Coding Style introduced by
Private member variable "eventDispatcherInterface" must contain a leading underscore
Loading history...
21
22
    private bool $strictMode;
0 ignored issues
show
Coding Style introduced by
Private member variable "strictMode" must contain a leading underscore
Loading history...
23
24
    /**
25
     * @param bool $strictMode if true throws an error if no handler is found
26
     */
27 4
    public function __construct(OperationMatcher $operationMatcher, bool $strictMode = false)
28
    {
29 4
        $this->operationMatcher = $operationMatcher;
30 4
        $this->strictMode = $strictMode;
31
    }
32
33 4
    public function setEventDispatcherInterface(EventDispatcherInterface $eventDispatcherInterface): void
34
    {
35 4
        $this->eventDispatcherInterface = $eventDispatcherInterface;
36
    }
37
38
    /**
39
     * @param array<Patchable>|Patchable|\Traversable $subject a Patchable instance or a collection of instances
40
     * @throws Exception\InvalidJsonRequestContent
41
     * @throws Exception\MissingOperationNameRequest
42
     * @throws Exception\MissingOperationRequest
43
     * @throws HandlerNotFoundException
44
     */
45 4
    public function handle($subject): void
46
    {
47 4
        $matchedOperations = $this->getMatchedOperations($subject);
48 2
        $this->handleSubject($subject, $matchedOperations);
49
    }
50
51 2
    protected function doHandle(MatchedPatchOperation $matchedPatchOperation, Patchable $subject): void
52
    {
53 2
        $event = new PatchManagerEvent($matchedPatchOperation, $subject);
54 2
        $this->dispatchEvents($event, $matchedPatchOperation->getOpName(), PatchManagerEvents::PATCH_MANAGER_PRE);
55
56 2
        $matchedPatchOperation->process($subject);
57 2
        $this->dispatchEvents($event, $matchedPatchOperation->getOpName(), PatchManagerEvents::PATCH_MANAGER_POST);
58
    }
59
60
    /**
61
     * dispatch events if the eventDispatcher is present
62
     */
63 2
    protected function dispatchEvents(PatchManagerEvent $event, string $opName, string $type): void
64
    {
65 2
        if (!isset($this->eventDispatcherInterface)) {
66
            return;
67
        }
68 2
        $this->eventDispatcherInterface->dispatch($event, $type);
69 2
        $this->eventDispatcherInterface->dispatch(
70 2
            $event,
71 2
            sprintf('%s.%s', $type, $opName)
72 2
        );
73
    }
74
75
    /**
76
     * @param array|Patchable|\Traversable $subject a Patchable instance or a collection of instances
77
     * @throws Exception\InvalidJsonRequestContent
78
     * @throws Exception\MissingOperationNameRequest
79
     * @throws Exception\MissingOperationRequest
80
     * @throws HandlerNotFoundException
81
     */
82 4
    private function getMatchedOperations($subject): Sequence
83
    {
84 4
        $matchedOperations = $this->operationMatcher->getMatchedOperations($subject);
85 4
        if ($this->strictMode && $matchedOperations->isEmpty()) {
86 2
            throw new HandlerNotFoundException($this->operationMatcher->getUnmatchedOperations($subject));
87
        }
88
89 2
        return $matchedOperations;
90
    }
91
92
    /**
93
     * @param iterable|Patchable $subject a Patchable instance or a collection of instances
94
     * @throws Exception\MissingOperationNameRequest
95
     * @throws Exception\MissingOperationRequest
96
     * @throws Exception\InvalidJsonRequestContent
97
     */
98 2
    private function handleSubject(Patchable|iterable $subject, Sequence $matchedOperations): void
99
    {
100 2
        if (is_iterable($subject)) {
101 2
            $this->handleMany($subject);
0 ignored issues
show
Bug introduced by
It seems like $subject can also be of type Cypress\PatchManager\Patchable; however, parameter $subjects of Cypress\PatchManager\PatchManager::handleMany() does only seem to accept iterable, maybe add an additional type check? ( Ignorable by Annotation )

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

101
            $this->handleMany(/** @scrutinizer ignore-type */ $subject);
Loading history...
102
103 2
            return;
104
        }
105
106
        foreach ($matchedOperations as $matchedPatchOperation) {
107
            $this->doHandle($matchedPatchOperation, $subject);
108
        }
109
    }
110
111
    /**
112
     * @param array<Patchable>|\Traversable<Patchable> $subjects
113
     * @throws Exception\InvalidJsonRequestContent
114
     * @throws Exception\MissingOperationNameRequest
115
     * @throws Exception\MissingOperationRequest
116
     */
117 2
    private function handleMany(iterable $subjects): void
118
    {
119 2
        foreach ($subjects as $subject) {
120 2
            foreach ($this->operationMatcher->getMatchedOperations($subject) as $matchedPatchOperation) {
121 2
                $this->doHandle($matchedPatchOperation, $subject);
122
            }
123
        }
124
    }
125
}
126