DebugEventDispatcher   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 72
wmc 7
lcom 1
cbo 5
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
B doDispatch() 0 30 5
A getDebugClassName() 0 10 1
1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) MASSIVE ART WebServices GmbH
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Sulu\Component\DocumentManager\EventDispatcher;
13
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
17
use Symfony\Component\EventDispatcher\Event;
18
use Symfony\Component\Stopwatch\Stopwatch;
19
20
/**
21
 * Logging and profiling event dispatcher for the document manager.
22
 */
23
class DebugEventDispatcher extends ContainerAwareEventDispatcher
24
{
25
    /**
26
     * @var Stopwatch
27
     */
28
    private $stopwatch;
29
30
    /**
31
     * @var LoggerInterface
32
     */
33
    private $logger;
34
35
    /**
36
     * @param ContainerInterface $container
37
     * @param Stopwatch $stopwatch
38
     * @param LoggerInterface $logger
39
     */
40
    public function __construct(
41
        ContainerInterface $container,
42
        Stopwatch $stopwatch,
43
        LoggerInterface $logger
44
    ) {
45
        parent::__construct($container);
46
        $this->stopwatch = $stopwatch;
47
        $this->logger = $logger;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    protected function doDispatch($listeners, $eventName, Event $event)
54
    {
55
        $eventStopwatch = $this->stopwatch->start($eventName, 'section');
56
57
        foreach ($listeners as $listener) {
58
            list($listenerInstance, $methodName) = $listener;
59
            $className = get_class($listenerInstance);
60
            $name = $this->getDebugClassName($className);
61
62
            $listenerStopwatch = $this->stopwatch->start($className . '->' . $methodName, 'document_manager_listener');
63
64
            call_user_func($listener, $event, $eventName, $this);
65
66
            $this->logger->debug(sprintf(
67
                '%-40s%-20s %s', $name, $methodName, $event->getDebugMessage()
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\EventDispatcher\Event as the method getDebugMessage() does only exist in the following sub-classes of Symfony\Component\EventDispatcher\Event: Sulu\Component\DocumentM...t\AbstractDocumentEvent, Sulu\Component\DocumentManager\Event\AbstractEvent, Sulu\Component\DocumentM...nt\AbstractMappingEvent, Sulu\Component\DocumentManager\Event\ClearEvent, Sulu\Component\DocumentM...t\ConfigureOptionsEvent, Sulu\Component\DocumentManager\Event\CopyEvent, Sulu\Component\DocumentManager\Event\CreateEvent, Sulu\Component\DocumentManager\Event\FindEvent, Sulu\Component\DocumentManager\Event\FlushEvent, Sulu\Component\DocumentManager\Event\HydrateEvent, Sulu\Component\DocumentM...Event\MetadataLoadEvent, Sulu\Component\DocumentManager\Event\MoveEvent, Sulu\Component\DocumentManager\Event\PersistEvent, Sulu\Component\DocumentM...QueryCreateBuilderEvent, Sulu\Component\DocumentM...\Event\QueryCreateEvent, Sulu\Component\DocumentM...Event\QueryExecuteEvent, Sulu\Component\DocumentManager\Event\RefreshEvent, Sulu\Component\DocumentManager\Event\RemoveEvent, Sulu\Component\DocumentManager\Event\ReorderEvent. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
68
            ));
69
70
            if ($listenerStopwatch->isStarted()) {
71
                $listenerStopwatch->stop();
72
            }
73
74
            if ($event->isPropagationStopped()) {
75
                break;
76
            }
77
        }
78
79
        if ($eventStopwatch->isStarted()) {
80
            $eventStopwatch->stop();
81
        }
82
    }
83
84
    private function getDebugClassName($className)
85
    {
86
        $parts = explode('\\', $className);
87
        $last = array_pop($parts);
88
        $parts = array_map(function ($part) {
89
            return substr($part, 0, 1);
90
        }, $parts);
91
92
        return implode('\\', $parts) . '\\' . $last;
93
    }
94
}
95