This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the SlotMachine library. |
||
5 | * |
||
6 | * (c) Adam Elsodaney <[email protected]> |
||
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 tests\SlotMachine; |
||
13 | |||
14 | use SlotMachine\Slot; |
||
15 | use SlotMachine\SlotMachine; |
||
16 | use Symfony\Component\HttpFoundation\Request; |
||
17 | use Symfony\Component\Yaml\Yaml; |
||
18 | |||
19 | class SlotMachineTest extends \PHPUnit_Framework_TestCase |
||
20 | { |
||
21 | /** @var SlotMachine|Slot[] */ |
||
22 | private $page; |
||
23 | /** @var array */ |
||
24 | private static $slotsConfig; |
||
25 | |||
26 | /** @var array */ |
||
27 | private static $slotsConfigWithOptions; |
||
28 | |||
29 | /** @var bool */ |
||
30 | private static $hasDeepParameterAccess; |
||
31 | |||
32 | public static function setUpBeforeClass() |
||
33 | { |
||
34 | $parameterBagGet = new \ReflectionMethod('Symfony\Component\HttpFoundation\ParameterBag', 'get'); |
||
35 | |||
36 | self::$slotsConfig = Yaml::parse(file_get_contents(__DIR__.'/fixtures/slots.config.yml')); |
||
0 ignored issues
–
show
|
|||
37 | self::$slotsConfigWithOptions = Yaml::parse(file_get_contents(__DIR__.'/fixtures/slots_with_options.config.yml')); |
||
0 ignored issues
–
show
It seems like
\Symfony\Component\Yaml\...h_options.config.yml')) can also be of type string or object<stdClass> . However, the property $slotsConfigWithOptions is declared as type array . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
38 | self::$hasDeepParameterAccess = $parameterBagGet->getNumberOfParameters() === 3; |
||
39 | } |
||
40 | |||
41 | public function setUp() |
||
42 | { |
||
43 | $this->page = new SlotMachine(self::$slotsConfig); |
||
44 | } |
||
45 | |||
46 | /** |
||
47 | * @covers SlotMachine\SlotMachine::count |
||
48 | */ |
||
49 | public function testCountable() |
||
50 | { |
||
51 | $this->assertEquals(10, count($this->page)); |
||
52 | } |
||
53 | |||
54 | /** |
||
55 | * @covers SlotMachine\SlotMachine::initialize |
||
56 | */ |
||
57 | public function testInitializeWithOptions() |
||
58 | { |
||
59 | $s = new SlotMachine(self::$slotsConfigWithOptions); |
||
60 | $this->assertEquals('Welcome back, Guest!', $s->get('headline', 3)); |
||
61 | $this->assertEquals(2, count($s)); |
||
62 | |||
63 | $t = new SlotMachine(self::$slotsConfigWithOptions, Request::create('?uid=8000')); |
||
64 | |||
65 | $this->assertEquals('See you again, Admin!', $t->get('headline', 8000)); |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * @covers SlotMachine\SlotMachine::get |
||
70 | */ |
||
71 | public function testGet() |
||
72 | { |
||
73 | $this->assertEquals('h', $this->page['headline']->getKey()); |
||
74 | |||
75 | $this->assertEquals('Howdy, stranger. Please take a moment to register.', $this->page->get('headline')); |
||
76 | |||
77 | // This slot has a custom default that should be used. |
||
78 | $this->assertEquals('penguin.png', $this->page->get('featured_image')); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * @covers SlotMachine\SlotMachine::get |
||
83 | * @covers SlotMachine\SlotMachine::all |
||
84 | * @covers SlotMachine\SlotMachine::toJson |
||
85 | * @covers SlotMachine\SlotMachine::__toString |
||
86 | */ |
||
87 | public function testAll() |
||
88 | { |
||
89 | $slots = $this->page->all(); |
||
90 | |||
91 | $this->assertEquals('Howdy, stranger. Please take a moment to register.', $slots['headline']); |
||
92 | $this->assertEquals('penguin.png', $slots['featured_image']); |
||
93 | |||
94 | $json = json_decode($this->page); |
||
95 | $this->assertEquals('penguin.png', $json->featured_image); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * @covers SlotMachine\SlotMachine::get |
||
100 | * @covers SlotMachine\SlotMachine::all |
||
101 | * @covers SlotMachine\SlotMachine::toJson |
||
102 | * @covers SlotMachine\SlotMachine::__toString |
||
103 | */ |
||
104 | public function testAllWithCustomRequestAndDeepParameters() |
||
105 | { |
||
106 | if (!self::$hasDeepParameterAccess) { |
||
107 | $this->markTestSkipped('This test requires deep parameter access from Symfony 2'); |
||
108 | return; |
||
109 | } |
||
110 | |||
111 | // Now try with a custom request |
||
112 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[h]=4&app_data[uid]=11&app_data[i]=2')); |
||
113 | $data = json_decode($slots); |
||
114 | $this->assertEquals('See you again, Claus!', $data->headline); |
||
115 | $this->assertEquals('<img src="parrot.png" alt="Featured Image" />', $data->featured_image_html); |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * @covers SlotMachine\SlotMachine::get |
||
120 | */ |
||
121 | public function testGetUndefinedCard() |
||
122 | { |
||
123 | // Return the default card |
||
124 | $this->assertEquals('Howdy, stranger. Please take a moment to register.', $this->page->get('headline', 9001)); |
||
125 | $this->assertEquals('penguin.png', $this->page->get('featured_image', 9001)); |
||
126 | |||
127 | // Return the fallback card |
||
128 | $this->assertEquals('Dubstep', $this->page->get('music_genre', 9001)); |
||
129 | |||
130 | $this->assertEquals('', $this->page->get('music_genre_optional', 9001)); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * @covers SlotMachine\SlotMachine::get |
||
135 | * @expectedException \SlotMachine\Exception\NoCardFoundException |
||
136 | */ |
||
137 | public function testGetUndefinedCardThrowsException() |
||
138 | { |
||
139 | $this->setExpectedException('SlotMachine\Exception\NoCardFoundException'); |
||
140 | $this->assertEquals('Splittercore', $this->page->get('music_genre_required', 9001)); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * @covers SlotMachine\SlotMachine::get |
||
145 | */ |
||
146 | public function testGetDefaultViaObjectMethod() |
||
147 | { |
||
148 | $this->assertEquals('Sign up now to begin your free download.', $this->page->get('headline', 2)); |
||
149 | |||
150 | // This slot has a custom default and should be overridden. |
||
151 | $this->assertEquals('parrot.png', $this->page->get('featured_image', 2)); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * @covers SlotMachine\SlotMachine::get |
||
156 | */ |
||
157 | public function testGetViaRequest() |
||
158 | { |
||
159 | // Test from passed parameters |
||
160 | $slots = new SlotMachine(self::$slotsConfig, Request::create('/', 'GET', array('h' => '2'))); |
||
161 | $this->assertEquals('Sign up now to begin your free download.', $slots->get('headline')); |
||
162 | |||
163 | // Test from query string |
||
164 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?h=2', 'GET')); |
||
165 | $this->assertEquals('Sign up now to begin your free download.', $slots->get('headline')); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * @covers SlotMachine\SlotMachine::get |
||
170 | */ |
||
171 | public function testGetFromArrayViaRequest() |
||
172 | { |
||
173 | if (!self::$hasDeepParameterAccess) { |
||
174 | $this->markTestSkipped('This test requires deep parameter access from Symfony 2'); |
||
175 | return; |
||
176 | } |
||
177 | |||
178 | // Test from passed array parameters |
||
179 | $slots = new SlotMachine(self::$slotsConfig, |
||
180 | Request::create('/', 'GET', array( |
||
181 | 'app_data' => array('fb' => 1) |
||
182 | )) |
||
183 | ); |
||
184 | $this->assertEquals('product_page', $slots->get('facebook_page')); |
||
185 | |||
186 | // Test from array query string |
||
187 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[fb]=2', 'GET')); |
||
188 | $this->assertEquals('promotional_page', $slots->get('facebook_page')); |
||
189 | |||
190 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[i]=5', 'GET')); |
||
191 | $this->assertEquals('elephant.png', $slots->get('featured_image')); |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * @covers SlotMachine\SlotMachine::get |
||
196 | */ |
||
197 | public function testGetAndResolveParameters() |
||
198 | { |
||
199 | if (!self::$hasDeepParameterAccess) { |
||
200 | $this->markTestSkipped('This test requires deep parameter access from Symfony 2'); |
||
201 | return; |
||
202 | } |
||
203 | |||
204 | // Test from array query string |
||
205 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[h]=1', 'GET')); |
||
206 | $this->assertEquals('Register today for your free gift.', $slots->get('headline')); |
||
207 | |||
208 | // Test from passed array parameters |
||
209 | $slots = new SlotMachine(self::$slotsConfig, Request::create('/', 'GET', array('app_data' => array('h' => 2)))); |
||
210 | $this->assertEquals('Sign up now to begin your free download.', $slots->get('headline')); |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * @covers SlotMachine\SlotMachine::initialize |
||
215 | */ |
||
216 | public function testAssignReel() |
||
217 | { |
||
218 | $this->assertEquals('London', $this->page->get('city')); |
||
219 | $this->assertEquals('Cologne', $this->page->get('city', 9)); |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Not sure if this test is really needed, but it's here anyway. |
||
224 | * @covers SlotMachine\SlotMachine::get |
||
225 | */ |
||
226 | public function testGetReturnsUtf8() |
||
227 | { |
||
228 | // Cyrillic |
||
229 | $this->assertEquals('Москва', $this->page->get('city_l10n', 8)); |
||
230 | |||
231 | // Arabic |
||
232 | $this->assertEquals('القاهرة', $this->page->get('city_l10n', 4)); |
||
233 | |||
234 | // Chinese |
||
235 | $this->assertEquals('上海', $this->page->get('city_l10n', 1)); |
||
236 | |||
237 | // Japanese |
||
238 | $this->assertEquals('東京', $this->page->get('city_l10n', 3)); |
||
239 | |||
240 | // Thai |
||
241 | $this->assertEquals('กรุงเทพมหานคร', $this->page->get('city_l10n', 6)); |
||
242 | |||
243 | // Latin Extended |
||
244 | $this->assertEquals('Köln', $this->page->get('city_l10n', 9)); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * @covers SlotMachine\SlotMachine::initialize |
||
249 | */ |
||
250 | public function testWithNestedSlots() |
||
251 | { |
||
252 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?uid=7&h=3')); |
||
253 | $this->assertEquals('Welcome back, Stan!', $slots->get('headline')); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * @covers SlotMachine\SlotMachine::initialize |
||
258 | */ |
||
259 | public function testWithNestedSlotsAndArrayParameters() |
||
260 | { |
||
261 | if (!self::$hasDeepParameterAccess) { |
||
262 | $this->markTestSkipped('This test requires deep parameter access from Symfony 2'); |
||
263 | return; |
||
264 | } |
||
265 | |||
266 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[uid]=6&app_data[h]=4')); |
||
267 | $this->assertEquals('See you again, Lois!', $slots->get('headline')); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * @covers SlotMachine\SlotMachine::initialize |
||
272 | */ |
||
273 | public function testWithNestedSlotsAndCustomDefaults() |
||
274 | { |
||
275 | if (!self::$hasDeepParameterAccess) { |
||
276 | $this->markTestSkipped('This test requires deep parameter access from Symfony 2'); |
||
277 | return; |
||
278 | } |
||
279 | |||
280 | $this->assertEquals('<img src="penguin.png" alt="Featured Image" />', $this->page->get('featured_image_html')); |
||
281 | |||
282 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[i]=6')); |
||
283 | $this->assertEquals('<img src="tiger.png" alt="Featured Image" />', $slots->get('featured_image_html')); |
||
284 | |||
285 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[i]=6&app_data[ih]=0')); |
||
286 | $this->assertEquals('<img src="tiger.png" />', $slots->get('featured_image_html')); |
||
287 | |||
288 | $slots = new SlotMachine(self::$slotsConfig, Request::create('?app_data[i]=6&app_data[ih]=43')); |
||
289 | $this->assertEquals('<img src="tiger.png" alt="Featured Image" />', $slots->get('featured_image_html')); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * @covers SlotMachine\SlotMachine::initialize |
||
294 | */ |
||
295 | public function testInitialize() |
||
296 | { |
||
297 | // Test by calling getCard directly on the Slot injected into the container. |
||
298 | // That way we know that it has been setup. |
||
299 | $this->assertEquals('Howdy, stranger. Please take a moment to register.', $this->page['headline']->getCard()); |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * @covers SlotMachine\SlotMachine::getConfig |
||
304 | */ |
||
305 | public function testGetConfig() |
||
306 | { |
||
307 | $this->assertTrue(is_array($this->page->getConfig())); |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * @covers SlotMachine\SlotMachine::getRequest |
||
312 | */ |
||
313 | public function testGetRequest() |
||
314 | { |
||
315 | $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\Request', $this->page->getRequest()); |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * @covers SlotMachine\SlotMachine::setRequest |
||
320 | */ |
||
321 | public function testSetRequest() |
||
322 | { |
||
323 | $c = clone $this->page; |
||
324 | $c->setRequest(Request::create('?msg=hello')); |
||
325 | $this->assertEquals('hello', $c->getRequest()->query->get('msg')); |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * @covers SlotMachine\SlotMachine::interpolate |
||
330 | */ |
||
331 | public function testInterpolate() |
||
332 | { |
||
333 | $card = 'I used to {verb} {article} {noun}, but then I took an arrow to the knee.'; |
||
334 | $interpolated = SlotMachine::interpolate($card, array( |
||
335 | 'verb' => 'be', |
||
336 | 'article' => 'an', |
||
337 | 'noun' => 'adventurer' |
||
338 | )); |
||
339 | |||
340 | $this->assertEquals('I used to be an adventurer, but then I took an arrow to the knee.', $interpolated); |
||
341 | |||
342 | // try with custom delimiters |
||
343 | $card = 'I used to %verb% %article% %noun%, but then I took an arrow to the knee.'; |
||
344 | $interpolated = SlotMachine::interpolate($card, array( |
||
345 | 'verb' => 'listen', |
||
346 | 'article' => 'to', |
||
347 | 'noun' => 'dubstep' |
||
348 | ), array('%', '%')); |
||
349 | |||
350 | $this->assertEquals('I used to listen to dubstep, but then I took an arrow to the knee.', $interpolated); |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * @covers SlotMachine\SlotMachine::interpolate |
||
355 | * @expectedException \LengthException |
||
356 | */ |
||
357 | public function testInterpolateThrowsException() |
||
358 | { |
||
359 | $this->setExpectedException('LengthException'); |
||
360 | |||
361 | $card = 'Yo <target>, I\'m real happy for you, Imma let you finish, but <subject> is one of the best <product> of all time!'; |
||
362 | SlotMachine::interpolate($card, array( |
||
363 | 'target' => 'Zend', |
||
364 | 'subject' => 'Symfony', |
||
365 | 'product' => 'PHP frameworks' |
||
366 | ), array('<')); |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * @covers SlotMachine\SlotMachine::interpolate |
||
371 | * @expectedException \PHPUnit_Framework_Error |
||
372 | */ |
||
373 | public function testInterpolateEmitsWarning() |
||
374 | { |
||
375 | $card = '"<quote>", said no one ever!'; |
||
376 | |||
377 | SlotMachine::interpolate($card, array( |
||
378 | 'quote' => 'PHP is a solid language', |
||
379 | ), array('<', '>', '*')); |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * @covers SlotMachine\SlotMachine::interpolate |
||
384 | */ |
||
385 | public function testInterpolateWhileEmittingWarning() |
||
386 | { |
||
387 | $card = '"<quote>", said no one ever!'; |
||
388 | |||
389 | $interpolated = @SlotMachine::interpolate($card, array( |
||
390 | 'quote' => "I won't stay longer than 4 hours in Starbucks for I need to be elsewhere", |
||
391 | ), array('<', '>', '*')); |
||
392 | |||
393 | $this->assertEquals( |
||
394 | "\"I won't stay longer than 4 hours in Starbucks for I need to be elsewhere\", said no one ever!", |
||
395 | $interpolated |
||
396 | ); |
||
397 | } |
||
398 | } |
||
399 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.