Completed
Push — master ( 164641...a3c0ef )
by Christian
14:31 queued 04:31
created

TwigExceptionController   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 77
Duplicated Lines 15.58 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 85%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 4
dl 12
loc 77
ccs 17
cts 20
cp 0.85
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A createView() 0 7 1
C findTemplate() 12 34 14
A templateExists() 0 16 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the FOSRestBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\RestBundle\Controller;
13
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\Templating\EngineInterface;
16
use Twig\Environment;
17
use Twig\Error\LoaderError;
18
use Twig\Loader\ExistsLoaderInterface;
19
20
/**
21
 * Custom ExceptionController that uses the view layer and supports HTTP response status code mapping.
22
 * It additionally is able to prepare the template parameters for the core EngineInterface.
23
 */
24
class TwigExceptionController extends TemplatingExceptionController
25
{
26 6
    /**
27
     * {@inheritdoc}
28 6
     */
29 6
    protected function createView(\Exception $exception, $code, array $templateData, Request $request, $showException)
30
    {
31 6
        $view = parent::createView($exception, $code, $templateData, $request, $showException);
32
        $view->setTemplate($this->findTemplate($request, $code, $showException));
33
34
        return $view;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     *
40 6
     * This code is inspired by TwigBundle and should be synchronized on a regular basis
41
     * see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
42 6
     */
43
    protected function findTemplate(Request $request, $statusCode, $showException)
44 6
    {
45 6
        $format = $request->getRequestFormat();
46 1
47 1
        $name = $showException ? 'exception' : 'error';
48
        if ($showException && 'html' == $format) {
49
            $name = 'exception_full';
50 6
        }
51 4
52 4
        // For error pages, try to find a template for the specific HTTP status code and format
53
        if (!$showException) {
54
            $template = sprintf('@Twig/Exception/%s%s.%s.twig', $name, $statusCode, $format);
55 4 View Code Duplication
            if (
56
                ($this->templating instanceof EngineInterface && $this->templating->exists($template)) ||
57
                ($this->templating instanceof Environment && $this->templateExists($template))
58 6
            ) {
59 6
                return $template;
60 6
            }
61
        }
62
63
        // try to find a template for the given format
64
        $template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format);
65 View Code Duplication
        if (
66
            ($this->templating instanceof EngineInterface && $this->templating->exists($template)) ||
67
            ($this->templating instanceof Environment && $this->templateExists($template))
68
        ) {
69
            return $template;
70
        }
71
72
        // default to a generic HTML exception
73
        $request->setRequestFormat('html');
74
75
        return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
76
    }
77
78
    /**
79
     * See if a template exists using the modern Twig mechanism.
80
     *
81
     * This code is based on TwigBundle and should be removed when the minimum required
82
     * version of Twig is >= 3.0. See src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
83
     */
84
    private function templateExists(string $template): bool
85
    {
86
        $loader = $this->templating->getLoader();
0 ignored issues
show
Bug introduced by
The method getLoader does only exist in Twig\Environment, but not in Symfony\Component\Templating\EngineInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
87
        if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) {
88
            return $loader->exists($template);
89
        }
90
91
        try {
92
            $loader->getSourceContext($template)->getCode();
93
94
            return true;
95
        } catch (LoaderError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
96
        }
97
98
        return false;
99
    }
100
}
101