Completed
Push — master ( a16e2f...7f604e )
by Mikhail
06:36
created

TimedTwigDecorator::getEnvironment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Mikhail Dolgov <[email protected]>
4
 * @date   09.03.2016 15:28
5
 */
6
7
namespace SilexPinbaProvider\Twig;
8
9
10
use Intaro\PinbaBundle\Stopwatch\Stopwatch;
11
12
class TimedTwigDecorator extends \Twig_Environment{
13
    /**
14
     * @var \Twig_Environment
15
     */
16
    private $environment;
17
    /**
18
     * @var Stopwatch
19
     */
20
    private $stopwatch;
21
22
    /**
23
     * @var string
24
     */
25
    private $serverName;
26
27
    /**
28
     * @param \Twig_Environment $environment
29
     * @param Stopwatch         $stopwatch
30
     * @param string            $serverName
31
     */
32
    public function __construct(\Twig_Environment $environment, Stopwatch $stopwatch, $serverName = 'localhost')
33
    {
34
        $this->environment = $environment;
35
        $this->stopwatch   = $stopwatch;
36
        $this->serverName  = $serverName;
37
    }
38
39
    /**
40
     * Renders a template.
41
     *
42
     * @param string $name    The template name
43
     * @param array  $context An array of parameters to pass to the template
44
     *
45
     * @return string The rendered template
46
     *
47
     * @throws \Twig_Error_Loader  When the template cannot be found
48
     * @throws \Twig_Error_Syntax  When an error occurred during compilation
49
     * @throws \Twig_Error_Runtime When an error occurred during rendering
50
     */
51
    public function render($name, array $context = array())
52
    {
53
        $e = $this->stopwatch->start(array(
54
            'server'        => $this->serverName,
55
            'group'         => 'twig::render',
56
            'twig_template' => (string)$name,
57
        ));
58
59
        $ret = $this->environment->render($name, $context);
60
61
        $e->stop();
62
63
        return $ret;
64
65
    }
66
67
    /**
68
     * @return \Twig_Environment
69
     */
70
    public function getEnvironment()
71
    {
72
        return (method_exists($this->environment, 'getEnvironment'))? $this->environment->getEnvironment():$this->environment;
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Twig_Environment as the method getEnvironment() does only exist in the following sub-classes of Twig_Environment: SilexPinbaProvider\Twig\TimedTwigDecorator. 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...
73
    }
74
75
    /**
76
     * @inheritdoc
77
     */
78
    public function getLoader()
79
    {
80
        return $this->environment->getLoader();
81
    }
82
83
84
    /**
85
     * is triggered when invoking inaccessible methods in an object context.
86
     *
87
     * @param $name      string
88
     * @param $arguments array
89
     * @return mixed
90
     * @link http://php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods
91
     */
92
    function __call($name, $arguments)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
93
    {
94
        return call_user_func_array(array($this->environment,$name),$arguments);
95
    }
96
97
98
}