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

Fixture   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 326
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 32
c 5
b 0
f 1
lcom 1
cbo 9
dl 0
loc 326
rs 9.6

23 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A givenCommands() 0 4 1
A givenEvents() 0 4 1
A getRepository() 0 4 1
A expectEvents() 0 5 1
A expectNoEvents() 0 4 1
A when() 0 8 3
A expectReturnValue() 0 6 1
A expectException() 0 6 1
A registerAnnotatedCommandHandler() 0 5 1
A registerCommandClosure() 0 5 1
A getAggregateId() 0 4 1
A onSuccess() 0 4 1
A onFailure() 0 4 1
A catchEvent() 0 5 1
A setAggregateId() 0 4 1
A getCommandBus() 0 4 1
A getEventBus() 0 4 1
A getAggregateClass() 0 4 1
A evaluate() 0 8 1
A checkReturnValue() 0 6 2
A checkThrownException() 0 13 3
A checkRaisedEvents() 0 17 4
1
<?php
2
/*
3
 * Copyright (c) 2012-2014 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\util\test;
25
26
use BadMethodCallException;
27
use Closure;
28
use Exception;
29
use PHPUnit_Framework_TestCase;
30
use precore\lang\ObjectClass;
31
use predaddy\commandhandling\AbstractCommand;
32
use predaddy\commandhandling\Command;
33
use predaddy\commandhandling\CommandBus;
34
use predaddy\commandhandling\DirectCommandBus;
35
use predaddy\domain\AbstractDomainEvent;
36
use predaddy\domain\AggregateId;
37
use predaddy\domain\GenericAggregateId;
38
use predaddy\domain\DomainEvent;
39
use predaddy\domain\EventPublisher;
40
use predaddy\domain\Repository;
41
use predaddy\eventhandling\EventBus;
42
use predaddy\messagehandling\annotation\Subscribe;
43
use predaddy\messagehandling\MessageCallback;
44
45
/**
46
 * Class Fixture
47
 *
48
 * @package predaddy\util\test
49
 * @author Janos Szurovecz <[email protected]>
50
 */
51
abstract class Fixture implements MessageCallback
0 ignored issues
show
Complexity introduced by
The class Fixture has a coupling between objects value of 28. Consider to reduce the number of dependencies under 13.
Loading history...
52
{
53
    const EVENT_NUMBER_MISMATCH = 'Raised and expected number of events mismatches';
54
55
    /**
56
     * @var DomainEvent[]
57
     */
58
    private $then = [];
59
60
    /**
61
     * @var DomainEvent[]
62
     */
63
    private $raisedEvents = [];
64
65
    /**
66
     * @var Command
67
     */
68
    private $command;
69
70
    /**
71
     * @var CommandBus
72
     */
73
    private $commandBus;
74
75
    /**
76
     * @var EventBus
77
     */
78
    private $eventBus;
79
80
    /**
81
     * @var string
82
     */
83
    private $aggregateClass;
84
85
    /**
86
     * @var mixed
87
     */
88
    private $expectedReturnValue;
89
90
    /**
91
     * @var mixed
92
     */
93
    private $commandResult;
94
95
    /**
96
     * @var bool
97
     */
98
    private $checkReturnValue = false;
99
100
    /**
101
     * @var null|string
102
     */
103
    private $expectedExceptionClass = null;
104
105
    /**
106
     * @var null|string
107
     */
108
    private $expectedExceptionMessage = null;
109
110
    /**
111
     * @var null|Exception
112
     */
113
    private $raisedException;
114
115
    /**
116
     * @var null|Repository
117
     */
118
    private $repository;
119
120
    /**
121
     * @var GenericAggregateId|null
122
     */
123
    private $aggregateId;
124
125
    public function __construct($aggregateClass, Repository $repository = null)
126
    {
127
        $this->aggregateClass = $aggregateClass;
128
        $this->commandBus = $repository === null
129
            ? new CommandBus()
130
            : DirectCommandBus::builder($repository)->build();
131
        $this->eventBus = new EventBus();
132
        EventPublisher::instance()->setEventBus($this->eventBus);
133
        $this->repository = $repository;
134
        //$this->aggregateId = new GenericAggregateId(UUID::randomUUID()->toString(), $this->getAggregateClass());
135
    }
136
137
    /**
138
     * These commands will be initialize the AR. The raised domain events will be ignored.
139
     * It works only with non-ES aggregates.
140
     *
141
     * @param Command $commands one ore more commands
142
     * @throws BadMethodCallException
143
     * @return CommandSourcedFixture
144
     */
145
    public function givenCommands(Command $commands)
0 ignored issues
show
Unused Code introduced by
The parameter $commands is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
146
    {
147
        throw new BadMethodCallException("This method is not supported");
148
    }
149
150
    /**
151
     * These events will be initialize the AR. It works only with ES aggregates.
152
     *
153
     * @param DomainEvent $events
154
     * @throws BadMethodCallException
155
     * @return EventSourcedFixture
156
     */
157
    public function givenEvents(DomainEvent $events)
0 ignored issues
show
Unused Code introduced by
The parameter $events is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
158
    {
159
        throw new BadMethodCallException("This method is not supported");
160
    }
161
162
    /**
163
     * Returns the registered or dynamically generated repository.
164
     *
165
     * @return null|Repository
166
     */
167
    public function getRepository()
168
    {
169
        return $this->repository;
170
    }
171
172
    /**
173
     * These events are expected to be raised. Starts the evaluation.
174
     *
175
     * @param DomainEvent $events one or more events
176
     */
177
    public function expectEvents(DomainEvent $events)
0 ignored issues
show
Unused Code introduced by
The parameter $events is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
178
    {
179
        $this->then = func_get_args();
180
        $this->evaluate();
181
    }
182
183
    /**
184
     * No expected events. Starts the evaluation.
185
     */
186
    public function expectNoEvents()
187
    {
188
        $this->evaluate();
189
    }
190
191
    /**
192
     * The AR's behavior will be tested when this command is applied.
193
     *
194
     * @param Command $command
195
     * @return $this
196
     */
197
    public function when(Command $command)
198
    {
199
        if ($this->aggregateId !== null && $command instanceof AbstractCommand) {
200
            CommandPopulator::populate($this->getAggregateId()->value(), $command);
201
        }
202
        $this->command = $command;
203
        return $this;
204
    }
205
206
    /**
207
     * The given value must be returned by the command handler.
208
     *
209
     * @param mixed $value
210
     * @return $this
211
     */
212
    public function expectReturnValue($value)
213
    {
214
        $this->checkReturnValue = true;
215
        $this->expectedReturnValue = $value;
216
        return $this;
217
    }
218
219
    /**
220
     * The given type of exception must be be thrown when the command is applied. Starts the evaluation.
221
     *
222
     * @param string $class the type of the exception
223
     * @param null|string $message the exception message
224
     */
225
    public function expectException($class, $message = null)
226
    {
227
        $this->expectedExceptionClass = $class;
228
        $this->expectedExceptionMessage = $message;
229
        $this->evaluate();
230
    }
231
232
    /**
233
     * The command handler which can handle the tested command.
234
     * If the command implements {@link DirectCommand} and is processed directly
235
     * by the AR, does not need to be used.
236
     *
237
     * @param $handler
238
     * @return $this
239
     */
240
    public function registerAnnotatedCommandHandler($handler)
241
    {
242
        $this->commandBus->register($handler);
243
        return $this;
244
    }
245
246
    /**
247
     * The same as {@link registerAnnotatedCommandHandler()} but with closure.
248
     *
249
     * @param Closure $closure
250
     * @return $this
251
     */
252
    public function registerCommandClosure(Closure $closure)
253
    {
254
        $this->commandBus->registerClosure($closure);
255
        return $this;
256
    }
257
258
    /**
259
     * The aggregate ID generated by the AR, or defined somehow else.
260
     * Can be obtained in order to do further tests if required.
261
     *
262
     * @return AggregateId
263
     */
264
    public function getAggregateId()
265
    {
266
        return $this->aggregateId;
267
    }
268
269
    /**
270
     * @param mixed $result
271
     * @return void
272
     */
273
    public function onSuccess($result)
274
    {
275
        $this->commandResult = $result;
276
    }
277
278
    /**
279
     * @param Exception $exception
280
     * @return void
281
     */
282
    public function onFailure(Exception $exception)
283
    {
284
        $this->raisedException = $exception;
285
    }
286
287
    /**
288
     * @Subscribe
289
     * @param DomainEvent $event
290
     */
291
    public function catchEvent(DomainEvent $event)
292
    {
293
        $this->raisedEvents[] = $event;
294
        $this->setAggregateId($event->aggregateId());
295
    }
296
297
    /**
298
     * @param AggregateId $aggregateId
299
     */
300
    protected function setAggregateId(AggregateId $aggregateId)
301
    {
302
        $this->aggregateId = $aggregateId;
0 ignored issues
show
Documentation Bug introduced by
It seems like $aggregateId of type object<predaddy\domain\AggregateId> is incompatible with the declared type object<predaddy\domain\GenericAggregateId>|null of property $aggregateId.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
303
    }
304
305
    /**
306
     * @return CommandBus
307
     */
308
    protected function getCommandBus()
309
    {
310
        return $this->commandBus;
311
    }
312
313
    /**
314
     * @return EventBus
315
     */
316
    protected function getEventBus()
317
    {
318
        return $this->eventBus;
319
    }
320
321
    /**
322
     * @return ObjectClass
323
     */
324
    protected function getAggregateClass()
325
    {
326
        return $this->aggregateClass;
327
    }
328
329
    private function evaluate()
330
    {
331
        $this->eventBus->register($this);
332
        $this->commandBus->post($this->command, $this);
333
        $this->checkReturnValue();
334
        $this->checkThrownException();
335
        $this->checkRaisedEvents();
336
    }
337
338
    private function checkReturnValue()
339
    {
340
        if ($this->checkReturnValue) {
341
            PHPUnit_Framework_TestCase::assertEquals($this->expectedReturnValue, $this->commandResult);
342
        }
343
    }
344
345
    private function checkThrownException()
346
    {
347
        if ($this->raisedException !== null) {
348
            if ($this->expectedExceptionClass === null) {
349
                throw $this->raisedException;
350
            }
351
            PHPUnit_Framework_TestCase::assertInstanceOf($this->expectedExceptionClass, $this->raisedException);
352
            PHPUnit_Framework_TestCase::assertEquals(
353
                $this->expectedExceptionMessage,
354
                $this->raisedException->getMessage()
355
            );
356
        }
357
    }
358
359
    private function checkRaisedEvents()
360
    {
361
        $thenCount = count($this->then);
362
        $raisedCount = count($this->raisedEvents);
363
        PHPUnit_Framework_TestCase::assertEquals($thenCount, $raisedCount, self::EVENT_NUMBER_MISMATCH);
364
        for ($i = 0; $i < $thenCount; $i++) {
365
            $expectedEvent = $this->then[$i];
366
            $raisedEvent = $this->raisedEvents[$i];
367
            if ($raisedEvent instanceof AbstractDomainEvent) {
368
                $raisedEvent = DomainEventMetaReset::reset($raisedEvent);
369
            }
370
            if ($expectedEvent instanceof AbstractDomainEvent) {
371
                $expectedEvent = DomainEventMetaReset::reset($expectedEvent);
372
            }
373
            PHPUnit_Framework_TestCase::assertEquals($expectedEvent, $raisedEvent);
374
        }
375
    }
376
}
377
378
class DomainEventMetaReset extends AbstractDomainEvent
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
379
{
380
    public static function reset(AbstractDomainEvent $event)
381
    {
382
        $event->id = '';
383
        $event->aggregateClass = '';
384
        $event->aggregateValue = '';
385
        $event->stateHash = null;
386
        $event->created = null;
387
        return $event;
388
    }
389
}
390
391
class CommandPopulator extends AbstractCommand
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
392
{
393
    public static function populate($aggregateId, AbstractCommand $command)
394
    {
395
        $command->aggregateId = $aggregateId;
396
    }
397
}
398