Passed
Push — master ( 476690...48bca4 )
by Mattia
46s queued 12s
created

PatchManager::dispatchEvents()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 3
dl 0
loc 9
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Cypress\PatchManager;
4
5
use Cypress\PatchManager\Event\PatchManagerEvent;
6
use Cypress\PatchManager\Event\PatchManagerEvents;
7
use Cypress\PatchManager\Exception\HandlerNotFoundException;
8
use PhpCollection\Sequence;
9
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
10
11
/**
12
 * The main entry point for the PatchManager bundle
13
 */
14
class PatchManager
15
{
16
    /**
17
     * @var OperationMatcher
18
     */
19
    private OperationMatcher $operationMatcher;
0 ignored issues
show
Coding Style introduced by
Private member variable "operationMatcher" must contain a leading underscore
Loading history...
20
21
    /**
22
     * @var EventDispatcherInterface
23
     */
24
    private EventDispatcherInterface $eventDispatcherInterface;
0 ignored issues
show
Coding Style introduced by
Private member variable "eventDispatcherInterface" must contain a leading underscore
Loading history...
25
26
    /**
27
     * @var bool
28
     */
29
    private bool $strictMode;
0 ignored issues
show
Coding Style introduced by
Private member variable "strictMode" must contain a leading underscore
Loading history...
30
31
    /**
32
     * @param OperationMatcher $operationMatcher
33
     * @param bool $strictMode if true throws an error if no handler is found
34
     */
35 5
    public function __construct(OperationMatcher $operationMatcher, bool $strictMode = false)
36
    {
37 5
        $this->operationMatcher = $operationMatcher;
38 5
        $this->strictMode = $strictMode;
39 5
    }
40
41
    /**
42
     * @param EventDispatcherInterface $eventDispatcherInterface
43
     */
44 5
    public function setEventDispatcherInterface(EventDispatcherInterface $eventDispatcherInterface): void
45
    {
46 5
        $this->eventDispatcherInterface = $eventDispatcherInterface;
47 5
    }
48
49
    /**
50
     * @param array<Patchable>|Patchable|\Traversable $subject a Patchable instance or a collection of instances
51
     * @throws Exception\InvalidJsonRequestContent
52
     * @throws Exception\MissingOperationNameRequest
53
     * @throws Exception\MissingOperationRequest
54
     * @throws HandlerNotFoundException
55
     */
56 5
    public function handle($subject): void
57
    {
58 5
        $matchedOperations = $this->getMatchedOperations($subject);
59 3
        $this->handleSubject($subject, $matchedOperations);
60 2
    }
61
62
    /**
63
     * @param MatchedPatchOperation $matchedPatchOperation
64
     * @param Patchable $subject
65
     */
66 3
    protected function doHandle(MatchedPatchOperation $matchedPatchOperation, Patchable $subject): void
67
    {
68 3
        $event = new PatchManagerEvent($matchedPatchOperation, $subject);
69 3
        $this->dispatchEvents($event, $matchedPatchOperation->getOpName(), PatchManagerEvents::PATCH_MANAGER_PRE);
70
71 3
        $matchedPatchOperation->process($subject);
72 2
        $this->dispatchEvents($event, $matchedPatchOperation->getOpName(), PatchManagerEvents::PATCH_MANAGER_POST);
73 2
    }
74
75
    /**
76
     * dispatch events if the eventDispatcher is present
77
     *
78
     * @param PatchManagerEvent $event
79
     * @param string $opName
80
     * @param string $type
81
     */
82 3
    protected function dispatchEvents(PatchManagerEvent $event, string $opName, string $type): void
83
    {
84 3
        if (!isset($this->eventDispatcherInterface)) {
85
            return;
86
        }
87 3
        $this->eventDispatcherInterface->dispatch($event, $type);
88 3
        $this->eventDispatcherInterface->dispatch(
89 3
            $event,
90 3
            sprintf('%s.%s', $type, $opName)
91
        );
92 3
    }
93
94
    /**
95
     * @param array|Patchable|\Traversable $subject a Patchable instance or a collection of instances
96
     * @throws Exception\InvalidJsonRequestContent
97
     * @throws Exception\MissingOperationNameRequest
98
     * @throws Exception\MissingOperationRequest
99
     * @throws HandlerNotFoundException
100
     * @return Sequence
101
     */
102 5
    private function getMatchedOperations($subject): Sequence
103
    {
104 5
        $matchedOperations = $this->operationMatcher->getMatchedOperations($subject);
105 5
        if ($this->strictMode && $matchedOperations->isEmpty()) {
106 2
            throw new HandlerNotFoundException($this->operationMatcher->getUnmatchedOperations($subject));
107
        }
108
109 3
        return $matchedOperations;
110
    }
111
112
    /**
113
     * @param array|Patchable|\Traversable $subject a Patchable instance or a collection of instances
114
     * @param Sequence $matchedOperations
115
     * @throws Exception\MissingOperationNameRequest
116
     * @throws Exception\MissingOperationRequest
117
     */
118 3
    private function handleSubject($subject, Sequence $matchedOperations): void
119
    {
120 3
        if (is_array($subject) || $subject instanceof \Traversable) {
121 2
            $this->handleMany($subject);
122
123 2
            return;
124
        }
125
126 1
        foreach ($matchedOperations as $matchedPatchOperation) {
127 1
            $this->doHandle($matchedPatchOperation, $subject);
128
        }
129
    }
130
131
    /**
132
     * @param array|\Traversable $subjects
133
     * @throws Exception\InvalidJsonRequestContent
134
     * @throws Exception\MissingOperationNameRequest
135
     * @throws Exception\MissingOperationRequest
136
     */
137 2
    private function handleMany($subjects): void
138
    {
139 2
        foreach ($subjects as $subject) {
140 2
            foreach ($this->operationMatcher->getMatchedOperations($subject) as $matchedPatchOperation) {
141 2
                $this->doHandle($matchedPatchOperation, $subject);
142
            }
143
        }
144 2
    }
145
}
146