1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\Comments\Tests; |
||||
4 | |||||
5 | use HTMLPurifier; |
||||
0 ignored issues
–
show
|
|||||
6 | use HTMLPurifier_Config; |
||||
0 ignored issues
–
show
The type
HTMLPurifier_Config was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||
7 | use ReflectionClass; |
||||
8 | use SilverStripe\Comments\Extensions\CommentsExtension; |
||||
9 | use SilverStripe\Comments\Model\Comment; |
||||
10 | use SilverStripe\Comments\Tests\Stubs\CommentableItem; |
||||
11 | use SilverStripe\Comments\Tests\Stubs\CommentableItemDisabled; |
||||
12 | use SilverStripe\Comments\Tests\Stubs\CommentableItemEnabled; |
||||
13 | use SilverStripe\Core\Config\Config; |
||||
14 | use SilverStripe\Dev\FunctionalTest; |
||||
15 | use SilverStripe\ORM\DataObject; |
||||
16 | use SilverStripe\Security\Member; |
||||
17 | use SilverStripe\Security\Security; |
||||
18 | |||||
19 | class CommentsTest extends FunctionalTest |
||||
20 | { |
||||
21 | protected static $fixture_file = 'CommentsTest.yml'; |
||||
22 | |||||
23 | protected static $extra_dataobjects = [ |
||||
24 | CommentableItem::class, |
||||
25 | CommentableItemEnabled::class, |
||||
26 | CommentableItemDisabled::class, |
||||
27 | ]; |
||||
28 | |||||
29 | protected function setUp() |
||||
30 | { |
||||
31 | parent::setUp(); |
||||
32 | |||||
33 | // Set good default values |
||||
34 | Config::modify()->merge(CommentsExtension::class, 'comments', [ |
||||
35 | 'enabled' => true, |
||||
36 | 'comment_permalink_prefix' => 'comment-', |
||||
37 | ]); |
||||
38 | } |
||||
39 | |||||
40 | public function testCommentsList() |
||||
41 | { |
||||
42 | // comments don't require moderation so unmoderated comments can be |
||||
43 | // shown but not spam posts |
||||
44 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
45 | 'require_moderation_nonmembers' => false, |
||||
46 | 'require_moderation' => false, |
||||
47 | 'require_moderation_cms' => false, |
||||
48 | ]); |
||||
49 | |||||
50 | $item = $this->objFromFixture(CommentableItem::class, 'spammed'); |
||||
51 | |||||
52 | $this->assertListEquals([ |
||||
53 | ['Name' => 'Comment 1'], |
||||
54 | ['Name' => 'Comment 3'] |
||||
55 | ], $item->Comments(), 'Only 2 non spam posts should be shown'); |
||||
56 | |||||
57 | // when moderated, only moderated, non spam posts should be shown. |
||||
58 | Config::modify()->merge(CommentableItem::class, 'comments', ['require_moderation_nonmembers' => true]); |
||||
59 | |||||
60 | // Check that require_moderation overrides this option |
||||
61 | Config::modify()->merge(CommentableItem::class, 'comments', ['require_moderation' => true]); |
||||
62 | |||||
63 | $this->assertListEquals(array( |
||||
64 | array('Name' => 'Comment 3') |
||||
65 | ), $item->Comments(), 'Only 1 non spam, moderated post should be shown'); |
||||
66 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
67 | |||||
68 | // require_moderation_nonmembers still filters out unmoderated comments |
||||
69 | Config::modify()->merge(CommentableItem::class, 'comments', ['require_moderation' => false]); |
||||
70 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
71 | |||||
72 | Config::modify()->merge(CommentableItem::class, 'comments', ['require_moderation_nonmembers' => false]); |
||||
73 | $this->assertEquals(2, $item->Comments()->Count()); |
||||
74 | |||||
75 | // With unmoderated comments set to display in frontend |
||||
76 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
77 | 'require_moderation' => true, |
||||
78 | 'frontend_moderation' => true, |
||||
79 | ]); |
||||
80 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
81 | |||||
82 | $this->logInWithPermission('ADMIN'); |
||||
83 | $this->assertEquals(2, $item->Comments()->Count()); |
||||
84 | |||||
85 | // With spam comments set to display in frontend |
||||
86 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
87 | 'require_moderation' => true, |
||||
88 | 'frontend_moderation' => false, |
||||
89 | 'frontend_spam' => true, |
||||
90 | ]); |
||||
91 | |||||
92 | $this->logOut(); |
||||
93 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
94 | |||||
95 | $this->logInWithPermission('ADMIN'); |
||||
96 | $this->assertEquals(2, $item->Comments()->Count()); |
||||
97 | |||||
98 | |||||
99 | // With spam and unmoderated comments set to display in frontend |
||||
100 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
101 | 'require_moderation' => true, |
||||
102 | 'frontend_moderation' => true, |
||||
103 | 'frontend_spam' => true, |
||||
104 | ]); |
||||
105 | |||||
106 | $this->logOut(); |
||||
107 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
108 | |||||
109 | $this->logInWithPermission('ADMIN'); |
||||
110 | $this->assertEquals(4, $item->Comments()->Count()); |
||||
111 | } |
||||
112 | |||||
113 | /** |
||||
114 | * Test moderation options configured via the CMS |
||||
115 | */ |
||||
116 | public function testCommentCMSModerationList() |
||||
117 | { |
||||
118 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
119 | 'require_moderation' => true, |
||||
120 | 'require_moderation_cms' => true, |
||||
121 | ]); |
||||
122 | |||||
123 | $item = $this->objFromFixture(CommentableItem::class, 'spammed'); |
||||
124 | |||||
125 | $this->assertEquals('None', $item->getModerationRequired()); |
||||
126 | |||||
127 | $this->assertListEquals([ |
||||
128 | ['Name' => 'Comment 1'], |
||||
129 | ['Name' => 'Comment 3'] |
||||
130 | ], $item->Comments(), 'Only 2 non spam posts should be shown'); |
||||
131 | |||||
132 | // when moderated, only moderated, non spam posts should be shown. |
||||
133 | $item->ModerationRequired = 'NonMembersOnly'; |
||||
134 | $item->write(); |
||||
135 | |||||
136 | $this->assertEquals('NonMembersOnly', $item->getModerationRequired()); |
||||
137 | |||||
138 | // Check that require_moderation overrides this option |
||||
139 | $item->ModerationRequired = 'Required'; |
||||
140 | $item->write(); |
||||
141 | $this->assertEquals('Required', $item->getModerationRequired()); |
||||
142 | |||||
143 | $this->assertListEquals([ |
||||
144 | ['Name' => 'Comment 3'] |
||||
145 | ], $item->Comments(), 'Only 1 non spam, moderated post should be shown'); |
||||
146 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
147 | |||||
148 | // require_moderation_nonmembers still filters out unmoderated comments |
||||
149 | $item->ModerationRequired = 'NonMembersOnly'; |
||||
150 | $item->write(); |
||||
151 | $this->assertEquals(1, $item->Comments()->Count()); |
||||
152 | |||||
153 | $item->ModerationRequired = 'None'; |
||||
154 | $item->write(); |
||||
155 | $this->assertEquals(2, $item->Comments()->Count()); |
||||
156 | } |
||||
157 | |||||
158 | public function testCanPostComment() |
||||
159 | { |
||||
160 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
161 | 'require_login' => false, |
||||
162 | 'require_login_cms' => false, |
||||
163 | 'required_permission' => false, |
||||
164 | ]); |
||||
165 | /** @var CommentableItem&CommentsExtension $item */ |
||||
166 | $item = $this->objFromFixture(CommentableItem::class, 'first'); |
||||
167 | /** @var CommentableItem&CommentsExtension $item2 */ |
||||
168 | $item2 = $this->objFromFixture(CommentableItem::class, 'second'); |
||||
169 | |||||
170 | // Test restriction free commenting |
||||
171 | $this->logOut(); |
||||
172 | $this->assertFalse($item->CommentsRequireLogin); |
||||
0 ignored issues
–
show
The property
CommentsRequireLogin does not exist on SilverStripe\Comments\Tests\Stubs\CommentableItem . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
173 | $this->assertTrue($item->canPostComment()); |
||||
0 ignored issues
–
show
The method
canPostComment() does not exist on SilverStripe\Comments\Tests\Stubs\CommentableItem . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
174 | |||||
175 | // Test permission required to post |
||||
176 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
177 | 'require_login' => true, |
||||
178 | 'required_permission' => 'POSTING_PERMISSION', |
||||
179 | ]); |
||||
180 | $this->assertTrue($item->CommentsRequireLogin); |
||||
181 | $this->assertFalse($item->canPostComment()); |
||||
182 | $this->logInWithPermission('WRONG_ONE'); |
||||
183 | $this->assertFalse($item->canPostComment()); |
||||
184 | $this->logInWithPermission('POSTING_PERMISSION'); |
||||
185 | $this->assertTrue($item->canPostComment()); |
||||
186 | $this->logInWithPermission('ADMIN'); |
||||
187 | $this->assertTrue($item->canPostComment()); |
||||
188 | |||||
189 | // Test require login to post, but not any permissions |
||||
190 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
191 | 'required_permission' => false, |
||||
192 | ]); |
||||
193 | $this->assertTrue($item->CommentsRequireLogin); |
||||
194 | |||||
195 | $this->logOut(); |
||||
196 | $this->assertFalse($item->canPostComment()); |
||||
197 | $this->logInWithPermission('ANY_PERMISSION'); |
||||
198 | $this->assertTrue($item->canPostComment()); |
||||
199 | |||||
200 | // Test options set via CMS |
||||
201 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
202 | 'require_login' => true, |
||||
203 | 'require_login_cms' => true, |
||||
204 | ]); |
||||
205 | $this->assertFalse($item->CommentsRequireLogin); |
||||
206 | $this->assertTrue($item2->CommentsRequireLogin); |
||||
207 | |||||
208 | $this->logOut(); |
||||
209 | $this->assertTrue($item->canPostComment()); |
||||
210 | $this->assertFalse($item2->canPostComment()); |
||||
211 | |||||
212 | // Login grants permission to post |
||||
213 | $this->logInWithPermission('ANY_PERMISSION'); |
||||
214 | $this->assertTrue($item->canPostComment()); |
||||
215 | $this->assertTrue($item2->canPostComment()); |
||||
216 | } |
||||
217 | public function testDeleteComment() |
||||
218 | { |
||||
219 | // Test anonymous user |
||||
220 | $this->logOut(); |
||||
221 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
222 | $commentID = $comment->ID; |
||||
223 | $this->assertNull($comment->DeleteLink(), 'No permission to see delete link'); |
||||
224 | $delete = $this->get('comments/delete/' . $comment->ID . '?ajax=1'); |
||||
225 | $this->assertEquals(403, $delete->getStatusCode()); |
||||
226 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
227 | $this->assertTrue($check && $check->exists()); |
||||
228 | |||||
229 | // Test non-authenticated user |
||||
230 | $this->logInAs('visitor'); |
||||
231 | $this->assertNull($comment->DeleteLink(), 'No permission to see delete link'); |
||||
232 | |||||
233 | // Test authenticated user |
||||
234 | $this->logInAs('commentadmin'); |
||||
235 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
236 | $commentID = $comment->ID; |
||||
237 | $adminComment1Link = $comment->DeleteLink(); |
||||
238 | $this->assertContains('comments/delete/' . $commentID . '?t=', $adminComment1Link); |
||||
239 | |||||
240 | // Test that this link can't be shared / XSS exploited |
||||
241 | $this->logInAs('commentadmin2'); |
||||
242 | $delete = $this->get($adminComment1Link); |
||||
243 | $this->assertEquals(400, $delete->getStatusCode()); |
||||
244 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
245 | $this->assertTrue($check && $check->exists()); |
||||
246 | |||||
247 | // Test that this other admin can delete the comment with their own link |
||||
248 | $adminComment2Link = $comment->DeleteLink(); |
||||
249 | $this->assertNotEquals($adminComment2Link, $adminComment1Link); |
||||
250 | $this->autoFollowRedirection = false; |
||||
251 | $delete = $this->get($adminComment2Link); |
||||
252 | $this->assertEquals(302, $delete->getStatusCode()); |
||||
253 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
254 | $this->assertFalse($check && $check->exists()); |
||||
255 | } |
||||
256 | |||||
257 | public function testSpamComment() |
||||
258 | { |
||||
259 | // Test anonymous user |
||||
260 | $this->logOut(); |
||||
261 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
262 | $commentID = $comment->ID; |
||||
263 | $this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link'); |
||||
264 | $spam = $this->get('comments/spam/' . $comment->ID . '?ajax=1'); |
||||
265 | $this->assertEquals(403, $spam->getStatusCode()); |
||||
266 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
267 | $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam'); |
||||
268 | |||||
269 | // Test non-authenticated user |
||||
270 | $this->logInAs('visitor'); |
||||
271 | $this->assertNull($comment->SpamLink(), 'No permission to see mark as spam link'); |
||||
272 | |||||
273 | // Test authenticated user |
||||
274 | $this->logInAs('commentadmin'); |
||||
275 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
276 | $commentID = $comment->ID; |
||||
277 | $adminComment1Link = $comment->SpamLink(); |
||||
278 | $this->assertContains('comments/spam/' . $commentID . '?t=', $adminComment1Link); |
||||
279 | |||||
280 | // Test that this link can't be shared / XSS exploited |
||||
281 | $this->logInAs('commentadmin2'); |
||||
282 | $spam = $this->get($adminComment1Link); |
||||
283 | $this->assertEquals(400, $spam->getStatusCode()); |
||||
284 | $check = DataObject::get_by_id(Comment::class, $comment->ID); |
||||
285 | $this->assertEquals(0, $check->IsSpam, 'No permission to mark as spam'); |
||||
286 | |||||
287 | // Test that this other admin can spam the comment with their own link |
||||
288 | $adminComment2Link = $comment->SpamLink(); |
||||
289 | $this->assertNotEquals($adminComment2Link, $adminComment1Link); |
||||
290 | $this->autoFollowRedirection = false; |
||||
291 | $spam = $this->get($adminComment2Link); |
||||
292 | $this->assertEquals(302, $spam->getStatusCode()); |
||||
293 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
294 | $this->assertEquals(1, $check->IsSpam); |
||||
295 | |||||
296 | // Cannot re-spam spammed comment |
||||
297 | $this->assertNull($check->SpamLink()); |
||||
298 | } |
||||
299 | |||||
300 | public function testHamComment() |
||||
301 | { |
||||
302 | // Test anonymous user |
||||
303 | $this->logOut(); |
||||
304 | $comment = $this->objFromFixture(Comment::class, 'secondComC'); |
||||
305 | $commentID = $comment->ID; |
||||
306 | $this->assertNull($comment->HamLink(), 'No permission to see mark as ham link'); |
||||
307 | $ham = $this->get('comments/ham/' . $comment->ID . '?ajax=1'); |
||||
308 | $this->assertEquals(403, $ham->getStatusCode()); |
||||
309 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
310 | $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham'); |
||||
311 | |||||
312 | // Test non-authenticated user |
||||
313 | $this->logInAs('visitor'); |
||||
314 | $this->assertNull($comment->HamLink(), 'No permission to see mark as ham link'); |
||||
315 | |||||
316 | // Test authenticated user |
||||
317 | $this->logInAs('commentadmin'); |
||||
318 | $comment = $this->objFromFixture(Comment::class, 'secondComC'); |
||||
319 | $commentID = $comment->ID; |
||||
320 | $adminComment1Link = $comment->HamLink(); |
||||
321 | $this->assertContains('comments/ham/' . $commentID . '?t=', $adminComment1Link); |
||||
322 | |||||
323 | // Test that this link can't be shared / XSS exploited |
||||
324 | $this->logInAs('commentadmin2'); |
||||
325 | $ham = $this->get($adminComment1Link); |
||||
326 | $this->assertEquals(400, $ham->getStatusCode()); |
||||
327 | $check = DataObject::get_by_id(Comment::class, $comment->ID); |
||||
328 | $this->assertEquals(1, $check->IsSpam, 'No permission to mark as ham'); |
||||
329 | |||||
330 | // Test that this other admin can ham the comment with their own link |
||||
331 | $adminComment2Link = $comment->HamLink(); |
||||
332 | $this->assertNotEquals($adminComment2Link, $adminComment1Link); |
||||
333 | $this->autoFollowRedirection = false; |
||||
334 | $ham = $this->get($adminComment2Link); |
||||
335 | $this->assertEquals(302, $ham->getStatusCode()); |
||||
336 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
337 | $this->assertEquals(0, $check->IsSpam); |
||||
338 | |||||
339 | // Cannot re-ham hammed comment |
||||
340 | $this->assertNull($check->HamLink()); |
||||
341 | } |
||||
342 | |||||
343 | public function testApproveComment() |
||||
344 | { |
||||
345 | // Test anonymous user |
||||
346 | $this->logOut(); |
||||
347 | $comment = $this->objFromFixture(Comment::class, 'secondComB'); |
||||
348 | $commentID = $comment->ID; |
||||
349 | $this->assertNull($comment->ApproveLink(), 'No permission to see approve link'); |
||||
350 | $approve = $this->get('comments/approve/' . $comment->ID . '?ajax=1'); |
||||
351 | $this->assertEquals(403, $approve->getStatusCode()); |
||||
352 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
353 | $this->assertEquals(0, $check->Moderated, 'No permission to approve'); |
||||
354 | |||||
355 | // Test non-authenticated user |
||||
356 | $this->logInAs('visitor'); |
||||
357 | $this->assertNull($comment->ApproveLink(), 'No permission to see approve link'); |
||||
358 | |||||
359 | // Test authenticated user |
||||
360 | $this->logInAs('commentadmin'); |
||||
361 | $comment = $this->objFromFixture(Comment::class, 'secondComB'); |
||||
362 | $commentID = $comment->ID; |
||||
363 | $adminComment1Link = $comment->ApproveLink(); |
||||
364 | $this->assertContains('comments/approve/' . $commentID . '?t=', $adminComment1Link); |
||||
365 | |||||
366 | // Test that this link can't be shared / XSS exploited |
||||
367 | $this->logInAs('commentadmin2'); |
||||
368 | $approve = $this->get($adminComment1Link); |
||||
369 | $this->assertEquals(400, $approve->getStatusCode()); |
||||
370 | $check = DataObject::get_by_id(Comment::class, $comment->ID); |
||||
371 | $this->assertEquals(0, $check->Moderated, 'No permission to approve'); |
||||
372 | |||||
373 | // Test that this other admin can approve the comment with their own link |
||||
374 | $adminComment2Link = $comment->ApproveLink(); |
||||
375 | $this->assertNotEquals($adminComment2Link, $adminComment1Link); |
||||
376 | $this->autoFollowRedirection = false; |
||||
377 | $approve = $this->get($adminComment2Link); |
||||
378 | $this->assertEquals(302, $approve->getStatusCode()); |
||||
379 | $check = DataObject::get_by_id(Comment::class, $commentID); |
||||
380 | $this->assertEquals(1, $check->Moderated); |
||||
381 | |||||
382 | // Cannot re-approve approved comment |
||||
383 | $this->assertNull($check->ApproveLink()); |
||||
384 | } |
||||
385 | |||||
386 | public function testCommenterURLWrite() |
||||
387 | { |
||||
388 | $comment = new Comment(); |
||||
389 | // We only care about the CommenterURL, so only set that |
||||
390 | // Check a http and https URL. Add more test urls here as needed. |
||||
391 | $protocols = [ |
||||
392 | 'Http', |
||||
393 | 'Https', |
||||
394 | ]; |
||||
395 | $url = '://example.com'; |
||||
396 | |||||
397 | foreach ($protocols as $protocol) { |
||||
398 | $comment->CommenterURL = $protocol . $url; |
||||
399 | // The protocol should stay as if, assuming it is valid |
||||
400 | $comment->write(); |
||||
401 | $this->assertEquals($comment->CommenterURL, $protocol . $url, $protocol . ':// is a valid protocol'); |
||||
402 | } |
||||
403 | } |
||||
404 | |||||
405 | public function testSanitizesWithAllowHtml() |
||||
406 | { |
||||
407 | if (!class_exists('\\HTMLPurifier')) { |
||||
408 | $this->markTestSkipped('HTMLPurifier class not found'); |
||||
409 | } |
||||
410 | |||||
411 | // Add p for paragraph |
||||
412 | // NOTE: The config method appears to append to the existing array |
||||
413 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
414 | 'html_allowed_elements' => ['p'], |
||||
415 | ]); |
||||
416 | |||||
417 | // Without HTML allowed |
||||
418 | $comment1 = new Comment(); |
||||
419 | $comment1->AllowHtml = false; |
||||
420 | $comment1->ParentClass = CommentableItem::class; |
||||
421 | $comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>'; |
||||
422 | $comment1->write(); |
||||
423 | $this->assertEquals( |
||||
424 | '<p><script>alert("w00t")</script>my comment</p>', |
||||
425 | $comment1->Comment, |
||||
426 | 'Does not remove HTML tags with html_allowed=false, ' . |
||||
427 | 'which is correct behaviour because the HTML will be escaped' |
||||
428 | ); |
||||
429 | |||||
430 | // With HTML allowed |
||||
431 | $comment2 = new Comment(); |
||||
432 | $comment2->AllowHtml = true; |
||||
433 | $comment2->ParentClass = CommentableItem::class; |
||||
434 | $comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>'; |
||||
435 | $comment2->write(); |
||||
436 | $this->assertEquals( |
||||
437 | '<p>my comment</p>', |
||||
438 | $comment2->Comment, |
||||
439 | 'Removes HTML tags which are not on the whitelist' |
||||
440 | ); |
||||
441 | } |
||||
442 | |||||
443 | public function testDefaultTemplateRendersHtmlWithAllowHtml() |
||||
444 | { |
||||
445 | if (!class_exists('\\HTMLPurifier')) { |
||||
446 | $this->markTestSkipped('HTMLPurifier class not found'); |
||||
447 | } |
||||
448 | |||||
449 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
450 | 'html_allowed_elements' => ['p'], |
||||
451 | ]); |
||||
452 | |||||
453 | $item = new CommentableItem(); |
||||
454 | $item->write(); |
||||
455 | |||||
456 | // Without HTML allowed |
||||
457 | $comment = new Comment(); |
||||
458 | $comment->Comment = '<p>my comment</p>'; |
||||
459 | $comment->AllowHtml = false; |
||||
460 | $comment->ParentID = $item->ID; |
||||
461 | $comment->ParentClass = CommentableItem::class; |
||||
462 | $comment->write(); |
||||
463 | |||||
464 | $html = $item->customise(['CommentsEnabled' => true])->renderWith('CommentsInterface'); |
||||
465 | $this->assertContains( |
||||
466 | '<p>my comment</p>', |
||||
467 | $html |
||||
468 | ); |
||||
469 | |||||
470 | $comment->AllowHtml = true; |
||||
471 | $comment->write(); |
||||
472 | $html = $item->customise(['CommentsEnabled' => true])->renderWith('CommentsInterface'); |
||||
473 | $this->assertContains( |
||||
474 | '<p>my comment</p>', |
||||
475 | $html |
||||
476 | ); |
||||
477 | } |
||||
478 | |||||
479 | |||||
480 | /** |
||||
481 | * Tests whether comments are enabled or disabled by default |
||||
482 | */ |
||||
483 | public function testDefaultEnabled() |
||||
484 | { |
||||
485 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
486 | 'enabled_cms' => true, |
||||
487 | 'require_moderation_cms' => true, |
||||
488 | 'require_login_cms' => true, |
||||
489 | ]); |
||||
490 | |||||
491 | // With default = true |
||||
492 | $obj = new CommentableItem(); |
||||
493 | $this->assertTrue((bool)$obj->getCommentsOption('enabled'), "Default setting is enabled"); |
||||
494 | $this->assertTrue((bool)$obj->ProvideComments); |
||||
495 | $this->assertEquals('None', $obj->ModerationRequired); |
||||
496 | $this->assertFalse((bool)$obj->CommentsRequireLogin); |
||||
497 | |||||
498 | $obj = new CommentableItemEnabled(); |
||||
499 | $this->assertTrue((bool)$obj->ProvideComments); |
||||
500 | $this->assertEquals('Required', $obj->ModerationRequired); |
||||
501 | $this->assertTrue((bool)$obj->CommentsRequireLogin); |
||||
502 | |||||
503 | $obj = new CommentableItemDisabled(); |
||||
504 | $this->assertFalse((bool)$obj->ProvideComments); |
||||
505 | $this->assertEquals('None', $obj->ModerationRequired); |
||||
506 | $this->assertFalse((bool)$obj->CommentsRequireLogin); |
||||
507 | |||||
508 | // With default = false |
||||
509 | // Because of config rules about falsey values, apply config to object directly |
||||
510 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
511 | 'enabled' => false, |
||||
512 | 'require_login' => true, |
||||
513 | 'require_moderation' => true, |
||||
514 | ]); |
||||
515 | |||||
516 | $obj = new CommentableItem(); |
||||
517 | |||||
518 | $this->assertFalse((bool)$obj->getCommentsOption('enabled'), 'Default setting is disabled'); |
||||
519 | $this->assertFalse((bool)$obj->ProvideComments); |
||||
520 | $this->assertEquals('Required', $obj->ModerationRequired); |
||||
521 | $this->assertTrue((bool)$obj->CommentsRequireLogin); |
||||
522 | |||||
523 | $obj = new CommentableItemEnabled(); |
||||
524 | |||||
525 | $this->assertTrue((bool)$obj->ProvideComments); |
||||
526 | $this->assertEquals('Required', $obj->ModerationRequired); |
||||
527 | $this->assertTrue((bool)$obj->CommentsRequireLogin); |
||||
528 | |||||
529 | $obj = new CommentableItemDisabled(); |
||||
530 | |||||
531 | $this->assertFalse((bool)$obj->ProvideComments); |
||||
532 | $this->assertEquals('None', $obj->ModerationRequired); |
||||
533 | $this->assertFalse((bool)$obj->CommentsRequireLogin); |
||||
534 | } |
||||
535 | |||||
536 | public function testOnBeforeDelete() |
||||
537 | { |
||||
538 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
539 | |||||
540 | $child = new Comment(); |
||||
541 | $child->Name = 'Fred Bloggs'; |
||||
542 | $child->Comment = 'Child of firstComA'; |
||||
543 | $child->write(); |
||||
544 | $comment->ChildComments()->add($child); |
||||
545 | $this->assertEquals(4, $comment->ChildComments()->count()); |
||||
546 | |||||
547 | $commentID = $comment->ID; |
||||
548 | $childCommentID = $child->ID; |
||||
549 | |||||
550 | $comment->delete(); |
||||
551 | |||||
552 | // assert that the new child been deleted |
||||
553 | $this->assertNull(DataObject::get_by_id(Comment::class, $commentID)); |
||||
554 | $this->assertNull(DataObject::get_by_id(Comment::class, $childCommentID)); |
||||
555 | } |
||||
556 | |||||
557 | public function testRequireDefaultRecords() |
||||
558 | { |
||||
559 | $this->markTestSkipped('TODO'); |
||||
560 | } |
||||
561 | |||||
562 | public function testLink() |
||||
563 | { |
||||
564 | $comment = $this->objFromFixture(Comment::class, 'thirdComD'); |
||||
565 | $this->assertEquals( |
||||
566 | 'CommentableItemController#comment-' . $comment->ID, |
||||
567 | $comment->Link() |
||||
568 | ); |
||||
569 | $this->assertEquals($comment->ID, $comment->ID); |
||||
570 | |||||
571 | // An orphan comment has no link |
||||
572 | $comment->ParentID = 0; |
||||
573 | $comment->ParentClass = null; |
||||
574 | $comment->write(); |
||||
575 | $this->assertEquals('', $comment->Link()); |
||||
576 | } |
||||
577 | |||||
578 | public function testPermalink() |
||||
579 | { |
||||
580 | $comment = $this->objFromFixture(Comment::class, 'thirdComD'); |
||||
581 | $this->assertEquals('comment-' . $comment->ID, $comment->Permalink()); |
||||
582 | } |
||||
583 | |||||
584 | /** |
||||
585 | * Test field labels are defined |
||||
586 | */ |
||||
587 | public function testFieldLabels() |
||||
588 | { |
||||
589 | /** @var Comment $comment */ |
||||
590 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
591 | |||||
592 | $labels = $comment->FieldLabels(); |
||||
593 | $expected = [ |
||||
594 | 'Name', |
||||
595 | 'Comment', |
||||
596 | 'Email', |
||||
597 | 'URL', |
||||
598 | 'IsSpam', |
||||
599 | 'Moderated', |
||||
600 | 'ParentTitle', |
||||
601 | 'Created', |
||||
602 | ]; |
||||
603 | foreach ($expected as $key) { |
||||
604 | $this->assertArrayHasKey($key, $labels); |
||||
605 | } |
||||
606 | } |
||||
607 | |||||
608 | public function testGetParent() |
||||
609 | { |
||||
610 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
611 | $item = $this->objFromFixture(CommentableItem::class, 'first'); |
||||
612 | $parent = $comment->Parent(); |
||||
613 | $this->assertSame($item->getClassName(), $parent->getClassName()); |
||||
614 | $this->assertSame($item->ID, $parent->ID); |
||||
615 | } |
||||
616 | |||||
617 | public function testGetParentTitle() |
||||
618 | { |
||||
619 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
620 | $title = $comment->getParentTitle(); |
||||
621 | $this->assertEquals('First', $title); |
||||
622 | |||||
623 | // Title from a comment with no parent is blank |
||||
624 | $comment->ParentID = 0; |
||||
625 | $comment->ParentClass = null; |
||||
626 | $comment->write(); |
||||
627 | $this->assertEquals('', $comment->getParentTitle()); |
||||
628 | } |
||||
629 | |||||
630 | public function testGetParentClassName() |
||||
631 | { |
||||
632 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
633 | $className = $comment->getParentClassName(); |
||||
634 | $this->assertEquals(CommentableItem::class, $className); |
||||
635 | } |
||||
636 | |||||
637 | public function testCastingHelper() |
||||
638 | { |
||||
639 | $this->markTestSkipped('TODO'); |
||||
640 | } |
||||
641 | |||||
642 | public function testGetEscapedComment() |
||||
643 | { |
||||
644 | $this->markTestSkipped('TODO'); |
||||
645 | } |
||||
646 | |||||
647 | public function testIsPreview() |
||||
648 | { |
||||
649 | $comment = new Comment(); |
||||
650 | $comment->Name = 'Fred Bloggs'; |
||||
651 | $comment->Comment = 'this is a test comment'; |
||||
652 | $this->assertTrue($comment->isPreview()); |
||||
653 | $comment->write(); |
||||
654 | $this->assertFalse($comment->isPreview()); |
||||
655 | } |
||||
656 | |||||
657 | public function testCanCreate() |
||||
658 | { |
||||
659 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
660 | |||||
661 | // admin can create - this is always false |
||||
662 | $this->logInAs('commentadmin'); |
||||
663 | $this->assertFalse($comment->canCreate()); |
||||
664 | |||||
665 | // visitor can view |
||||
666 | $this->logInAs('visitor'); |
||||
667 | $this->assertFalse($comment->canCreate()); |
||||
668 | } |
||||
669 | |||||
670 | public function testCanView() |
||||
671 | { |
||||
672 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
673 | |||||
674 | // admin can view |
||||
675 | $this->logInAs('commentadmin'); |
||||
676 | $this->assertTrue($comment->canView()); |
||||
677 | |||||
678 | // visitor can view |
||||
679 | $this->logInAs('visitor'); |
||||
680 | $this->assertTrue($comment->canView()); |
||||
681 | |||||
682 | $comment->ParentID = 0; |
||||
683 | $comment->write(); |
||||
684 | $this->assertFalse($comment->canView()); |
||||
685 | } |
||||
686 | |||||
687 | public function testCanEdit() |
||||
688 | { |
||||
689 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
690 | |||||
691 | // admin can edit |
||||
692 | $this->logInAs('commentadmin'); |
||||
693 | $this->assertTrue($comment->canEdit()); |
||||
694 | |||||
695 | // visitor cannot |
||||
696 | $this->logInAs('visitor'); |
||||
697 | $this->assertFalse($comment->canEdit()); |
||||
698 | |||||
699 | $comment->ParentID = 0; |
||||
700 | $comment->write(); |
||||
701 | $this->assertFalse($comment->canEdit()); |
||||
702 | } |
||||
703 | |||||
704 | public function testCanDelete() |
||||
705 | { |
||||
706 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
707 | |||||
708 | // admin can delete |
||||
709 | $this->logInAs('commentadmin'); |
||||
710 | $this->assertTrue($comment->canDelete()); |
||||
711 | |||||
712 | // visitor cannot |
||||
713 | $this->logInAs('visitor'); |
||||
714 | $this->assertFalse($comment->canDelete()); |
||||
715 | |||||
716 | $comment->ParentID = 0; |
||||
717 | $comment->write(); |
||||
718 | $this->assertFalse($comment->canDelete()); |
||||
719 | } |
||||
720 | |||||
721 | public function testGetMember() |
||||
722 | { |
||||
723 | $this->logInAs('visitor'); |
||||
724 | $current = Security::getCurrentUser(); |
||||
725 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
726 | $method = $this->getMethod('getMember'); |
||||
727 | |||||
728 | // null case |
||||
729 | $member = $method->invokeArgs($comment, array()); |
||||
730 | $this->assertEquals($current->ID, $member->ID); |
||||
731 | |||||
732 | // numeric ID case |
||||
733 | $member = $method->invokeArgs($comment, array($current->ID)); |
||||
734 | $this->assertEquals($current->ID, $member->ID); |
||||
735 | |||||
736 | // identity case |
||||
737 | $member = $method->invokeArgs($comment, array($current)); |
||||
738 | $this->assertEquals($current->ID, $member->ID); |
||||
739 | } |
||||
740 | |||||
741 | public function testGetAuthorName() |
||||
742 | { |
||||
743 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
744 | $this->assertEquals( |
||||
745 | 'FA', |
||||
746 | $comment->getAuthorName() |
||||
747 | ); |
||||
748 | |||||
749 | $comment->Name = ''; |
||||
750 | $this->assertEquals( |
||||
751 | '', |
||||
752 | $comment->getAuthorName() |
||||
753 | ); |
||||
754 | |||||
755 | $author = $this->objFromFixture(Member::class, 'visitor'); |
||||
756 | $comment->AuthorID = $author->ID; |
||||
757 | $comment->write(); |
||||
758 | $this->assertEquals( |
||||
759 | 'visitor', |
||||
760 | $comment->getAuthorName() |
||||
761 | ); |
||||
762 | |||||
763 | // null the names, expect null back |
||||
764 | $comment->Name = null; |
||||
765 | $comment->AuthorID = 0; |
||||
766 | $this->assertNull($comment->getAuthorName()); |
||||
767 | } |
||||
768 | |||||
769 | |||||
770 | public function testLinks() |
||||
771 | { |
||||
772 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
773 | $this->logInAs('commentadmin'); |
||||
774 | |||||
775 | $method = $this->getMethod('ActionLink'); |
||||
776 | |||||
777 | // test with starts of strings and tokens and salts change each time |
||||
778 | $this->assertContains( |
||||
779 | '/comments/theaction/' . $comment->ID, |
||||
780 | $method->invokeArgs($comment, array('theaction')) |
||||
781 | ); |
||||
782 | |||||
783 | $this->assertContains( |
||||
784 | '/comments/delete/' . $comment->ID, |
||||
785 | $comment->DeleteLink() |
||||
786 | ); |
||||
787 | |||||
788 | $this->assertContains( |
||||
789 | '/comments/spam/' . $comment->ID, |
||||
790 | $comment->SpamLink() |
||||
791 | ); |
||||
792 | |||||
793 | $comment->markSpam(); |
||||
794 | $this->assertContains( |
||||
795 | '/comments/ham/' . $comment->ID, |
||||
796 | $comment->HamLink() |
||||
797 | ); |
||||
798 | |||||
799 | //markApproved |
||||
800 | $comment->markUnapproved(); |
||||
801 | $this->assertContains( |
||||
802 | '/comments/approve/' . $comment->ID, |
||||
803 | $comment->ApproveLink() |
||||
804 | ); |
||||
805 | } |
||||
806 | |||||
807 | public function testMarkSpam() |
||||
808 | { |
||||
809 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
810 | $comment->markSpam(); |
||||
811 | $this->assertTrue($comment->Moderated); |
||||
812 | $this->assertTrue($comment->IsSpam); |
||||
813 | } |
||||
814 | |||||
815 | public function testMarkApproved() |
||||
816 | { |
||||
817 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
818 | $comment->markApproved(); |
||||
819 | $this->assertTrue($comment->Moderated); |
||||
820 | $this->assertFalse($comment->IsSpam); |
||||
821 | } |
||||
822 | |||||
823 | public function testMarkUnapproved() |
||||
824 | { |
||||
825 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
826 | $comment->markApproved(); |
||||
827 | $this->assertTrue($comment->Moderated); |
||||
828 | } |
||||
829 | |||||
830 | public function testSpamClass() |
||||
831 | { |
||||
832 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
833 | $this->assertEquals('notspam', $comment->spamClass()); |
||||
834 | $comment->Moderated = false; |
||||
835 | $this->assertEquals('unmoderated', $comment->spamClass()); |
||||
836 | $comment->IsSpam = true; |
||||
837 | $this->assertEquals('spam', $comment->spamClass()); |
||||
838 | } |
||||
839 | |||||
840 | public function testGetTitle() |
||||
841 | { |
||||
842 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
843 | $this->assertEquals( |
||||
844 | 'Comment by FA on First', |
||||
845 | $comment->getTitle() |
||||
846 | ); |
||||
847 | } |
||||
848 | |||||
849 | public function testGetCMSFields() |
||||
850 | { |
||||
851 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
852 | $fields = $comment->getCMSFields(); |
||||
853 | $names = []; |
||||
854 | foreach ($fields as $field) { |
||||
855 | $names[] = $field->getName(); |
||||
856 | } |
||||
857 | $expected = [ |
||||
858 | 'Created', |
||||
859 | 'Name', |
||||
860 | 'Comment', |
||||
861 | 'Email', |
||||
862 | 'URL', |
||||
863 | 'Options', |
||||
864 | ]; |
||||
865 | $this->assertEquals($expected, $names); |
||||
866 | } |
||||
867 | |||||
868 | public function testGetCMSFieldsCommentHasAuthor() |
||||
869 | { |
||||
870 | $member = Member::get()->filter('FirstName', 'visitor')->first(); |
||||
871 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
872 | $comment->AuthorID = $member->ID; |
||||
873 | $comment->write(); |
||||
874 | |||||
875 | $fields = $comment->getCMSFields(); |
||||
876 | $names = []; |
||||
877 | foreach ($fields as $field) { |
||||
878 | $names[] = $field->getName(); |
||||
879 | } |
||||
880 | $expected = [ |
||||
881 | 'Created', |
||||
882 | 'Name', |
||||
883 | 'AuthorMember', |
||||
884 | 'Comment', |
||||
885 | 'Email', |
||||
886 | 'URL', |
||||
887 | 'Options', |
||||
888 | ]; |
||||
889 | $this->assertEquals($expected, $names); |
||||
890 | } |
||||
891 | |||||
892 | public function testGetCMSFieldsWithParentComment() |
||||
893 | { |
||||
894 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
895 | |||||
896 | $child = new Comment(); |
||||
897 | $child->Name = 'John Smith'; |
||||
898 | $child->Comment = 'This is yet another test commnent'; |
||||
899 | $child->ParentCommentID = $comment->ID; |
||||
900 | $child->write(); |
||||
901 | |||||
902 | $fields = $child->getCMSFields(); |
||||
903 | $names = []; |
||||
904 | foreach ($fields as $field) { |
||||
905 | $names[] = $field->getName(); |
||||
906 | } |
||||
907 | $expected = [ |
||||
908 | 'Created', |
||||
909 | 'Name', |
||||
910 | 'Comment', |
||||
911 | 'Email', |
||||
912 | 'URL', |
||||
913 | 'Options', |
||||
914 | 'ParentComment_Title', |
||||
915 | 'ParentComment_Created', |
||||
916 | 'ParentComment_AuthorName', |
||||
917 | 'ParentComment_EscapedComment', |
||||
918 | ]; |
||||
919 | $this->assertEquals($expected, $names); |
||||
920 | } |
||||
921 | |||||
922 | public function testPurifyHtml() |
||||
923 | { |
||||
924 | if (!class_exists(HTMLPurifier_Config::class)) { |
||||
925 | $this->markTestSkipped('HTMLPurifier class not found'); |
||||
926 | } |
||||
927 | |||||
928 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
929 | |||||
930 | $dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>'; |
||||
931 | $this->assertEquals( |
||||
932 | 'my comment', |
||||
933 | $comment->purifyHtml($dirtyHTML) |
||||
934 | ); |
||||
935 | } |
||||
936 | |||||
937 | public function testGravatar() |
||||
938 | { |
||||
939 | // Turn gravatars on |
||||
940 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
941 | 'use_gravatar' => true, |
||||
942 | 'gravatar_size' => 80, |
||||
943 | 'gravatar_default' => 'identicon', |
||||
944 | 'gravatar_rating' => 'g', |
||||
945 | ]); |
||||
946 | |||||
947 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
948 | |||||
949 | $this->assertEquals( |
||||
950 | 'https://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?s' |
||||
951 | . '=80&d=identicon&r=g', |
||||
952 | $comment->Gravatar() |
||||
953 | ); |
||||
954 | |||||
955 | // Turn gravatars off |
||||
956 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
957 | 'use_gravatar' => false, |
||||
958 | ]); |
||||
959 | |||||
960 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
961 | |||||
962 | $this->assertEquals( |
||||
963 | '', |
||||
964 | $comment->Gravatar() |
||||
965 | ); |
||||
966 | } |
||||
967 | |||||
968 | public function testGetRepliesEnabled() |
||||
969 | { |
||||
970 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
971 | 'nested_comments' => false, |
||||
972 | ]); |
||||
973 | |||||
974 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
975 | $this->assertFalse($comment->getRepliesEnabled()); |
||||
976 | |||||
977 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
978 | 'nested_comments' => true, |
||||
979 | 'nested_depth' => 4, |
||||
980 | ]); |
||||
981 | |||||
982 | $this->assertTrue($comment->getRepliesEnabled()); |
||||
983 | |||||
984 | $comment->Depth = 4; |
||||
985 | $this->assertFalse($comment->getRepliesEnabled()); |
||||
986 | |||||
987 | |||||
988 | // 0 indicates no limit for nested_depth |
||||
989 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
990 | 'nested_comments' => true, |
||||
991 | 'nested_depth' => 0, |
||||
992 | ]); |
||||
993 | |||||
994 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
995 | $comment->Depth = 234; |
||||
996 | |||||
997 | $comment->markUnapproved(); |
||||
998 | $this->assertFalse($comment->getRepliesEnabled()); |
||||
999 | |||||
1000 | $comment->markSpam(); |
||||
1001 | $this->assertFalse($comment->getRepliesEnabled()); |
||||
1002 | |||||
1003 | $comment->markApproved(); |
||||
1004 | $this->assertTrue($comment->getRepliesEnabled()); |
||||
1005 | } |
||||
1006 | |||||
1007 | public function testAllReplies() |
||||
1008 | { |
||||
1009 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1010 | 'nested_comments' => true, |
||||
1011 | 'nested_depth' => 4, |
||||
1012 | ]); |
||||
1013 | |||||
1014 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
1015 | |||||
1016 | $this->assertEquals( |
||||
1017 | 3, |
||||
1018 | $comment->allReplies()->count() |
||||
1019 | ); |
||||
1020 | |||||
1021 | $child = new Comment(); |
||||
1022 | $child->Name = 'Fred Smith'; |
||||
1023 | $child->Comment = 'This is a child comment'; |
||||
1024 | $child->ParentCommentID = $comment->ID; |
||||
1025 | |||||
1026 | // spam should be returned by this method |
||||
1027 | $child->markSpam(); |
||||
1028 | $child->write(); |
||||
1029 | $replies = $comment->allReplies(); |
||||
1030 | $this->assertEquals( |
||||
1031 | 4, |
||||
1032 | $comment->allReplies()->count() |
||||
1033 | ); |
||||
1034 | |||||
1035 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1036 | 'nested_comments' => false, |
||||
1037 | ]); |
||||
1038 | |||||
1039 | $this->assertEquals(0, $comment->allReplies()->count()); |
||||
1040 | } |
||||
1041 | |||||
1042 | public function testReplies() |
||||
1043 | { |
||||
1044 | CommentableItem::add_extension(CommentsExtension::class); |
||||
1045 | $this->logInWithPermission('ADMIN'); |
||||
1046 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1047 | 'nested_comments' => true, |
||||
1048 | 'nested_depth' => 4, |
||||
1049 | ]); |
||||
1050 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
1051 | $this->assertEquals( |
||||
1052 | 3, |
||||
1053 | $comment->Replies()->count() |
||||
1054 | ); |
||||
1055 | |||||
1056 | // Test that spam comments are not returned |
||||
1057 | $childComment = $comment->Replies()->first(); |
||||
1058 | $childComment->IsSpam = 1; |
||||
1059 | $childComment->write(); |
||||
1060 | $this->assertEquals( |
||||
1061 | 2, |
||||
1062 | $comment->Replies()->count() |
||||
1063 | ); |
||||
1064 | |||||
1065 | // Test that unmoderated comments are not returned |
||||
1066 | // |
||||
1067 | $childComment = $comment->Replies()->first(); |
||||
1068 | |||||
1069 | // FIXME - moderation settings scenarios need checked here |
||||
1070 | $childComment->Moderated = 0; |
||||
1071 | $childComment->IsSpam = 0; |
||||
1072 | $childComment->write(); |
||||
1073 | $this->assertEquals( |
||||
1074 | 2, |
||||
1075 | $comment->Replies()->count() |
||||
1076 | ); |
||||
1077 | |||||
1078 | |||||
1079 | // Test moderation required on the front end |
||||
1080 | $item = $this->objFromFixture(CommentableItem::class, 'first'); |
||||
1081 | $item->ModerationRequired = 'Required'; |
||||
1082 | $item->write(); |
||||
1083 | |||||
1084 | Config::modify()->merge(CommentableItemDisabled::class, 'comments', [ |
||||
1085 | 'nested_comments' => true, |
||||
1086 | 'nested_depth' => 4, |
||||
1087 | 'frontend_moderation' => true, |
||||
1088 | ]); |
||||
1089 | |||||
1090 | $comment = DataObject::get_by_id(Comment::class, $comment->ID); |
||||
1091 | |||||
1092 | $this->assertEquals( |
||||
1093 | 2, |
||||
1094 | $comment->Replies()->count() |
||||
1095 | ); |
||||
1096 | |||||
1097 | // Turn off nesting, empty array should be returned |
||||
1098 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1099 | 'nested_comments' => false, |
||||
1100 | ]); |
||||
1101 | |||||
1102 | $this->assertEquals( |
||||
1103 | 0, |
||||
1104 | $comment->Replies()->count() |
||||
1105 | ); |
||||
1106 | |||||
1107 | CommentableItem::remove_extension(CommentsExtension::class); |
||||
1108 | } |
||||
1109 | |||||
1110 | public function testPagedReplies() |
||||
1111 | { |
||||
1112 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1113 | 'nested_comments' => true, |
||||
1114 | 'nested_depth' => 4, |
||||
1115 | 'comments_per_page' => 2, |
||||
1116 | ]); |
||||
1117 | |||||
1118 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
1119 | $pagedList = $comment->pagedReplies(); |
||||
1120 | |||||
1121 | $this->assertEquals( |
||||
1122 | 2, |
||||
1123 | $pagedList->TotalPages() |
||||
1124 | ); |
||||
1125 | |||||
1126 | $this->assertEquals( |
||||
1127 | 3, |
||||
1128 | $pagedList->getTotalItems() |
||||
1129 | ); |
||||
1130 | |||||
1131 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1132 | 'nested_comments' => false, |
||||
1133 | ]); |
||||
1134 | |||||
1135 | $this->assertEquals(0, $comment->PagedReplies()->count()); |
||||
1136 | } |
||||
1137 | |||||
1138 | public function testReplyForm() |
||||
1139 | { |
||||
1140 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1141 | 'nested_comments' => false, |
||||
1142 | 'nested_depth' => 4, |
||||
1143 | ]); |
||||
1144 | |||||
1145 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
1146 | |||||
1147 | // No nesting, no reply form |
||||
1148 | $form = $comment->replyForm(); |
||||
1149 | $this->assertNull($form); |
||||
1150 | |||||
1151 | // parent item so show form |
||||
1152 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1153 | 'nested_comments' => true, |
||||
1154 | 'nested_depth' => 4, |
||||
1155 | ]); |
||||
1156 | $form = $comment->ReplyForm(); |
||||
1157 | $this->assertNotNull($form); |
||||
1158 | $names = []; |
||||
1159 | |||||
1160 | foreach ($form->Fields() as $field) { |
||||
1161 | array_push($names, $field->getName()); |
||||
1162 | } |
||||
1163 | |||||
1164 | $this->assertContains('NameEmailURLComment', $names, 'The CompositeField name'); |
||||
1165 | $this->assertContains('ParentID', $names); |
||||
1166 | $this->assertContains('ParentClassName', $names); |
||||
1167 | $this->assertContains('ReturnURL', $names); |
||||
1168 | $this->assertContains('ParentCommentID', $names); |
||||
1169 | |||||
1170 | // no parent, no reply form |
||||
1171 | |||||
1172 | $comment->ParentID = 0; |
||||
1173 | $comment->ParentClass = null; |
||||
1174 | $comment->write(); |
||||
1175 | $form = $comment->replyForm(); |
||||
1176 | $this->assertNull($form); |
||||
1177 | } |
||||
1178 | |||||
1179 | public function testUpdateDepth() |
||||
1180 | { |
||||
1181 | Config::modify()->merge(CommentableItem::class, 'comments', [ |
||||
1182 | 'nested_comments' => true, |
||||
1183 | 'nested_depth' => 4, |
||||
1184 | ]); |
||||
1185 | |||||
1186 | $comment = $this->objFromFixture(Comment::class, 'firstComA'); |
||||
1187 | $children = $comment->allReplies()->toArray(); |
||||
1188 | // Make the second child a child of the first |
||||
1189 | // Make the third child a child of the second |
||||
1190 | $reply1 = $children[0]; |
||||
1191 | $reply2 = $children[1]; |
||||
1192 | $reply3 = $children[2]; |
||||
1193 | $reply2->ParentCommentID = $reply1->ID; |
||||
1194 | $reply2->write(); |
||||
1195 | $this->assertEquals(3, $reply2->Depth); |
||||
1196 | $reply3->ParentCommentID = $reply2->ID; |
||||
1197 | $reply3->write(); |
||||
1198 | $this->assertEquals(4, $reply3->Depth); |
||||
1199 | } |
||||
1200 | |||||
1201 | public function testGetToken() |
||||
1202 | { |
||||
1203 | $this->markTestSkipped('TODO'); |
||||
1204 | } |
||||
1205 | |||||
1206 | public function testMemberSalt() |
||||
1207 | { |
||||
1208 | $this->markTestSkipped('TODO'); |
||||
1209 | } |
||||
1210 | |||||
1211 | public function testAddToUrl() |
||||
1212 | { |
||||
1213 | $this->markTestSkipped('TODO'); |
||||
1214 | } |
||||
1215 | |||||
1216 | public function testCheckRequest() |
||||
1217 | { |
||||
1218 | $this->markTestSkipped('TODO'); |
||||
1219 | } |
||||
1220 | |||||
1221 | public function testGenerate() |
||||
1222 | { |
||||
1223 | $this->markTestSkipped('TODO'); |
||||
1224 | } |
||||
1225 | |||||
1226 | protected static function getMethod($name) |
||||
1227 | { |
||||
1228 | $class = new ReflectionClass(Comment::class); |
||||
1229 | $method = $class->getMethod($name); |
||||
1230 | $method->setAccessible(true); |
||||
1231 | return $method; |
||||
1232 | } |
||||
1233 | } |
||||
1234 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths