1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
App::uses('Controller', 'Controller'); |
4
|
|
|
App::uses('EntriesController', 'Controller'); |
5
|
|
|
App::uses('SaitoControllerTestCase', 'Lib/Test'); |
6
|
|
|
|
7
|
|
|
class EntriesMockController extends EntriesController { |
8
|
|
|
|
9
|
|
|
// @codingStandardsIgnoreStart |
10
|
|
|
public $uses = array('Entry'); |
11
|
|
|
// @codingStandardsIgnoreEnd |
12
|
|
|
|
13
|
|
|
public function getInitialThreads($User, $order = ['Entry.last_answer' => 'DESC']) { |
14
|
|
|
$this->_getInitialThreads($User, $order); |
15
|
|
|
} |
16
|
|
|
|
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
class EntriesControllerTestCase extends \Saito\Test\ControllerTestCase { |
20
|
|
|
|
21
|
|
|
use \Saito\Test\SecurityMockTrait; |
22
|
|
|
|
23
|
|
|
public $fixtures = [ |
24
|
|
|
'app.bookmark', |
25
|
|
|
'app.category', |
26
|
|
|
'app.entry', |
27
|
|
|
'app.esevent', |
28
|
|
|
'app.esnotification', |
29
|
|
|
'app.setting', |
30
|
|
|
'app.shout', |
31
|
|
|
'app.smiley', |
32
|
|
|
'app.smiley_code', |
33
|
|
|
'app.upload', |
34
|
|
|
'app.user', |
35
|
|
|
'app.user_block', |
36
|
|
|
'app.user_ignore', |
37
|
|
|
'app.user_online', |
38
|
|
|
'app.user_read' |
39
|
|
|
]; |
40
|
|
|
|
41
|
|
|
public function testMix() { |
42
|
|
|
$result = $this->testAction('/entries/mix/1', array('return' => 'vars')); |
|
|
|
|
43
|
|
|
$this->assertStringStartsWith('First_Subject', |
44
|
|
|
$result['title_for_layout']); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
public function testMixNoAuthorization() { |
48
|
|
|
$this->testAction('/entries/mix/4', ['return' => 'view']); |
|
|
|
|
49
|
|
|
$this->assertEquals($this->controller->Auth->redirectUrl(), '/entries/mix/4'); |
50
|
|
|
$this->assertRedirectedTo('login'); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
public function testMixNotFound() { |
54
|
|
|
$this->generate('Entries', array()); |
55
|
|
|
$this->setExpectedException('NotFoundException'); |
56
|
|
|
$this->testAction('/entries/mix/9999'); |
|
|
|
|
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* only logged in users should be able to answer |
61
|
|
|
*/ |
62
|
|
|
public function testAddUserNotLoggedInGet() { |
63
|
|
|
$this->generate('Entries', ['methods' => 'add']); |
64
|
|
|
$this->testAction('/entries/add'); |
|
|
|
|
65
|
|
|
$this->assertRedirectedTo('login'); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* successfull add request |
70
|
|
|
*/ |
71
|
|
|
public function testAddSuccess() { |
72
|
|
|
//* setup mock and data |
73
|
|
|
$C = $this->generate( |
74
|
|
|
'Entries', |
75
|
|
|
['models' => ['Esevent' => ['notifyUserOnEvents']]] |
76
|
|
|
); |
77
|
|
|
$this->_loginUser(1); |
78
|
|
|
$data = [ |
79
|
|
|
'Entry' => [ |
80
|
|
|
'subject' => 'subject', |
81
|
|
|
'text' => 'text', |
82
|
|
|
'category_id' => 1, |
83
|
|
|
], |
84
|
|
|
'Event' => [ |
85
|
|
|
1 => ['event_type_id' => 0], |
86
|
|
|
2 => ['event_type_id' => 1] |
87
|
|
|
] |
88
|
|
|
]; |
89
|
|
|
|
90
|
|
|
$latestEntry = $C->Entry->find('first', |
91
|
|
|
['contain' => false, 'order' => ['Entry.id' => 'desc']]); |
92
|
|
|
$expectedId = $latestEntry['Entry']['id'] + 1; |
93
|
|
|
|
94
|
|
|
//* setup notification test |
95
|
|
|
$expected = [ |
96
|
|
|
[ |
97
|
|
|
'subject' => $expectedId, |
98
|
|
|
'event' => 'Model.Entry.replyToEntry', |
99
|
|
|
'receiver' => 'EmailNotification', |
100
|
|
|
'set' => 0, |
101
|
|
|
], |
102
|
|
|
[ |
103
|
|
|
'subject' => $expectedId, |
104
|
|
|
'event' => 'Model.Entry.replyToThread', |
105
|
|
|
'receiver' => 'EmailNotification', |
106
|
|
|
'set' => 1, |
107
|
|
|
] |
108
|
|
|
]; |
109
|
|
|
$C->Entry->Esevent->expects($this->once()) |
110
|
|
|
->method('notifyUserOnEvents') |
111
|
|
|
->with(1, $expected); |
112
|
|
|
|
113
|
|
|
//* test |
114
|
|
|
$this->testAction( |
115
|
|
|
'entries/add', |
|
|
|
|
116
|
|
|
[ |
117
|
|
|
'data' => $data, |
118
|
|
|
'method' => 'POST', |
119
|
|
|
'return' => 'vars' |
120
|
|
|
] |
121
|
|
|
); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
public function testAddSubjectToLong() { |
125
|
|
|
$Entries = $this->generate( 'Entries'); |
126
|
|
|
$this->_loginUser(1); |
127
|
|
|
|
128
|
|
|
// maxlength attribute is set for textfield |
129
|
|
|
$result = $this->testAction('entries/add', |
|
|
|
|
130
|
|
|
['method' => 'GET', 'return' => 'view']); |
131
|
|
|
$this->assertTextContains('maxlength="40"', $result); |
132
|
|
|
|
133
|
|
|
// subject is one char to long |
134
|
|
|
$data = [ |
135
|
|
|
'Entry' => [ |
136
|
|
|
// 41 chars |
137
|
|
|
'subject' => 'Vorher wie ich in der mobilen Version ka…', |
138
|
|
|
'category_id' => 1, |
139
|
|
|
'pid' => 0 |
140
|
|
|
], |
141
|
|
|
'Event' => [ |
142
|
|
|
1 => ['event_type_id' => 0], |
143
|
|
|
2 => ['event_type_id' => 1] |
144
|
|
|
] |
145
|
|
|
]; |
146
|
|
|
|
147
|
|
|
$result = $this->testAction( |
148
|
|
|
'entries/add', |
|
|
|
|
149
|
|
|
['data' => $data, 'method' => 'POST', 'return' => 'view'] |
150
|
|
|
); |
151
|
|
|
$this->assertTextContains('Subject is to long.', $result); |
152
|
|
|
$id = $Entries->Entry->find('count') + 1; |
153
|
|
|
|
154
|
|
|
// subject has max length |
155
|
|
|
$data['Entry']['subject'] = mb_substr($data['Entry']['subject'], 1); |
156
|
|
|
$this->testAction( |
157
|
|
|
'entries/add', |
|
|
|
|
158
|
|
|
['data' => $data, 'method' => 'POST'] |
159
|
|
|
); |
160
|
|
|
|
161
|
|
|
$this->assertRedirectedTo('entries/view/' . $id); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
public function testNoDirectCallOfAnsweringFormWithId() { |
165
|
|
|
$Entries = $this->generate('Entries', |
166
|
|
|
array( |
167
|
|
|
'methods' => array('referer') |
168
|
|
|
)); |
169
|
|
|
$this->_loginUser(1); |
170
|
|
|
$Entries->expects($this->once()) |
171
|
|
|
->method('referer') |
172
|
|
|
->will($this->returnValue('/foo')); |
173
|
|
|
$this->testAction('/entries/add/1'); |
|
|
|
|
174
|
|
|
$this->assertRedirectedTo('foo'); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* User is not logged in |
179
|
|
|
*/ |
180
|
|
|
public function testCategoryChooserNotLoggedIn() { |
181
|
|
|
$Entries = $this->generate('EntriesMock', ['methods' => ['paginate']]); |
182
|
|
|
|
183
|
|
|
Configure::write('Saito.Settings.category_chooser_global', 1); |
184
|
|
|
|
185
|
|
|
$Entries->expects($this->once()) |
186
|
|
|
->method('paginate') |
187
|
|
|
->will($this->returnValue(array())); |
188
|
|
|
|
189
|
|
|
App::uses('CurrentUserComponent', 'Controller/Component'); |
190
|
|
|
App::uses('ComponentCollection', 'Controller'); |
191
|
|
|
$User = new CurrentUserComponent(new ComponentCollection()); |
192
|
|
|
|
193
|
|
|
$User->Categories = $this->getMock('Saito\User\Auth\CategoryAuthorization', ['getAllowed'], |
|
|
|
|
194
|
|
|
[$User]); |
195
|
|
|
$User->Categories->expects($this->any()) |
196
|
|
|
->method('getAllowed') |
197
|
|
|
->will($this->returnValue([ |
198
|
|
|
1 => 'Admin', |
199
|
|
|
2 => 'Ontopic', |
200
|
|
|
7 => 'Foo' |
201
|
|
|
] |
202
|
|
|
)); |
203
|
|
|
|
204
|
|
|
$User->setSettings([]); |
205
|
|
|
$Entries->getInitialThreads($User); |
206
|
|
|
$this->assertFalse(isset($Entries->viewVars['categoryChooser'])); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Admin completely deactivated category-chooser |
211
|
|
|
*/ |
212
|
|
View Code Duplication |
public function testCategoryChooserDeactivated() { |
213
|
|
|
$Entries = $this->generate('EntriesMock', ['methods' => ['paginate']]); |
214
|
|
|
|
215
|
|
|
Configure::write('Saito.Settings.category_chooser_global', 0); |
216
|
|
|
Configure::write('Saito.Settings.category_chooser_user_override', 0); |
217
|
|
|
|
218
|
|
|
$Entries->expects($this->once()) |
219
|
|
|
->method('paginate') |
220
|
|
|
->will($this->returnValue(array())); |
221
|
|
|
|
222
|
|
|
App::uses('CurrentUserComponent', 'Controller/Component'); |
223
|
|
|
App::uses('ComponentCollection', 'Controller'); |
224
|
|
|
$User = new CurrentUserComponent(new ComponentCollection()); |
225
|
|
|
|
226
|
|
|
$User->Categories = $this->getMock( |
|
|
|
|
227
|
|
|
'Saito\User\Auth\CategoryAuthorization', |
228
|
|
|
['getAllowed'], |
229
|
|
|
[$User] |
230
|
|
|
); |
231
|
|
|
$User->Categories->expects($this->any()) |
232
|
|
|
->method('getAllowed') |
233
|
|
|
->will($this->returnValue([ |
234
|
|
|
1 => 'Admin', |
235
|
|
|
2 => 'Ontopic', |
236
|
|
|
7 => 'Foo' |
237
|
|
|
] |
238
|
|
|
)); |
239
|
|
|
|
240
|
|
|
$User->setSettings(array( |
241
|
|
|
'id' => 1, |
242
|
|
|
'user_sort_last_answer' => 1, |
243
|
|
|
'user_type' => 'admin', |
244
|
|
|
'user_category_active' => 0, |
245
|
|
|
'user_category_custom' => '', |
246
|
|
|
'user_category_override' => 1, |
247
|
|
|
)); |
248
|
|
|
$Entries->getInitialThreads($User); |
249
|
|
|
$this->assertFalse(isset($Entries->viewVars['categoryChooser'])); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
View Code Duplication |
public function testCategoryChooserEmptyCustomSet() { |
253
|
|
|
$Entries = $this->generate('EntriesMock', ['methods' => ['paginate']]); |
254
|
|
|
|
255
|
|
|
Configure::write('Saito.Settings.category_chooser_global', 0); |
256
|
|
|
Configure::write('Saito.Settings.category_chooser_user_override', 1); |
257
|
|
|
|
258
|
|
|
$Entries->expects($this->once()) |
259
|
|
|
->method('paginate') |
260
|
|
|
->will($this->returnValue(array())); |
261
|
|
|
|
262
|
|
|
App::uses('CurrentUserComponent', 'Controller/Component'); |
263
|
|
|
App::uses('ComponentCollection', 'Controller'); |
264
|
|
|
$User = new CurrentUserComponent(new ComponentCollection()); |
265
|
|
|
|
266
|
|
|
$User->Categories = $this->getMock( |
|
|
|
|
267
|
|
|
'Saito\User\Auth\CategoryAuthorization', |
268
|
|
|
['getAllowed'], |
269
|
|
|
[$User] |
270
|
|
|
); |
271
|
|
|
$User->Categories->expects($this->any()) |
272
|
|
|
->method('getAllowed') |
273
|
|
|
->will($this->returnValue([ |
274
|
|
|
1 => 'Admin', |
275
|
|
|
2 => 'Ontopic', |
276
|
|
|
7 => 'Foo' |
277
|
|
|
] |
278
|
|
|
)); |
279
|
|
|
|
280
|
|
|
$User->setSettings(array( |
281
|
|
|
'id' => 1, |
282
|
|
|
'user_sort_last_answer' => 1, |
283
|
|
|
'user_type' => 'admin', |
284
|
|
|
'user_category_active' => 0, |
285
|
|
|
'user_category_custom' => array(), |
286
|
|
|
'user_category_override' => 1, |
287
|
|
|
)); |
288
|
|
|
$Entries->getInitialThreads($User); |
289
|
|
|
$this->assertTrue(isset($Entries->viewVars['categoryChooser'])); |
290
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooserTitleId'], 'All Categories'); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
/** |
294
|
|
|
* Test custom set |
295
|
|
|
* |
296
|
|
|
* - new categories (8) are in the custom set |
297
|
|
|
*/ |
298
|
|
|
public function testCategoryChooserCustomSet() { |
299
|
|
|
$Entries = $this->generate('EntriesMock', ['methods' => ['paginate']]); |
300
|
|
|
|
301
|
|
|
Configure::write('Saito.Settings.category_chooser_global', 1); |
302
|
|
|
|
303
|
|
|
$Entries->expects($this->once()) |
304
|
|
|
->method('paginate') |
305
|
|
|
->will($this->returnValue(array())); |
306
|
|
|
|
307
|
|
|
App::uses('CurrentUserComponent', 'Controller/Component'); |
308
|
|
|
App::uses('ComponentCollection', 'Controller'); |
309
|
|
|
$User = new CurrentUserComponent(new ComponentCollection()); |
310
|
|
|
|
311
|
|
|
$User->Categories = $this->getMock( |
|
|
|
|
312
|
|
|
'Saito\User\Auth\CategoryAuthorization', |
313
|
|
|
['getAllowed'], |
314
|
|
|
[$User] |
315
|
|
|
); |
316
|
|
|
$User->Categories->expects($this->any()) |
317
|
|
|
->method('getAllowed') |
318
|
|
|
->will($this->returnValue([ |
319
|
|
|
2 => 'Ontopic', |
320
|
|
|
7 => 'Foo', |
321
|
|
|
8 => 'Bar' |
322
|
|
|
] |
323
|
|
|
)); |
324
|
|
|
|
325
|
|
|
$User->setSettings(array( |
326
|
|
|
'id' => 1, |
327
|
|
|
'user_sort_last_answer' => 1, |
328
|
|
|
'user_type' => 'admin', |
329
|
|
|
'user_category_active' => 0, |
330
|
|
|
'user_category_custom' => array(1 => 1, 2 => 1, 7 => 0), |
331
|
|
|
)); |
332
|
|
|
$Entries->getInitialThreads($User); |
333
|
|
|
$this->assertTrue(isset($Entries->viewVars['categoryChooser'])); |
334
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooserChecked'], |
335
|
|
|
array( |
336
|
|
|
'2' => '2', |
337
|
|
|
'8' => '8', |
338
|
|
|
)); |
339
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooser'], |
340
|
|
|
array( |
341
|
|
|
'2' => 'Ontopic', |
342
|
|
|
'7' => 'Foo', |
343
|
|
|
'8' => 'Bar', |
344
|
|
|
)); |
345
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooserTitleId'], |
346
|
|
|
'Custom'); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
public function testCategoryChooserSingleCategory() { |
350
|
|
|
$Entries = $this->generate('EntriesMock', ['methods' => ['paginate']]); |
351
|
|
|
|
352
|
|
|
Configure::write('Saito.Settings.category_chooser_global', 1); |
353
|
|
|
|
354
|
|
|
$Entries->expects($this->once()) |
355
|
|
|
->method('paginate') |
356
|
|
|
->will($this->returnValue(array())); |
357
|
|
|
|
358
|
|
|
App::uses('CurrentUserComponent', 'Controller/Component'); |
359
|
|
|
App::uses('ComponentCollection', 'Controller'); |
360
|
|
|
$User = new CurrentUserComponent(new ComponentCollection()); |
361
|
|
|
|
362
|
|
|
$User->Categories = $this->getMock( |
|
|
|
|
363
|
|
|
'Saito\User\Auth\CategoryAuthorization', |
364
|
|
|
['getAllowed'], |
365
|
|
|
[$User] |
366
|
|
|
); |
367
|
|
|
$User->Categories->expects($this->any()) |
368
|
|
|
->method('getAllowed') |
369
|
|
|
->will($this->returnValue([ |
370
|
|
|
1 => 'Admin', |
371
|
|
|
2 => 'Ontopic', |
372
|
|
|
7 => 'Foo' |
373
|
|
|
] |
374
|
|
|
)); |
375
|
|
|
|
376
|
|
|
$User->setSettings(array( |
377
|
|
|
'id' => 1, |
378
|
|
|
'user_sort_last_answer' => 1, |
379
|
|
|
'user_type' => 'admin', |
380
|
|
|
'user_category_active' => 7, |
381
|
|
|
'user_category_custom' => array(1 => 1, 2 => 1, 7 => 0), |
382
|
|
|
)); |
383
|
|
|
$Entries->getInitialThreads($User); |
384
|
|
|
$this->assertTrue(isset($Entries->viewVars['categoryChooser'])); |
385
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooserTitleId'], 7); |
386
|
|
|
$this->assertEquals($Entries->viewVars['categoryChooserChecked'], |
387
|
|
|
array( |
388
|
|
|
'1' => '1', |
389
|
|
|
'2' => '2', |
390
|
|
|
)); |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
public function testIndex() { |
394
|
|
|
$this->generate('Entries'); |
395
|
|
|
$this->_logoutUser(); |
396
|
|
|
|
397
|
|
|
//* not logged in user |
398
|
|
|
$result = $this->testAction('/entries/index', array('return' => 'vars')); |
|
|
|
|
399
|
|
|
$entries = $result['entries']; |
400
|
|
|
$this->assertEquals(count($entries), 3); |
401
|
|
|
|
402
|
|
|
//* logged in user |
403
|
|
|
$this->_loginUser(3); |
404
|
|
|
$result = $this->testAction('/entries/index', array('return' => 'vars')); |
|
|
|
|
405
|
|
|
$entries = $result['entries']; |
406
|
|
|
$this->assertEquals(count($entries), 4); |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
public function testIndexSanitation() { |
410
|
|
|
$this->generate('Entries'); |
411
|
|
|
$this->_loginUser(7); |
412
|
|
|
|
413
|
|
|
// uses contents to check in slidetabs |
414
|
|
|
$result = $this->testAction('/entries/index', ['return' => 'contents']); |
|
|
|
|
415
|
|
|
// uses <body>-HTML only: exclude <head> which may contain unescaped JS-data |
416
|
|
|
preg_match('/<body(.*)<\/body>/sm', $result, $matches); |
417
|
|
|
$result = $matches[0]; |
418
|
|
|
$this->assertTextNotContains('&<Subject', $result); |
419
|
|
|
$this->assertTextContains('&<Subject', $result); |
420
|
|
|
$this->assertTextNotContains('&<Username', $result); |
421
|
|
|
$this->assertTextContains('&<Username', $result); |
422
|
|
|
// check for no double encoding |
423
|
|
|
$this->assertTextNotContains('&amp;&lt;Username', $result); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
View Code Duplication |
public function testMergeNoSourceId() { |
427
|
|
|
$Entries = $this->generate('Entries', |
428
|
|
|
array( |
429
|
|
|
'models' => array( |
430
|
|
|
'Entry' => array('merge') |
431
|
|
|
) |
432
|
|
|
)); |
433
|
|
|
$this->_loginUser(2); |
434
|
|
|
|
435
|
|
|
$data = array( |
436
|
|
|
'Entry' => array( |
437
|
|
|
'targetId' => 2, |
438
|
|
|
) |
439
|
|
|
); |
440
|
|
|
|
441
|
|
|
$Entries->Entry->expects($this->never()) |
442
|
|
|
->method('merge'); |
443
|
|
|
$this->setExpectedException('NotFoundException'); |
444
|
|
|
$result = $this->testAction('/entries/merge/', |
|
|
|
|
445
|
|
|
array( |
446
|
|
|
'data' => $data, |
447
|
|
|
'method' => 'post' |
448
|
|
|
)); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
View Code Duplication |
public function testMergeSourceIdNotFound() { |
452
|
|
|
$Entries = $this->generate('Entries', |
453
|
|
|
array( |
454
|
|
|
'models' => array( |
455
|
|
|
'Entry' => array('merge') |
456
|
|
|
) |
457
|
|
|
)); |
458
|
|
|
$this->_loginUser(2); |
459
|
|
|
|
460
|
|
|
$data = array( |
461
|
|
|
'Entry' => array( |
462
|
|
|
'targetId' => 2, |
463
|
|
|
) |
464
|
|
|
); |
465
|
|
|
|
466
|
|
|
$Entries->Entry->expects($this->never()) |
467
|
|
|
->method('merge'); |
468
|
|
|
$this->setExpectedException('NotFoundException'); |
469
|
|
|
$result = $this->testAction('/entries/merge/9999', |
|
|
|
|
470
|
|
|
array( |
471
|
|
|
'data' => $data, |
472
|
|
|
'method' => 'post' |
473
|
|
|
)); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
public function testMergeShowForm() { |
477
|
|
|
$Entries = $this->generate('Entries', |
478
|
|
|
array( |
479
|
|
|
'models' => array( |
480
|
|
|
'Entry' => array('merge') |
481
|
|
|
) |
482
|
|
|
)); |
483
|
|
|
$this->_loginUser(2); |
484
|
|
|
|
485
|
|
|
$data = array( |
486
|
|
|
'Entry' => array() |
487
|
|
|
); |
488
|
|
|
$Entries->Entry->expects($this->never()) |
489
|
|
|
->method('merge'); |
490
|
|
|
$result = $this->testAction('/entries/merge/4', |
|
|
|
|
491
|
|
|
array( |
492
|
|
|
'data' => $data, |
493
|
|
|
'method' => 'post' |
494
|
|
|
)); |
495
|
|
|
$this->assertFalse(isset($this->headers['Location'])); |
496
|
|
|
} |
497
|
|
|
|
498
|
|
View Code Duplication |
public function testMergeIsNotAuthorized() { |
499
|
|
|
$Entries = $this->generate('Entries', |
500
|
|
|
array( |
501
|
|
|
'models' => array( |
502
|
|
|
'Entry' => array('merge') |
503
|
|
|
) |
504
|
|
|
)); |
505
|
|
|
$this->_loginUser(3); |
506
|
|
|
|
507
|
|
|
$data = array( |
508
|
|
|
'Entry' => array( |
509
|
|
|
'targetId' => 2, |
510
|
|
|
) |
511
|
|
|
); |
512
|
|
|
|
513
|
|
|
$Entries->Entry->expects($this->never()) |
514
|
|
|
->method('merge'); |
515
|
|
|
$this->setExpectedException('MethodNotAllowedException'); |
516
|
|
|
$result = $this->testAction('/entries/merge/4', |
|
|
|
|
517
|
|
|
array( |
518
|
|
|
'data' => $data, |
519
|
|
|
'method' => 'post' |
520
|
|
|
)); |
521
|
|
|
} |
522
|
|
|
|
523
|
|
View Code Duplication |
public function testMerge() { |
524
|
|
|
$Entries = $this->generate('Entries', |
525
|
|
|
array( |
526
|
|
|
'models' => array( |
527
|
|
|
'Entry' => array('threadMerge') |
528
|
|
|
) |
529
|
|
|
)); |
530
|
|
|
$this->_loginUser(2); |
531
|
|
|
|
532
|
|
|
$data = array( |
533
|
|
|
'Entry' => array( |
534
|
|
|
'targetId' => 2, |
535
|
|
|
) |
536
|
|
|
); |
537
|
|
|
|
538
|
|
|
$Entries->Entry->expects($this->exactly(1)) |
539
|
|
|
->method('threadMerge') |
540
|
|
|
->with('2') |
541
|
|
|
->will($this->returnValue(true)); |
542
|
|
|
|
543
|
|
|
$result = $this->testAction('/entries/merge/4', |
|
|
|
|
544
|
|
|
array( |
545
|
|
|
'data' => $data, |
546
|
|
|
'method' => 'post' |
547
|
|
|
)); |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
/** |
551
|
|
|
* Entry does not exist |
552
|
|
|
*/ |
553
|
|
|
public function testEditNoEntry() { |
554
|
|
|
$Entries = $this->generate('Entries'); |
|
|
|
|
555
|
|
|
$this->_loginUser(2); |
556
|
|
|
$this->setExpectedException('NotFoundException'); |
557
|
|
|
$this->testAction('entries/edit/9999'); |
|
|
|
|
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
/** |
561
|
|
|
* Entry does not exist |
562
|
|
|
*/ |
563
|
|
|
public function testEditNoEntryId() { |
564
|
|
|
$Entries = $this->generate('Entries'); |
|
|
|
|
565
|
|
|
$this->_loginUser(2); |
566
|
|
|
$this->setExpectedException('BadRequestException'); |
567
|
|
|
$this->testAction('entries/edit/'); |
|
|
|
|
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
/** |
571
|
|
|
* Show editing form |
572
|
|
|
*/ |
573
|
|
|
public function testEditShowForm() { |
574
|
|
|
$Entries = $this->generate('Entries', |
575
|
|
|
array( |
576
|
|
|
'models' => array( |
577
|
|
|
'Entry' => array( |
578
|
|
|
'isEditingForbidden', |
579
|
|
|
) |
580
|
|
|
) |
581
|
|
|
)); |
582
|
|
|
|
583
|
|
|
$this->_loginUser(1); |
584
|
|
|
|
585
|
|
|
$Entries->Entry->expects($this->any()) |
586
|
|
|
->method('isEditingForbidden') |
587
|
|
|
->will($this->returnValue(false)); |
588
|
|
|
|
589
|
|
|
$result = $this->testAction('entries/edit/2', |
|
|
|
|
590
|
|
|
array( |
591
|
|
|
'return' => 'view' |
592
|
|
|
)); |
593
|
|
|
|
594
|
|
|
// test that subject is quoted |
595
|
|
|
$this->assertContains('value="Second_Subject"', $result); |
596
|
|
|
// test that text is quoted |
597
|
|
|
$this->assertContains('Second_Text</textarea>', $result); |
598
|
|
|
// notification are un/checked |
599
|
|
|
$this->assertNotRegExp('/data\[Event\]\[1\]\[event_type_id\]"\s+?checked="checked"/', $result); |
600
|
|
|
$this->assertRegExp('/data\[Event\]\[2\]\[event_type_id\]"\s+?checked="checked"/', $result); |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
/** |
604
|
|
|
* tests that the form renders without error if saving fails |
605
|
|
|
* |
606
|
|
|
* doesn't test for any specific validation error |
607
|
|
|
*/ |
608
|
|
|
public function testEditNoInternalErrorOnValidationError() { |
609
|
|
|
$Entries = $this->generate('Entries', [ |
610
|
|
|
'models' => ['Entry' => ['get', 'update']] |
611
|
|
|
]); |
612
|
|
|
|
613
|
|
|
$Entries->Entry->expects($this->at(0)) |
614
|
|
|
->method('get') |
615
|
|
|
->with(2) |
616
|
|
|
->will($this->returnValue([ |
617
|
|
|
'Entry' => [ |
618
|
|
|
'id' => 2, |
619
|
|
|
'tid' => 1, |
620
|
|
|
'pid' => 1, |
621
|
|
|
'time' => time() - 1, |
622
|
|
|
'user_id' => 2, |
623
|
|
|
'fixed' => false |
624
|
|
|
], |
625
|
|
|
'User' => [ |
626
|
|
|
'username' => 'Mitch' |
627
|
|
|
], |
628
|
|
|
'rights' => [ |
629
|
|
|
'isEditingAsUserForbidden' => false, |
630
|
|
|
'isEditingForbidden' => false |
631
|
|
|
] |
632
|
|
|
])); |
633
|
|
|
$Entries->Entry->expects($this->once()) |
634
|
|
|
->method('update') |
635
|
|
|
->will($this->returnValue(false)); |
636
|
|
|
|
637
|
|
|
$this->_loginUser(1); |
638
|
|
|
$this->testAction('entries/edit/2', [ |
|
|
|
|
639
|
|
|
'data' => [ |
640
|
|
|
'Entry' => [ |
641
|
|
|
'pid' => 1, |
642
|
|
|
] |
643
|
|
|
], |
644
|
|
|
'method' => 'POST' |
645
|
|
|
]); |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
public function testPreviewLoggedIn() { |
649
|
|
|
$this->setExpectedException('ForbiddenException'); |
650
|
|
|
$this->testAction('/entries/preview'); |
|
|
|
|
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
public function testPreviewIsAjax() { |
654
|
|
|
$this->generate('Entries'); |
655
|
|
|
$this->_loginUser(1); |
656
|
|
|
$this->setExpectedException('BadRequestException'); |
657
|
|
|
$this->testAction('/entries/preview'); |
|
|
|
|
658
|
|
|
} |
659
|
|
|
|
660
|
|
View Code Duplication |
public function testPreviewIsPut() { |
661
|
|
|
$this->generate('Entries'); |
662
|
|
|
$this->_setAjax(); |
663
|
|
|
$this->_loginUser(1); |
664
|
|
|
$this->setExpectedException('MethodNotAllowedException'); |
665
|
|
|
$this->testAction('/entries/preview', array('method' => 'GET')); |
|
|
|
|
666
|
|
|
} |
667
|
|
|
|
668
|
|
|
/* |
669
|
|
|
public function testPreview() { |
670
|
|
|
$this->generate('Entries'); |
671
|
|
|
$this->_setAjax(); |
672
|
|
|
$this->_loginUser(1); |
673
|
|
|
|
674
|
|
|
$this->testAction( |
675
|
|
|
'/entries/preview', |
676
|
|
|
array('method' => 'PUT') |
677
|
|
|
); |
678
|
|
|
} |
679
|
|
|
*/ |
680
|
|
|
|
681
|
|
|
public function testView() { |
682
|
|
|
//# not logged in user |
683
|
|
|
$Entries = $this->generate('Entries'); |
684
|
|
|
$this->_logoutUser(); |
685
|
|
|
|
686
|
|
|
$result = $this->testAction('/entries/view/1', array('return' => 'vars')); |
|
|
|
|
687
|
|
|
$this->assertEquals($result['entry']['Entry']['id'], 1); |
688
|
|
|
|
689
|
|
|
$this->testAction('/entries/view/2'); |
|
|
|
|
690
|
|
|
$this->assertFalse(isset($this->headers['Location'])); |
691
|
|
|
|
692
|
|
|
$this->testAction('/entries/view/4', array('return' => 'view')); |
|
|
|
|
693
|
|
|
$this->assertEquals($Entries->Auth->redirectUrl(), '/entries/view/4'); |
694
|
|
|
$this->assertRedirectedTo('login'); |
695
|
|
|
|
696
|
|
|
//# logged in user |
697
|
|
|
$this->_loginUser(3); |
698
|
|
|
$result = $this->testAction('/entries/view/4', array('return' => 'vars')); |
|
|
|
|
699
|
|
|
$this->assertEquals($result['entry']['Entry']['id'], 4); |
700
|
|
|
|
701
|
|
|
$this->testAction('/entries/view/2', array('return' => 'vars')); |
|
|
|
|
702
|
|
|
$this->assertFalse(isset($this->headers['Location'])); |
703
|
|
|
|
704
|
|
|
$this->testAction('/entries/view/4', array('return' => 'vars')); |
|
|
|
|
705
|
|
|
$this->assertFalse(isset($this->headers['Location'])); |
706
|
|
|
|
707
|
|
|
//* redirect to index if entry does not exist |
708
|
|
|
$this->testAction('/entries/view/9999', array('return' => 'vars')); |
|
|
|
|
709
|
|
|
$this->assertRedirectedTo(); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
public function testViewIncreaseViewCounterNotLoggedIn() { |
713
|
|
|
$Entries = $this->generate('Entries', [ |
714
|
|
|
'models' => ['Entry' => ['incrementViews']] |
715
|
|
|
]); |
716
|
|
|
$id = 1; |
717
|
|
|
$Entries->Entry->expects($this->once()) |
718
|
|
|
->method('incrementViews') |
719
|
|
|
->with($id); |
720
|
|
|
$this->testAction('/entries/view/' . $id); |
|
|
|
|
721
|
|
|
} |
722
|
|
|
|
723
|
|
View Code Duplication |
public function testViewIncreaseViewCounterLoggedIn() { |
724
|
|
|
$Entries = $this->generate('Entries', [ |
725
|
|
|
'models' => ['Entry' => ['incrementViews']] |
726
|
|
|
]); |
727
|
|
|
$id = 1; |
728
|
|
|
$Entries->Entry->expects($this->once()) |
729
|
|
|
->method('incrementViews') |
730
|
|
|
->with($id); |
731
|
|
|
$this->_loginUser(1); |
732
|
|
|
$this->testAction('/entries/view/' . $id); |
|
|
|
|
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
/** |
736
|
|
|
* don't increase view counter if user views its own posting |
737
|
|
|
*/ |
738
|
|
|
public function testViewIncreaseViewCounterSameUser() { |
739
|
|
|
$Entries = $this->generate('Entries', [ |
740
|
|
|
'models' => ['Entry' => ['incrementViews']] |
741
|
|
|
]); |
742
|
|
|
$id = 1; |
743
|
|
|
$this->_loginUser(3); |
744
|
|
|
|
745
|
|
|
$Entries->Entry->expects($this->never()) |
746
|
|
|
->method('incrementViews'); |
747
|
|
|
$this->testAction('/entries/view/' . $id); |
|
|
|
|
748
|
|
|
} |
749
|
|
|
|
750
|
|
|
/** |
751
|
|
|
* don't increase view counter on spiders/crawlers |
752
|
|
|
*/ |
753
|
|
|
public function testViewIncreaseViewCounterCrawler() { |
754
|
|
|
$this->_setUserAgent('A Crawler Agent'); |
755
|
|
|
$id = 1; |
756
|
|
|
$Entries = $this->generate('Entries', [ |
757
|
|
|
'models' => ['Entry' => ['incrementViews']] |
758
|
|
|
]); |
759
|
|
|
|
760
|
|
|
$Entries->Entry->expects($this->never()) |
761
|
|
|
->method('incrementViews'); |
762
|
|
|
|
763
|
|
|
$this->testAction('/entries/view/' . $id); |
|
|
|
|
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
public function testViewBoxFooter() { |
767
|
|
|
$result = $this->testAction('entries/view/1', |
|
|
|
|
768
|
|
|
array( |
769
|
|
|
'return' => 'view' |
770
|
|
|
)); |
771
|
|
|
$this->assertTextNotContains('panel-footer panel-form', $result); |
772
|
|
|
|
773
|
|
|
$this->_loginUser(3); |
774
|
|
|
$result = $this->testAction('entries/view/1', |
|
|
|
|
775
|
|
|
array( |
776
|
|
|
'return' => 'view' |
777
|
|
|
)); |
778
|
|
|
$this->assertTextContains('panel-footer panel-form', $result); |
779
|
|
|
} |
780
|
|
|
|
781
|
|
|
/** |
782
|
|
|
* Checks that the mod-button is in-/visible |
783
|
|
|
*/ |
784
|
|
|
public function testViewModButton() { |
785
|
|
|
/** |
786
|
|
|
* Mod Button is not visible for anon users |
787
|
|
|
*/ |
788
|
|
|
$result = $this->testAction('entries/view/1', |
|
|
|
|
789
|
|
|
array( |
790
|
|
|
'return' => 'view' |
791
|
|
|
)); |
792
|
|
|
$this->assertTextNotContains('dropdown', $result); |
793
|
|
|
|
794
|
|
|
/** |
795
|
|
|
* Mod Button is not visible for normal users |
796
|
|
|
*/ |
797
|
|
|
$this->_loginUser(3); |
798
|
|
|
$result = $this->testAction('entries/view/1', |
|
|
|
|
799
|
|
|
array( |
800
|
|
|
'return' => 'view' |
801
|
|
|
)); |
802
|
|
|
$this->assertTextNotContains('dropdown', $result); |
803
|
|
|
|
804
|
|
|
/** |
805
|
|
|
* Mod Button is visible for mods |
806
|
|
|
*/ |
807
|
|
|
$this->_loginUser(2); |
808
|
|
|
$result = $this->testAction('entries/view/1', |
|
|
|
|
809
|
|
|
array( |
810
|
|
|
'return' => 'view' |
811
|
|
|
)); |
812
|
|
|
$this->assertTextContains('dropdown', $result); |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
public function testViewSanitation() { |
816
|
|
|
$result = $this->testAction('/entries/view/11', ['return' => 'view']); |
|
|
|
|
817
|
|
|
$this->assertTextNotContains('&<Subject', $result); |
818
|
|
|
$this->assertTextContains('&<Subject', $result); |
819
|
|
|
$this->assertTextNotContains('&<Text', $result); |
820
|
|
|
$this->assertTextContains('&<Text', $result); |
821
|
|
|
$this->assertTextNotContains('&<Username', $result); |
822
|
|
|
$this->assertTextContains('&<Username', $result); |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
public function testThreadLineAnon() { |
826
|
|
|
$Entries = $this->generate( |
827
|
|
|
'Entries', |
828
|
|
|
['components' => ['Auth' => ['_stop']]] |
829
|
|
|
); |
830
|
|
|
$Entries->Auth->expects($this->once())->method('_stop'); |
831
|
|
|
$result = $this->testAction('/entries/threadLine/1.json'); |
|
|
|
|
832
|
|
|
// $this->assertRedirectedTo('login'); |
833
|
|
|
} |
834
|
|
|
|
835
|
|
|
public function testThreadLineForbidden() { |
836
|
|
|
$this->generate('Entries'); |
837
|
|
|
$this->_loginUser(3); |
838
|
|
|
$this->testAction('/entries/threadLine/6.json'); |
|
|
|
|
839
|
|
|
$this->assertRedirectedTo('login'); |
840
|
|
|
} |
841
|
|
|
|
842
|
|
View Code Duplication |
public function testThreadLineSucces() { |
843
|
|
|
$this->generate('Entries'); |
844
|
|
|
$this->_loginUser(1); |
845
|
|
|
$result = $this->testAction('/entries/threadLine/6.json', ['return' => 'view']); |
|
|
|
|
846
|
|
|
$expected = 'Third Thread First_Subject'; |
847
|
|
|
$this->assertContains($expected, $result); |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
public function testAppStats() { |
851
|
|
|
Configure::write('Cache.disable', false); |
852
|
|
|
Cache::delete('header_counter', 'short'); |
853
|
|
|
|
854
|
|
|
// test with no user online |
855
|
|
|
$result = $this->testAction('/entries/index', |
|
|
|
|
856
|
|
|
['method' => 'GET', 'return' => 'vars']); |
857
|
|
|
$headerCounter = $result['HeaderCounter']; |
858
|
|
|
|
859
|
|
|
$this->assertEquals($headerCounter['user_online'], 1); |
860
|
|
|
$this->assertEquals($headerCounter['user'], 10); |
861
|
|
|
$this->assertEquals($headerCounter['entries'], 11); |
862
|
|
|
$this->assertEquals($headerCounter['threads'], 5); |
863
|
|
|
$this->assertEquals($headerCounter['user_registered'], 0); |
864
|
|
|
$this->assertEquals($headerCounter['user_anonymous'], 1); |
865
|
|
|
|
866
|
|
|
// test with one user online |
867
|
|
|
$this->_loginUser(2); |
868
|
|
|
|
869
|
|
|
$result = $this->testAction('/entries/index', |
|
|
|
|
870
|
|
|
['method' => 'GET', 'return' => 'vars']); |
871
|
|
|
$headerCounter = $result['HeaderCounter']; |
872
|
|
|
|
873
|
|
|
/* without cache |
874
|
|
|
$this->assertEquals($headerCounter['user_online'], 2); |
875
|
|
|
$this->assertEquals($headerCounter['user_registered'], 1); |
876
|
|
|
$this->assertEquals($headerCounter['user_anonymous'], 1); |
877
|
|
|
*/ |
878
|
|
|
|
879
|
|
|
// with cache |
880
|
|
|
$this->assertEquals($headerCounter['user_online'], 1); |
881
|
|
|
$this->assertEquals($headerCounter['user_registered'], 1); |
882
|
|
|
$this->assertEquals($headerCounter['user_anonymous'], 0); |
883
|
|
|
|
884
|
|
|
// test with second user online |
885
|
|
|
$this->_loginUser(3); |
886
|
|
|
|
887
|
|
|
$result = $this->testAction('/entries/index', |
|
|
|
|
888
|
|
|
['method' => 'GET', 'return' => 'vars']); |
889
|
|
|
$headerCounter = $result['HeaderCounter']; |
890
|
|
|
|
891
|
|
|
// with cache |
892
|
|
|
$this->assertEquals($headerCounter['user_online'], 1); |
893
|
|
|
$this->assertEquals($headerCounter['user_registered'], 2); |
894
|
|
|
$this->assertEquals($headerCounter['user_anonymous'], 0); |
895
|
|
|
} |
896
|
|
|
|
897
|
|
|
public function testFeedJson() { |
898
|
|
|
$result = $this->testAction('/entries/feed/feed.json', |
|
|
|
|
899
|
|
|
['method' => 'GET', 'return' => 'vars']); |
900
|
|
|
$this->assertEquals($result['entries'][0]['Entry']['subject'], 'First_Subject'); |
901
|
|
|
$this->assertFalse(isset($result['entries'][0]['Entry']['ip'])); |
902
|
|
|
} |
903
|
|
|
|
904
|
|
|
public function testSolveNotLoggedIn() { |
905
|
|
|
$this->generate('Entries', ['methods' => 'solve']); |
906
|
|
|
$this->testAction('/entries/solve/1'); |
|
|
|
|
907
|
|
|
$this->assertRedirectedTo('login'); |
908
|
|
|
} |
909
|
|
|
|
910
|
|
|
public function testSolveNoEntry() { |
911
|
|
|
$this->generate('Entries'); |
912
|
|
|
$this->_loginUser(1); |
913
|
|
|
$this->setExpectedException('BadRequestException'); |
914
|
|
|
$this->testAction('/entries/solve/9999'); |
|
|
|
|
915
|
|
|
} |
916
|
|
|
|
917
|
|
|
public function testSolveNotRootEntryUser() { |
918
|
|
|
$this->generate('Entries'); |
919
|
|
|
$this->_loginUser(2); |
920
|
|
|
$this->setExpectedException('BadRequestException'); |
921
|
|
|
$this->testAction('/entries/solve/1'); |
|
|
|
|
922
|
|
|
} |
923
|
|
|
|
924
|
|
|
public function testSolveIsRootEntry() { |
925
|
|
|
$this->generate('Entries'); |
926
|
|
|
$this->_loginUser(3); |
927
|
|
|
$this->setExpectedException('BadRequestException'); |
928
|
|
|
$this->testAction('/entries/solve/1'); |
|
|
|
|
929
|
|
|
} |
930
|
|
|
|
931
|
|
View Code Duplication |
public function testSolveSaveError() { |
932
|
|
|
$Entries = $this->generate('Entries', ['models' => ['Entry' => ['toggleSolve']]]); |
933
|
|
|
$this->_loginUser(3); |
934
|
|
|
$Entries->Entry->expects($this->once()) |
935
|
|
|
->method('toggleSolve') |
936
|
|
|
->with('1') |
937
|
|
|
->will($this->returnValue(false)); |
938
|
|
|
$this->setExpectedException('BadRequestException'); |
939
|
|
|
$this->testAction('/entries/solve/1'); |
|
|
|
|
940
|
|
|
} |
941
|
|
|
|
942
|
|
|
public function testSeo() { |
943
|
|
|
$config = Configure::read('App'); |
944
|
|
|
$config['baseUrl'] = '/'; |
945
|
|
|
Configure::write('App', $config); |
946
|
|
|
|
947
|
|
|
$result = $this->testAction('/entries/index', |
|
|
|
|
948
|
|
|
['method' => 'GET', 'return' => 'contents']); |
949
|
|
|
$this->assertTextNotContains('noindex', $result); |
950
|
|
|
$expected = '<link rel="canonical" href="' . Router::url('/', |
951
|
|
|
true) . '"/>'; |
952
|
|
|
$this->assertTextContains($expected, $result); |
953
|
|
|
|
954
|
|
|
Configure::write('Saito.Settings.topics_per_page', 2); |
955
|
|
|
$result = $this->testAction('/entries/index/page:2/', |
|
|
|
|
956
|
|
|
['method' => 'GET', 'return' => 'contents']); |
957
|
|
|
$this->assertTextNotContains('rel="canonical"', $result); |
958
|
|
|
$expected = '<meta name="robots" content="noindex, follow">'; |
959
|
|
|
$this->assertTextContains($expected, $result); |
960
|
|
|
} |
961
|
|
|
|
962
|
|
View Code Duplication |
public function testSolve() { |
963
|
|
|
$Entries = $this->generate('Entries', ['models' => ['Entry' => ['toggleSolve']]]); |
964
|
|
|
$this->_loginUser(3); |
965
|
|
|
$Entries->Entry->expects($this->once()) |
966
|
|
|
->method('toggleSolve') |
967
|
|
|
->with('1') |
968
|
|
|
->will($this->returnValue(true)); |
969
|
|
|
$result = $this->testAction('/entries/solve/1'); |
|
|
|
|
970
|
|
|
$this->assertTextEquals($result, ''); |
971
|
|
|
} |
972
|
|
|
|
973
|
|
|
//----------------------------------------------- |
974
|
|
|
|
975
|
|
|
public function setUp() { |
976
|
|
|
parent::setUp(); |
977
|
|
|
$this->_saitoSettingsTopicsPerPage = Configure::read('Saito.Settings.topics_per_page'); |
|
|
|
|
978
|
|
|
Configure::write('Saito.Settings.topics_per_page', 20); |
979
|
|
|
} |
980
|
|
|
|
981
|
|
|
public function tearDown() { |
982
|
|
|
parent::tearDown(); |
983
|
|
|
Configure::write('Saito.Settings.topics_per_page', |
984
|
|
|
$this->_saitoSettingsTopicsPerPage); |
985
|
|
|
} |
986
|
|
|
|
987
|
|
|
} |
988
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.