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

TwigExceptionController::findTemplate()   C

Complexity

Conditions 14
Paths 20

Size

Total Lines 34

Duplication

Lines 12
Ratio 35.29 %

Code Coverage

Tests 11
CRAP Score 15.9289

Importance

Changes 0
Metric Value
dl 12
loc 34
ccs 11
cts 14
cp 0.7856
rs 6.2666
c 0
b 0
f 0
cc 14
nc 20
nop 3
crap 15.9289

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
/*
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