Failed Conditions
Push — master ( c04808...f5c6c8 )
by Arnold
04:54
created

Twig::initTwig()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 14
cts 14
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 6
nop 0
crap 4
1
<?php
2
3
namespace Jasny\Controller\View;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
7
/**
8
 * View using Twig
9
 */
10
trait Twig
11
{
12
    /**
13
     * Twig environment
14
     * @var \Twig_Environment
15
     */
16
    protected $twig;
17
18
19
    /**
20
     * Get server request
21
     * @return ServerRequestInterface
22
     */
23
    abstract public function getRequest();
24
25
    /**
26
     * Output result
27
     *
28
     * @param mixed  $data
29
     * @param string $format  Output format as MIME or extension
30
     */
31
    abstract public function output($data, $format = null);
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
32
33
34
    /**
35
     * Get path of the view files
36
     *
37
     * @return string
38
     */
39 1
    protected function getViewPath()
40
    {
41 1
        return getcwd();
42
    }
43
44
    /**
45
     * Assert valid variable, function and filter name
46
     * 
47
     * @param string $name
48
     * @throws \InvalidArgumentException
49
     */
50 19
    protected function assertViewVariableName($name)
51
    {
52 19 View Code Duplication
        if (!is_string($name)) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
53 3
            $type = (is_object($name) ? get_class($name) . ' ' : '') . gettype($name);
54 3
            throw new \InvalidArgumentException("Expected name to be a string, not a $type");
55
        }
56
57 16
        if (!preg_match('/^[a-z]\w*$/i', $name)) {
58 3
            throw new \InvalidArgumentException("Invalid name '$name'");
59
        }
60 13
    }
61
    
62
    /**
63
     * Add a global variable to the view.
64
     *
65
     * @param string $name   Variable name
66
     * @param mixed  $value
67
     * @return $this
68
     */
69 6
    public function setViewVariable($name, $value)
70
    {
71 6
        $this->assertViewVariableName($name);
72
73 4
        $this->getTwig()->addGlobal($name, $value);
74
75 4
        return $this;
76
    }
77
78
    /**
79
     * Expose a function to the view.
80
     *
81
     * @param string      $name      Function name
82
     * @param string|null $function
83
     * @param string      $as        'function' or 'filter'
84
     * @return $this
85
     */
86 13
    public function setViewFunction($name, $function = null, $as = 'function')
87
    {
88 13
        $this->assertViewVariableName($name);
89
        
90 9
        if ($as === 'function') {
91 3
            $function = new \Twig_SimpleFunction($name, $function ?: $name);
92 3
            $this->getTwig()->addFunction($function);
93 9
        } elseif ($as === 'filter') {
94 3
            $filter = new \Twig_SimpleFilter($name, $function ?: $name);
95 3
            $this->getTwig()->addFilter($filter);
96 3
        } else {
97 3
            $not = is_string($as) ? "'$as'" : 'a ' . gettype($as);
98 3
            throw new \InvalidArgumentException("You should create either a 'function' or 'filter', not $not");
99
        }
100
101 6
        return $this;
102
    }
103
104
    /**
105
     * Get twig environment instance
106
     *
107
     * @return \Twig_Environment
108
     */
109 1
    public function createTwigEnvironment()
110
    {
111 1
        $path = $this->getViewPath();
112 1
        $loader = new \Twig_Loader_Filesystem($path);
113
114 1
        return new \Twig_Environment($loader);
115
    }
116
117
    /**
118
     * Initialize the Twig environment
119
     */
120 4
    protected function initTwig()
121
    {
122 3
        $this->twig = $this->createTwigEnvironment();
123
124 3
        $extensions = ['DateExtension', 'PcreExtension', 'TextExtension', 'ArrayExtension'];
125 3
        foreach ($extensions as $name) {
126 4
            $class = "Jasny\Twig\\$name";
127
128 4
            if (class_exists($class)) {
129 4
                $this->twig->addExtension(new $class());
130 3
            }
131 3
        }
132
133 3
        $this->twig->addGlobal('current_url', $this->getRequest()->getUri());
134
        
135 3
        if (method_exists($this, 'flash')) {
136 1
            $this->twig->addGlobal('flash', $this->flash());
0 ignored issues
show
Bug introduced by
It seems like flash() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
137 1
        }
138 3
    }
139
140
    /**
141
     * Get Twig environment
142
     *
143
     * @return \Twig_Environment
144
     */
145 3
    public function getTwig()
146
    {
147 3
        if (!isset($this->twig)) {
148 3
            $this->initTwig();
149 3
        }
150
151 3
        return $this->twig;
152
    }
153
154
155
    /**
156
     * View rendered template
157
     *
158
     * @param string $name    Template name
159
     * @param array  $context Template context
160
     */
161 3
    public function view($name, array $context = [])
162
    {
163 3
        if (!pathinfo($name, PATHINFO_EXTENSION)) {
164 1
            $name .= '.html.twig';
165 1
        }
166
167 3
        $twig = $this->getTwig();
168 3
        $tmpl = $twig->loadTemplate($name);
169
170 3
        $this->output($tmpl->render($context), 'text/html; charset=' . $twig->getCharset());
171 3
    }
172
}
173