Completed
Pull Request — master (#37)
by San
10:18
created

PommProfilerController::explain()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 56
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 56
rs 8.7592
cc 6
eloc 36
nc 7
nop 4

How to fix   Long Method   

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
 * This file is part of Pomm's SymfonyBidge package.
4
 *
5
 * (c) 2014 Grégoire HUBERT <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace PommProject\SymfonyBridge\Controller;
11
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15
use Symfony\Component\HttpKernel\Profiler\Profiler;
16
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17
18
use PommProject\Foundation\Pomm;
19
20
/**
21
 * Controllers for the Pomm profiler extension.
22
 *
23
 * @package PommSymfonyBridge
24
 * @copyright 2014 Grégoire HUBERT
25
 * @author Grégoire HUBERT
26
 * @license X11 {@link http://opensource.org/licenses/mit-license.php}
27
 */
28
class PommProfilerController
29
{
30
    private $generator;
31
    private $profiler;
32
    private $twig;
33
    private $pomm;
34
35
    public function __construct(
36
        UrlGeneratorInterface $generator,
37
        Profiler $profiler,
38
        \Twig_Environment $twig,
39
        Pomm $pomm
40
    ) {
41
        $this->generator = $generator;
42
        $this->profiler  = $profiler;
43
        $this->twig      = $twig;
44
        $this->pomm      = $pomm;
45
    }
46
47
    /**
48
     * Controller to explain a SQL query.
49
     *
50
     * @param $request
51
     * @param string $token
52
     * @param int $index_query
53
     *
54
     * @return Response
55
     */
56
    public function explainAction(Request $request, $token, $index_query)
57
    {
58
        return $this->explain($request, $token, $index_query, 'raw');
59
    }
60
61
    /**
62
     * Controller to explain a SQL query as graph.
63
     *
64
     * @param $request
65
     * @param string $token
66
     * @param int $index_query
67
     *
68
     * @return Response
69
     */
70
    public function graphAction(Request $request, $token, $index_query)
71
    {
72
        return $this->explain($request, $token, $index_query, 'json');
73
    }
74
75
    public function explain(Request $request, $token, $index_query, $format)
76
    {
77
        $panel = 'pomm';
78
        $page  = 'home';
79
80
        if (!($profile = $this->profiler->loadProfile($token))) {
81
            return new Response(
82
                $this->twig->render(
83
                    '@WebProfiler/Profiler/info.html.twig',
84
                    array('about' => 'no_token', 'token' => $token)
85
                ),
86
                200,
87
                array('Content-Type' => 'text/html')
88
            );
89
        }
90
91
        $this->profiler->disable();
92
93
        if (!$profile->hasCollector($panel)) {
94
            throw new NotFoundHttpException(sprintf('Panel "%s" is not available for token "%s".', $panel, $token));
95
        }
96
97
        if (!array_key_exists($index_query, $profile->getCollector($panel)->getQueries())) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\HttpKe...\DataCollectorInterface as the method getQueries() does only exist in the following implementations of said interface: PommProject\SymfonyBridge\DatabaseDataCollector.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
98
            throw new \InvalidArgumentException(sprintf("No such query index '%s'.", $index_query));
99
        }
100
101
        $query_data = $profile->getCollector($panel)->getQueries()[$index_query];
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\HttpKe...\DataCollectorInterface as the method getQueries() does only exist in the following implementations of said interface: PommProject\SymfonyBridge\DatabaseDataCollector.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
102
103
        $explain = 'explain';
104
105
        if ($format === 'json') {
106
            $explain .= ' (COSTS, VERBOSE, FORMAT JSON)';
107
        }
108
109
        $explain = $this->pomm[$query_data['session_stamp']]
110
            ->getClientUsingPooler('query_manager', null)
111
            ->query(sprintf("%s %s", $explain, $query_data['sql']), $query_data['parameters']);
112
113
        if ($format === 'json') {
114
            $template = '@Pomm/Profiler/graph.html.twig';
115
        }
116
        else {
117
            $template = '@Pomm/Profiler/explain.html.twig';
118
        }
119
120
        return new Response($this->twig->render($template, array(
121
            'token' => $token,
122
            'profile' => $profile,
123
            'collector' => $profile->getCollector($panel),
124
            'panel' => $panel,
125
            'page' => $page,
126
            'request' => $request,
127
            'query_index' => $index_query,
128
            'explain' => $explain,
129
        )), 200, array('Content-Type' => 'text/html'));
130
    }
131
}
132