GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — bugfix/5.4build ( 31a631 )
by Szurovecz
08:38
created

SimpleMessageBus::dispatch()   C

Complexity

Conditions 10
Paths 4

Size

Total Lines 48
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
c 5
b 1
f 1
dl 0
loc 48
rs 5.3454
cc 10
eloc 35
nc 4
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * Copyright (c) 2013 Janos Szurovecz
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6
 * this software and associated documentation files (the "Software"), to deal in
7
 * the Software without restriction, including without limitation the rights to
8
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
 * of the Software, and to permit persons to whom the Software is furnished to do
10
 * so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in all
13
 * copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 */
23
24
namespace predaddy\messagehandling;
25
26
use ArrayObject;
27
use Closure;
28
use Exception;
29
use precore\util\Collections;
30
use precore\util\Objects;
31
use SplHeap;
32
use SplObjectStorage;
33
34
/**
35
 * {@link MessageBus} which find handler methods in the registered message handlers.
36
 *
37
 * Handler method finding mechanism can be modified with
38
 * {@link MessageHandlerDescriptorFactory} and {@link FunctionDescriptorFactory} instances
39
 * through the builder object.
40
 *
41
 * It manages {@link PropagationStoppable} messages properly.
42
 *
43
 * @author Janos Szurovecz <[email protected]>
44
 */
45
class SimpleMessageBus extends InterceptableMessageBus implements HandlerFactoryRegisterableMessageBus
0 ignored issues
show
Complexity introduced by
The class SimpleMessageBus has a coupling between objects value of 19. Consider to reduce the number of dependencies under 13.
Loading history...
46
{
47
    /**
48
     * @var string
49
     */
50
    private $identifier;
51
52
    /**
53
     * @var MessageHandlerDescriptorFactory
54
     */
55
    private $handlerDescriptorFactory;
56
57
    /**
58
     * @var FunctionDescriptorFactory
59
     */
60
    private $closureDescriptorFactory;
61
62
    /**
63
     * @var SplObjectStorage
64
     */
65
    private $factories;
66
67
    /**
68
     * @var SubscriberExceptionHandler
69
     */
70
    private $exceptionHandler;
71
72
    /**
73
     * @var SplObjectStorage
74
     */
75
    private $functionDescriptors;
76
77
    /**
78
     * @param SimpleMessageBusBuilder $builder
79
     */
80
    public function __construct(SimpleMessageBusBuilder $builder = null)
81
    {
82
        if ($builder === null) {
83
            $builder = self::builder();
84
        }
85
        parent::__construct($builder->getInterceptors());
86
        $this->identifier = $builder->getIdentifier();
87
        $this->exceptionHandler = $builder->getExceptionHandler();
88
        $this->handlerDescriptorFactory = $builder->getHandlerDescriptorFactory();
89
        $this->closureDescriptorFactory = $builder->getHandlerDescriptorFactory()->getFunctionDescriptorFactory();
90
        $this->functionDescriptors = new SplObjectStorage();
91
        $this->factories = new SplObjectStorage();
92
    }
93
94
    /**
95
     * @return SimpleMessageBusBuilder
96
     */
97
    public static function builder()
98
    {
99
        return new SimpleMessageBusBuilder();
100
    }
101
102
    public function registerHandlerFactory(Closure $factory)
103
    {
104
        $descriptor = $this->closureDescriptorFactory->create(new ClosureWrapper($factory), self::DEFAULT_PRIORITY);
105
        $this->factories->attach($factory, $descriptor);
106
    }
107
108
    public function unregisterHandlerFactory(Closure $factory)
109
    {
110
        $this->factories->detach($factory);
111
    }
112
113
    /**
114
     * @param object $handler
115
     */
116
    public function register($handler)
117
    {
118
        $descriptor = $this->handlerDescriptorFactory->create($handler);
119
        foreach ($descriptor->getFunctionDescriptors() as $functionDescriptor) {
120
            $this->functionDescriptors->attach($functionDescriptor);
121
        }
122
    }
123
124
    /**
125
     * @param object $handler
126
     */
127
    public function unregister($handler)
128
    {
129
        $descriptor = $this->handlerDescriptorFactory->create($handler);
130
        foreach ($descriptor->getFunctionDescriptors() as $functionDescriptor) {
131
            $this->functionDescriptors->detach($functionDescriptor);
132
        }
133
    }
134
135
    /**
136
     * @param Closure $closure
137
     * @param int $priority
138
     */
139
    public function registerClosure(Closure $closure, $priority = self::DEFAULT_PRIORITY)
140
    {
141
        $descriptor = $this->closureDescriptorFactory->create(new ClosureWrapper($closure), $priority);
142
        $this->functionDescriptors->attach($descriptor);
143
    }
144
145
    /**
146
     * @param Closure $closure
147
     * @param int $priority
148
     */
149
    public function unregisterClosure(Closure $closure, $priority = self::DEFAULT_PRIORITY)
150
    {
151
        $descriptor = $this->closureDescriptorFactory->create(new ClosureWrapper($closure), $priority);
152
        $this->functionDescriptors->detach($descriptor);
153
        foreach ($this->functionDescriptors as $key => $value) {
154
            if ($value->equals($descriptor)) {
155
                $this->functionDescriptors->offsetUnset($value);
156
                break;
157
            }
158
        }
159
    }
160
161
    /**
162
     * Dispatches $message to all handlers.
163
     *
164
     * @param $message
165
     * @param MessageCallback $callback
166
     * @return void
167
     */
168
    protected function dispatch($message, MessageCallback $callback)
169
    {
170
        $handled = false;
171
        foreach ($this->callableWrappersFor($message) as $callable) {
172
            $handled = true;
173
            if ($message instanceof PropagationStoppable && $message->isPropagationStopped()) {
174
                break;
175
            }
176
            try {
177
                $result = $callable->invoke($message);
178
                self::getLogger()->debug(
179
                    "The following message has been dispatched to handler '{}' through message bus '{}': {}",
180
                    [$callable, $this, $message]
181
                );
182
                if ($result !== null) {
183
                    $callback->onSuccess($result);
184
                }
185
            } catch (Exception $exp) {
186
                self::getLogger()->warn(
187
                    "An error occurred in the following message handler through message bus '{}': {}, message is {}!",
188
                    [$this, $callable, $message],
189
                    $exp
190
                );
191
                $context = new SubscriberExceptionContext($this, $message, $callable);
192
                try {
193
                    $this->exceptionHandler->handleException($exp, $context);
194
                } catch (Exception $e) {
195
                    self::getLogger()->error(
196
                        "An error occurred in the exception handler with context '{}'",
197
                        [$context],
198
                        $e
199
                    );
200
                }
201
                try {
202
                    $callback->onFailure($exp);
203
                } catch (Exception $e) {
204
                    self::getLogger()->error("An error occurred in message callback on bus '{}'", [$this], $e);
205
                }
206
            }
207
        }
208
        if (!$handled && !($message instanceof DeadMessage)) {
209
            self::getLogger()->debug(
210
                "The following message as a DeadMessage is being posted to '{}' message bus: {}",
211
                [$this, $message]
212
            );
213
            $this->dispatch(new DeadMessage($message), $callback);
214
        }
215
    }
216
217
    /**
218
     * @param $message
219
     * @return ArrayObject
220
     */
221
    protected function callableWrappersFor($message)
222
    {
223
        $heap = Collections::createHeap(Collections::reverseOrder());
224
225
        self::insertAllHandlers($this->functionDescriptors, $heap, $message);
226
227
        foreach ($this->factories as $factory) {
228
            /* @var $factoryDescriptor FunctionDescriptor */
229
            $factoryDescriptor = $this->factories[$factory];
230
            if ($factoryDescriptor->isHandlerFor($message)) {
231
                $handler = call_user_func($factory, $message);
232
                $descriptor = $this->handlerDescriptorFactory->create($handler);
233
                self::insertAllHandlers($descriptor->getFunctionDescriptors(), $heap, $message);
234
            }
235
        }
236
237
        $res = new ArrayObject();
238
        foreach ($heap as $functionDescriptor) {
239
            $res->append($functionDescriptor->getCallableWrapper());
240
        }
241
242
        return $res;
243
    }
244
245
    private static function insertAllHandlers($functionDescriptors, SplHeap $heap, $message)
246
    {
247
        /* @var $functionDescriptor FunctionDescriptor */
248
        foreach ($functionDescriptors as $functionDescriptor) {
249
            if ($functionDescriptor->isHandlerFor($message)) {
250
                $heap->insert($functionDescriptor);
251
            }
252
        }
253
    }
254
255
    public function toString()
256
    {
257
        return Objects::toStringHelper($this)
258
            ->add($this->identifier)
259
            ->toString();
260
    }
261
}
262