testSandboxGloballySet()   F
last analyzed

Complexity

Conditions 9
Paths 4374

Size

Total Lines 90
Code Lines 64

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 90
rs 3.4117
cc 9
eloc 64
nc 4374
nop 0

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
/*
4
 * This file is part of Twig.
5
 *
6
 * (c) Fabien Potencier
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
class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase
13
{
14
    protected static $params, $templates;
15
16
    public function setUp()
17
    {
18
        self::$params = array(
19
            'name' => 'Fabien',
20
            'obj'  => new FooObject(),
21
            'arr'  => array('obj' => new FooObject()),
22
        );
23
24
        self::$templates = array(
25
            '1_basic1' => '{{ obj.foo }}',
26
            '1_basic2' => '{{ name|upper }}',
27
            '1_basic3' => '{% if name %}foo{% endif %}',
28
            '1_basic4' => '{{ obj.bar }}',
29
            '1_basic5' => '{{ obj }}',
30
            '1_basic6' => '{{ arr.obj }}',
31
            '1_basic7' => '{{ cycle(["foo","bar"], 1) }}',
32
            '1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}',
33
            '1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}',
34
            '1_basic'  => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
35
            '1_layout' => '{% block content %}{% endblock %}',
36
            '1_child'  => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}",
37
        );
38
    }
39
40
    /**
41
     * @expectedException        Twig_Sandbox_SecurityError
42
     * @expectedExceptionMessage Filter "json_encode" is not allowed in "1_child" at line 3.
43
     */
44
    public function testSandboxWithInheritance()
45
    {
46
        $twig = $this->getEnvironment(true, array(), self::$templates, array('block'));
47
        $twig->loadTemplate('1_child')->render(array());
48
    }
49
50
    public function testSandboxGloballySet()
51
    {
52
        $twig = $this->getEnvironment(false, array(), self::$templates);
53
        $this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally');
54
55
        $twig = $this->getEnvironment(true, array(), self::$templates);
56
        try {
57
            $twig->loadTemplate('1_basic1')->render(self::$params);
58
            $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called');
59
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
60
        }
61
62
        $twig = $this->getEnvironment(true, array(), self::$templates);
63
        try {
64
            $twig->loadTemplate('1_basic2')->render(self::$params);
65
            $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called');
66
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
67
        }
68
69
        $twig = $this->getEnvironment(true, array(), self::$templates);
70
        try {
71
            $twig->loadTemplate('1_basic3')->render(self::$params);
72
            $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template');
73
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
74
        }
75
76
        $twig = $this->getEnvironment(true, array(), self::$templates);
77
        try {
78
            $twig->loadTemplate('1_basic4')->render(self::$params);
79
            $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template');
80
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
81
        }
82
83
        $twig = $this->getEnvironment(true, array(), self::$templates);
84
        try {
85
            $twig->loadTemplate('1_basic5')->render(self::$params);
86
            $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
87
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
88
        }
89
90
        $twig = $this->getEnvironment(true, array(), self::$templates);
91
        try {
92
            $twig->loadTemplate('1_basic6')->render(self::$params);
93
            $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template');
94
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
95
        }
96
97
        $twig = $this->getEnvironment(true, array(), self::$templates);
98
        try {
99
            $twig->loadTemplate('1_basic7')->render(self::$params);
100
            $this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template');
101
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
102
        }
103
104
        $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => 'foo'));
105
        FooObject::reset();
106
        $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods');
107
        $this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once');
108
109
        $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => '__toString'));
110
        FooObject::reset();
111
        $this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allow some methods');
112
        $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
113
114
        $twig = $this->getEnvironment(false, array(), self::$templates);
115
        FooObject::reset();
116
        $this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allows __toString when sandbox disabled');
117
        $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once');
118
119
        $twig = $this->getEnvironment(true, array(), self::$templates, array(), array('upper'));
120
        $this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters');
121
122
        $twig = $this->getEnvironment(true, array(), self::$templates, array('if'));
123
        $this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags');
124
125
        $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array('FooObject' => 'bar'));
126
        $this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties');
127
128
        $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array(), array('cycle'));
129
        $this->assertEquals('bar', $twig->loadTemplate('1_basic7')->render(self::$params), 'Sandbox allow some functions');
130
131
        foreach (array('getfoobar', 'getFoobar', 'getFooBar') as $name) {
132
            $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => $name));
133
            FooObject::reset();
134
            $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic8')->render(self::$params), 'Sandbox allow methods in a case-insensitive way');
135
            $this->assertEquals(2, FooObject::$called['getFooBar'], 'Sandbox only calls method once');
136
137
            $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic9')->render(self::$params), 'Sandbox allow methods via shortcut names (ie. without get/set)');
138
        }
139
    }
140
141
    public function testSandboxLocallySetForAnInclude()
142
    {
143
        self::$templates = array(
144
            '2_basic'    => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}',
145
            '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
146
        );
147
148
        $twig = $this->getEnvironment(false, array(), self::$templates);
149
        $this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include');
150
151
        self::$templates = array(
152
            '3_basic'    => '{{ obj.foo }}{% sandbox %}{% include "3_included" %}{% endsandbox %}{{ obj.foo }}',
153
            '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}',
154
        );
155
156
        $twig = $this->getEnvironment(true, array(), self::$templates);
157
        try {
158
            $twig->loadTemplate('3_basic')->render(self::$params);
159
            $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed');
160
        } catch (Twig_Sandbox_SecurityError $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
161
        }
162
    }
163
164
    public function testMacrosInASandbox()
165
    {
166
        $twig = $this->getEnvironment(true, array('autoescape' => true), array('index' => <<<EOF
167
{%- import _self as macros %}
168
169
{%- macro test(text) %}<p>{{ text }}</p>{% endmacro %}
170
171
{{- macros.test('username') }}
172
EOF
173
        ), array('macro', 'import'), array('escape'));
174
175
        $this->assertEquals('<p>username</p>', $twig->loadTemplate('index')->render(array()));
176
    }
177
178
    protected function getEnvironment($sandboxed, $options, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array(), $functions = array())
179
    {
180
        $loader = new Twig_Loader_Array($templates);
181
        $twig = new Twig_Environment($loader, array_merge(array('debug' => true, 'cache' => false, 'autoescape' => false), $options));
182
        $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
183
        $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed));
184
185
        return $twig;
186
    }
187
}
188
189
class FooObject
190
{
191
    public static $called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0);
192
193
    public $bar = 'bar';
194
195
    public static function reset()
196
    {
197
        self::$called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0);
198
    }
199
200
    public function __toString()
201
    {
202
        ++self::$called['__toString'];
203
204
        return 'foo';
205
    }
206
207
    public function foo()
208
    {
209
        ++self::$called['foo'];
210
211
        return 'foo';
212
    }
213
214
    public function getFooBar()
215
    {
216
        ++self::$called['getFooBar'];
217
218
        return 'foobar';
219
    }
220
}
221