Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 173
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
phpbb_functional_mcp_main_test
0.00% covered (danger)
0.00%
0 / 173
0.00% covered (danger)
0.00%
0 / 8
552
0.00% covered (danger)
0.00%
0 / 1
 test_create_topics
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
2
 test_mcp_view_forum
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 mcp_view_forum_actions_data
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 test_mcp_view_forum_actions
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
30
 test_mcp_view_forum_permanently_delete_topic
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
 mcp_view_topic_actions_data
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 test_create_topic_with_replies
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 test_mcp_view_topic_actions
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 1
132
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14/**
15* @group functional
16*/
17class phpbb_functional_mcp_main_test extends phpbb_functional_test_case
18{
19    public function test_create_topics()
20    {
21        $this->add_lang(['acp/common', 'acp/forums', 'common']);
22        $this->login();
23        $this->admin_login();
24
25        $this->set_flood_interval(0);
26
27        // Create a forum to move topics around
28        $forum_name = 'MCP Test #1';
29        $crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}");
30        $form = $crawler->selectButton($this->lang('CREATE_FORUM'))->form([
31            'forum_name'    => $forum_name,
32        ]);
33        $crawler = self::submit($form);
34        $form = $crawler->selectButton($this->lang('SUBMIT'))->form([
35            'forum_parent_id'    => 1,
36            'forum_perm_from'    => 2,
37        ]);
38        $crawler = self::submit($form);
39        $this->assertContainsLang('FORUM_CREATED', $crawler->text());
40
41        // Create topics to test with
42        $post = [];
43        $post[] = $this->create_topic(2, 'Test Topic 3', 'Testing forum moderation actions from MCP/View forum page.');
44        $crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
45        $this->assertStringContainsString('Testing forum moderation actions from MCP/View forum page.', $crawler->filter('html')->text());
46
47        $post[] = $this->create_topic(2, 'Topic to merge with', 'Testing merge topics moderation actions from MCP/View forum page.');
48        $crawler = self::request('GET', "viewtopic.php?t={$post[1]['topic_id']}&sid={$this->sid}");
49        $this->assertStringContainsString('Testing merge topics moderation actions from MCP/View forum page.', $crawler->filter('html')->text());
50
51        $this->set_flood_interval(15);
52
53        return $post;
54}
55
56
57    /**
58     * @depends test_create_topics
59     */
60    public function test_mcp_view_forum($post)
61    {
62        $this->add_lang(['common']);
63        $this->login();
64
65        // Browse MCP main page from forum view (gives &f=2)
66        $crawler = self::request('GET', "viewforum.php?f=2&sid={$this->sid}");
67        $crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
68
69        // Test forum moderation page has a list of topics to select
70        $this->assertGreaterThanOrEqual(3, $crawler->filter('input[type=checkbox]')->count());
71
72        return $post;
73    }
74
75    public static function mcp_view_forum_actions_data()
76    {
77        // action, success message, require_confirmation
78        return [
79            ['delete_topic', 'TOPIC_DELETED_SUCCESS', true],
80            ['restore_topic', 'TOPIC_RESTORED_SUCCESS', true],
81            ['fork', 'TOPIC_FORKED_SUCCESS', true],
82            ['lock', 'TOPIC_LOCKED_SUCCESS', true],
83            ['unlock', 'TOPIC_UNLOCKED_SUCCESS', true],
84            ['resync', 'TOPIC_RESYNC_SUCCESS', false],
85            ['make_global', 'TOPIC_TYPE_CHANGED', true],
86            ['make_announce', 'TOPIC_TYPE_CHANGED', true],
87            ['make_sticky', 'TOPIC_TYPE_CHANGED', true],
88            ['make_normal', 'TOPIC_TYPE_CHANGED', true],
89            ['merge_topics', 'POSTS_MERGED_SUCCESS', true],
90            ['move', 'TOPIC_MOVED_SUCCESS', true],
91        ];
92    }
93
94    /**
95     * @depends test_mcp_view_forum
96     * @dataProvider mcp_view_forum_actions_data
97     */
98    public function test_mcp_view_forum_actions($action, $message, $require_confirmation, $post)
99    {
100        $topic_id_1 = $post[0]['topic_id'];
101        $topic_id_2 = $post[1]['topic_id'];
102
103        $this->add_lang(['common', 'mcp']);
104        $this->login();
105
106        $crawler = self::request('GET', "viewforum.php?f=2&sid={$this->sid}");
107        $crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
108
109        // Test actions
110        $form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
111            'action' => $action,
112            'topic_id_list' => [$action == 'move' ? $topic_id_2 : $topic_id_1], // while moving, topic_id_1 has been already merged into topic_id_2
113        ]);
114        $crawler = self::submit($form);
115
116        if ($require_confirmation)
117        {
118            if ($action == 'merge_topics')
119            {
120                // Merge topic_id_1 into topic_id_2
121                $select_for_merge_link = $crawler->selectLink($this->lang('SELECT_MERGE'))->reduce(
122                    function ($node, $i) use ($topic_id_2)
123                    {
124                        return (bool) strpos($node->attr('href'), "to_topic_id=$topic_id_2");
125                    }
126                )->link();
127
128                $crawler = self::$client->click($select_for_merge_link);
129            }
130
131            $form = $crawler->selectButton($this->lang('YES'))->form();
132
133            if (in_array($action, ['fork', 'move']))
134            {
135                // Fork or move the topic to the 'MCP Test #1'
136                $forum_id = $crawler->filter('select > option')->reduce(
137                    function ($node, $i)
138                    {
139                        return (bool) strpos($node->text(), 'MCP Test #1');
140                    }
141                )->attr('value');
142                $form['to_forum_id']->select($forum_id);
143            }
144
145            $crawler = self::submit($form);
146        }
147
148        $this->assertStringContainsString($this->lang($message), $crawler->filter('#message p')->text());
149    }
150
151    /**
152     * @depends test_mcp_view_forum_actions
153     */
154    public function test_mcp_view_forum_permanently_delete_topic()
155    {
156        $this->add_lang(['common', 'mcp']);
157        $this->login();
158
159        // Get to the forum 'MCP Test #1' where the topic has been moved to in previous test
160        $crawler = self::request('GET', "index.php?sid={$this->sid}");
161        $crawler = self::$client->click($crawler->selectLink('MCP Test #1')->link());
162        $crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
163
164        // Get topic ids to delete (forked and moved topics in the previous test)
165        $topic_link_1 = $crawler->selectLink('Test Topic 3')->attr('href');
166        $topic_link_2 = $crawler->selectLink('Topic to merge with')->attr('href');
167        $topic_ids = [
168            (int) $this->get_parameter_from_link($topic_link_1, 't'),
169            (int) $this->get_parameter_from_link($topic_link_2, 't'),
170        ];
171
172        $form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
173            'action' => 'delete_topic',
174            'topic_id_list' => $topic_ids, // tick both topics in the list
175        ]);
176        $crawler = self::submit($form);
177
178        $form = $crawler->selectButton($this->lang('YES'))->form();
179        $form['delete_permanent']->tick();
180        $crawler = self::submit($form);
181        $this->assertStringContainsString($this->lang('TOPICS_DELETED_SUCCESS'), $crawler->filter('#message p')->text());
182    }
183
184    public static function mcp_view_topic_actions_data()
185    {
186        // action, success message, require_confirmation
187        return [
188            ['lock_post', 'POSTS_LOCKED_SUCCESS', true],
189            ['unlock_post', 'POSTS_UNLOCKED_SUCCESS', true],
190            ['resync', 'TOPIC_RESYNC_SUCCESS', false],
191            ['split_all', 'TOPIC_SPLIT_SUCCESS', true],
192            ['split_beyond', 'TOPIC_SPLIT_SUCCESS', true],
193            ['merge_posts', 'POSTS_MERGED_SUCCESS', true],
194            ['delete_post', 'POSTS_DELETED_SUCCESS', true],
195        ];
196    }
197
198    public function test_create_topic_with_replies()
199    {
200        $this->login();
201
202        // Create topic and replies to test with
203        $post = [];
204        $post[] = $this->create_topic(2, 'Test Topic 4', 'Testing topic moderation actions from MCP/View topic page.');
205        $crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
206        $this->assertStringContainsString('Testing topic moderation actions from MCP/View topic page.', $crawler->filter('html')->text());
207
208        // Create replies. Flood control was disabled above
209        for ($i = 1; $i <= 15; $i++)
210        {
211            usleep(100000);
212            $post_text = "This is reply number $i to the Test Topic 4 to test moderation actions from MCP/View topic page.";
213            $post[$i] = $this->create_post(2, $post[0]['topic_id'], 'Re: Test Topic 4', $post_text);
214            $crawler = self::request('GET', "viewtopic.php?p={$post[$i]['post_id']}&sid={$this->sid}#p{$post[$i]['post_id']}");
215            $this->assertStringContainsString($post_text, $crawler->filter('html')->text());
216        }
217
218        return $post;
219    }
220
221    /**
222     * @depends test_create_topic_with_replies
223     * @dataProvider mcp_view_topic_actions_data
224     */
225    public function test_mcp_view_topic_actions($action, $message, $require_confirmation, $post)
226    {
227        $this->add_lang(['common', 'mcp']);
228        $this->login();
229
230        $crawler = self::request('GET', "viewtopic.php?t={$post[0]['topic_id']}&sid={$this->sid}");
231        $crawler = self::$client->click($crawler->selectLink($this->lang('MCP_SHORT'))->link());
232        $this->assertLessThanOrEqual(count($post), $crawler->filter('input[type=checkbox]')->count());
233
234        // Test actions
235        $form = $crawler->selectButton($this->lang('SUBMIT'))->form();
236
237        // Set posts to select for actions
238        $post_id_list = [];
239        switch ($action)
240        {
241            case 'lock_post':
242            case 'unlock_post':
243                $post_id_list = [$post[1]['post_id'], $post[2]['post_id']];
244            break;
245
246            case 'split_all':
247                $post_id_list = [$post[13]['post_id'], $post[14]['post_id'], $post[15]['post_id']]; // Split last 3 replies
248                $subject = '[Split] Topic 1';
249            break;
250
251            case 'split_beyond':
252                $post_id_list = [$post[10]['post_id']]; // Split from 10th reply
253                $subject = '[Split] Topic 2';
254            break;
255
256            case 'merge_posts':
257                $post_id_list = [$post[7]['post_id'], $post[8]['post_id'], $post[9]['post_id']]; // Split replies 7, 8, 9
258            break;
259
260            case 'delete_post':
261                $post_id_list = [$post[4]['post_id'], $post[5]['post_id'], $post[6]['post_id']]; // Delete posts 4, 5, 6
262            break;
263
264            default:
265            break;
266        }
267
268        $form->disableValidation()->setValues([
269            'action' => $action,
270            'post_id_list' => $post_id_list, // tick post ids
271        ]);
272        $crawler = self::submit($form);
273
274        if ($require_confirmation)
275        {
276            if ($action == 'merge_posts')
277            {
278                // Merge posts into '[Split] Topic 1'
279                // Get topics list to select from
280                $crawler = self::$client->click($crawler->selectLink($this->lang('SELECT_TOPIC'))->link());
281
282                // Get '[Split] Topic 1' topic_id
283                $to_topic_link = $crawler->selectLink('[Split] Topic 1')->attr('href');
284                $to_topic_id = (int) $this->get_parameter_from_link($to_topic_link, 't');
285                
286                // Select '[Split] Topic 1'
287                $select_for_merge_link = $crawler->selectLink($this->lang('SELECT_MERGE'))->reduce(
288                    function ($node, $i) use ($to_topic_id)
289                    {
290                        return (bool) strpos($node->attr('href'), "to_topic_id=$to_topic_id");
291                    }
292                )->link();
293
294                $crawler = self::$client->click($select_for_merge_link);
295
296                $this->assertEquals($to_topic_id, (int) $crawler->filter('#to_topic_id')->attr('value'));
297
298                // Reselect post ids to move
299                $form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues(['post_id_list' => $post_id_list]);
300                $crawler = self::submit($form);
301            }
302
303            if (in_array($action, ['split_all', 'split_beyond']))
304            {
305                $form = $crawler->selectButton($this->lang('SUBMIT'))->form()->disableValidation()->setValues([
306                    'subject' => $subject,
307                    'post_id_list' => $post_id_list, // tick post ids
308                    'to_forum_id' => 2,
309                ]);
310                $crawler = self::submit($form);    
311            }
312
313            $form = $crawler->selectButton($this->lang('YES'))->form();
314            $crawler = self::submit($form);
315        }
316
317        $this->assertStringContainsString($this->lang($message), $crawler->filter('#message p')->text());
318    }
319}