Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core_search;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
require_once(__DIR__ . '/fixtures/testable_core_search.php');
22
require_once(__DIR__ . '/fixtures/mock_block_area.php');
23
 
24
/**
25
 * Unit tests for the base_block class.
26
 *
27
 * @package core_search
28
 * @copyright 2017 The Open University
29
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 */
31
class base_block_test extends \advanced_testcase {
32
    /**
33
     * Tests getting the name out of the class name.
34
     */
35
    public function test_get_block_name() {
36
        $area = new \block_mockblock\search\area();
37
        $this->assertEquals('mockblock', $area->get_block_name());
38
    }
39
 
40
    /**
41
     * Tests getting the recordset.
42
     */
43
    public function test_get_document_recordset() {
44
        global $DB, $USER;
45
 
46
        $this->resetAfterTest();
47
        $this->setAdminUser();
48
 
49
        // Create course and activity module.
50
        $generator = $this->getDataGenerator();
51
        $course = $generator->create_course();
52
        $coursecontext = \context_course::instance($course->id);
53
        $page = $generator->create_module('page', ['course' => $course->id]);
54
        $pagecontext = \context_module::instance($page->cmid);
55
 
56
        // Create another 2 courses (in same category and in a new category).
57
        $cat1context = \context_coursecat::instance($course->category);
58
        $course2 = $generator->create_course();
59
        $course2context = \context_course::instance($course2->id);
60
        $cat2 = $generator->create_category();
61
        $cat2context = \context_coursecat::instance($cat2->id);
62
        $course3 = $generator->create_course(['category' => $cat2->id]);
63
        $course3context = \context_course::instance($course3->id);
64
 
65
        // Add blocks by hacking table (because it's not a real block type).
66
 
67
        // 1. Block on course page.
68
        $configdata = base64_encode(serialize((object) ['example' => 'content']));
69
        $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id,
70
                'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*',
71
                'defaultweight' => 0, 'timecreated' => 1, 'timemodified' => 1,
72
                'configdata' => $configdata];
73
        $block1id = $DB->insert_record('block_instances', $instance);
74
        $block1context = \context_block::instance($block1id);
75
 
76
        // 2. Block on activity page.
77
        $instance->parentcontextid = $pagecontext->id;
78
        $instance->pagetypepattern = 'mod-page-view';
79
        $instance->timemodified = 2;
80
        $block2id = $DB->insert_record('block_instances', $instance);
81
        \context_block::instance($block2id);
82
 
83
        // 3. Block on site context.
84
        $sitecourse = get_site();
85
        $sitecontext = \context_course::instance($sitecourse->id);
86
        $instance->parentcontextid = $sitecontext->id;
87
        $instance->pagetypepattern = 'site-index';
88
        $instance->timemodified = 3;
89
        $block3id = $DB->insert_record('block_instances', $instance);
90
        $block3context = \context_block::instance($block3id);
91
 
92
        // 4. Block on course page but no data.
93
        $instance->parentcontextid = $coursecontext->id;
94
        $instance->pagetypepattern = 'course-view-*';
95
        unset($instance->configdata);
96
        $instance->timemodified = 4;
97
        $block4id = $DB->insert_record('block_instances', $instance);
98
        \context_block::instance($block4id);
99
 
100
        // 5. Block on course page but not this block.
101
        $instance->blockname = 'mockotherblock';
102
        $instance->configdata = $configdata;
103
        $instance->timemodified = 5;
104
        $block5id = $DB->insert_record('block_instances', $instance);
105
        \context_block::instance($block5id);
106
 
107
        // 6. Block on course page with '*' page type.
108
        $instance->blockname = 'mockblock';
109
        $instance->pagetypepattern = '*';
110
        $instance->timemodified = 6;
111
        $block6id = $DB->insert_record('block_instances', $instance);
112
        \context_block::instance($block6id);
113
 
114
        // 7. Block on course page with 'course-*' page type.
115
        $instance->pagetypepattern = 'course-*';
116
        $instance->timemodified = 7;
117
        $block7id = $DB->insert_record('block_instances', $instance);
118
        \context_block::instance($block7id);
119
 
120
        // 8. Block on course 2.
121
        $instance->parentcontextid = $course2context->id;
122
        $instance->timemodified = 8;
123
        $block8id = $DB->insert_record('block_instances', $instance);
124
        \context_block::instance($block8id);
125
 
126
        // 9. Block on course 3.
127
        $instance->parentcontextid = $course3context->id;
128
        $instance->timemodified = 9;
129
        $block9id = $DB->insert_record('block_instances', $instance);
130
        \context_block::instance($block9id);
131
 
132
        // Get all the blocks.
133
        $area = new \block_mockblock\search\area();
134
        $results = self::recordset_to_indexed_array($area->get_document_recordset());
135
 
136
        // Only blocks 1, 3, 6, 7, 8, 9 should be returned. Check all the fields for the first two.
137
        $this->assertCount(6, $results);
138
 
139
        $this->assertEquals($block1id, $results[0]->id);
140
        $this->assertEquals(1, $results[0]->timemodified);
141
        $this->assertEquals(1, $results[0]->timecreated);
142
        $this->assertEquals($configdata, $results[0]->configdata);
143
        $this->assertEquals($course->id, $results[0]->courseid);
144
        $this->assertEquals($block1context->id, $results[0]->contextid);
145
 
146
        $this->assertEquals($block3id, $results[1]->id);
147
        $this->assertEquals(3, $results[1]->timemodified);
148
        $this->assertEquals(1, $results[1]->timecreated);
149
        $this->assertEquals($configdata, $results[1]->configdata);
150
        $this->assertEquals($sitecourse->id, $results[1]->courseid);
151
        $this->assertEquals($block3context->id, $results[1]->contextid);
152
 
153
        // For the later ones, just check it got the right ones!
154
        $this->assertEquals($block6id, $results[2]->id);
155
        $this->assertEquals($block7id, $results[3]->id);
156
        $this->assertEquals($block8id, $results[4]->id);
157
        $this->assertEquals($block9id, $results[5]->id);
158
 
159
        // Repeat with a time restriction.
160
        $results = self::recordset_to_indexed_array($area->get_document_recordset(2));
161
 
162
        // Only block 3, 6, 7, 8, and 9 are returned.
163
        $this->assertEquals([$block3id, $block6id, $block7id, $block8id, $block9id],
164
                self::records_to_ids($results));
165
 
166
        // Now use context restrictions. First, the whole site (no change).
167
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
168
                0, \context_system::instance()));
169
        $this->assertEquals([$block1id, $block3id, $block6id, $block7id, $block8id, $block9id],
170
                self::records_to_ids($results));
171
 
172
        // Course page only (leave out the one on site page and other courses).
173
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
174
                0, $coursecontext));
175
        $this->assertEquals([$block1id, $block6id, $block7id],
176
                self::records_to_ids($results));
177
 
178
        // Other course page only.
179
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
180
                0, $course2context));
181
        $this->assertEquals([$block8id], self::records_to_ids($results));
182
 
183
        // Activity module only (no results).
184
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
185
                0, $pagecontext));
186
        $this->assertCount(0, $results);
187
 
188
        // Specific block context.
189
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
190
                0, $block3context));
191
        $this->assertEquals([$block3id], self::records_to_ids($results));
192
 
193
        // User context (no results).
194
        $usercontext = \context_user::instance($USER->id);
195
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
196
                0, $usercontext));
197
        $this->assertCount(0, $results);
198
 
199
        // Category 1 context (courses 1 and 2).
200
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
201
                0, $cat1context));
202
        $this->assertEquals([$block1id, $block6id, $block7id, $block8id],
203
                self::records_to_ids($results));
204
 
205
        // Category 2 context (course 3).
206
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
207
                0, $cat2context));
208
        $this->assertEquals([$block9id], self::records_to_ids($results));
209
 
210
        // Combine context restriction (category 1) with timemodified.
211
        $results = self::recordset_to_indexed_array($area->get_document_recordset(
212
                7, $cat1context));
213
        $this->assertEquals([$block7id, $block8id], self::records_to_ids($results));
214
    }
215
 
216
    /**
217
     * Utility function to convert recordset to array for testing.
218
     *
219
     * @param \moodle_recordset $rs Recordset to convert
220
     * @return array Array indexed by number (0, 1, 2, ...)
221
     */
222
    protected static function recordset_to_indexed_array(\moodle_recordset $rs) {
223
        $results = [];
224
        foreach ($rs as $rec) {
225
            $results[] = $rec;
226
        }
227
        $rs->close();
228
        return $results;
229
    }
230
 
231
    /**
232
     * Utility function to convert records to array of IDs.
233
     *
234
     * @param array $recs Records which should have an 'id' field
235
     * @return array Array of ids
236
     */
237
    protected static function records_to_ids(array $recs) {
238
        $ids = [];
239
        foreach ($recs as $rec) {
240
            $ids[] = $rec->id;
241
        }
242
        return $ids;
243
    }
244
 
245
    /**
246
     * Tests the get_doc_url function.
247
     */
248
    public function test_get_doc_url() {
249
        global $DB;
250
 
251
        $this->resetAfterTest();
252
 
253
        // Create course and activity module.
254
        $generator = $this->getDataGenerator();
255
        $course = $generator->create_course();
256
        $coursecontext = \context_course::instance($course->id);
257
        $page = $generator->create_module('page', ['course' => $course->id]);
258
        $pagecontext = \context_module::instance($page->cmid);
259
 
260
        // Create block on course page.
261
        $configdata = base64_encode(serialize(new \stdClass()));
262
        $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id,
263
                'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0,
264
                'timecreated' => 1, 'timemodified' => 1, 'configdata' => $configdata];
265
        $blockid = $DB->insert_record('block_instances', $instance);
266
 
267
        // Get document URL.
268
        $area = new \block_mockblock\search\area();
269
        $doc = $this->get_doc($course->id, $blockid);
270
        $expected = new \moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $blockid);
271
        $this->assertEquals($expected, $area->get_doc_url($doc));
272
        $this->assertEquals($expected, $area->get_context_url($doc));
273
 
274
        // Repeat with block on site page.
275
        $sitecourse = get_site();
276
        $sitecontext = \context_course::instance($sitecourse->id);
277
        $instance->pagetypepattern = 'site-index';
278
        $instance->parentcontextid = $sitecontext->id;
279
        $block2id = $DB->insert_record('block_instances', $instance);
280
 
281
        // Get document URL.
282
        $doc2 = $this->get_doc($course->id, $block2id);
283
        $expected = new \moodle_url('/', ['redirect' => 0], 'inst' . $block2id);
284
        $this->assertEquals($expected, $area->get_doc_url($doc2));
285
        $this->assertEquals($expected, $area->get_context_url($doc2));
286
 
287
        // Repeat with block on module page (this cannot happen yet because the search query will
288
        // only include course context blocks, but let's check it works for the future).
289
        $instance->pagetypepattern = 'mod-page-view';
290
        $instance->parentcontextid = $pagecontext->id;
291
        $block3id = $DB->insert_record('block_instances', $instance);
292
 
293
        // Get and check document URL, ignoring debugging message for unsupported page type.
294
        $debugmessage = 'Unexpected module-level page type for block ' . $block3id .
295
                ': mod-page-view';
296
        $doc3 = $this->get_doc($course->id, $block3id);
297
        $this->assertDebuggingCalledCount(2, [$debugmessage, $debugmessage]);
298
 
299
        $expected = new \moodle_url('/mod/page/view.php', ['id' => $page->cmid], 'inst' . $block3id);
300
        $this->assertEquals($expected, $area->get_doc_url($doc3));
301
        $this->assertDebuggingCalled($debugmessage);
302
        $this->assertEquals($expected, $area->get_context_url($doc3));
303
        $this->assertDebuggingCalled($debugmessage);
304
 
305
        // Repeat with another block on course page but '*' pages.
306
        $instance->pagetypepattern = '*';
307
        $instance->parentcontextid = $coursecontext->id;
308
        $block4id = $DB->insert_record('block_instances', $instance);
309
 
310
        // Get document URL.
311
        $doc = $this->get_doc($course->id, $block4id);
312
        $expected = new \moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $block4id);
313
        $this->assertEquals($expected, $area->get_doc_url($doc));
314
        $this->assertEquals($expected, $area->get_context_url($doc));
315
 
316
        // And same thing but 'course-*' pages.
317
        $instance->pagetypepattern = 'course-*';
318
        $block5id = $DB->insert_record('block_instances', $instance);
319
 
320
        // Get document URL.
321
        $doc = $this->get_doc($course->id, $block5id);
322
        $expected = new \moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $block5id);
323
        $this->assertEquals($expected, $area->get_doc_url($doc));
324
        $this->assertEquals($expected, $area->get_context_url($doc));
325
    }
326
 
327
    /**
328
     * Tests the check_access function.
329
     */
330
    public function test_check_access() {
331
        global $DB;
332
 
333
        $this->resetAfterTest();
334
 
335
        // Create course and activity module.
336
        $generator = $this->getDataGenerator();
337
        $course = $generator->create_course();
338
        $coursecontext = \context_course::instance($course->id);
339
        $page = $generator->create_module('page', ['course' => $course->id]);
340
        $pagecontext = \context_module::instance($page->cmid);
341
 
342
        // Create block on course page.
343
        $configdata = base64_encode(serialize(new \stdClass()));
344
        $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id,
345
                'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0,
346
                'timecreated' => 1, 'timemodified' => 1, 'configdata' => $configdata];
347
        $blockid = $DB->insert_record('block_instances', $instance);
348
 
349
        // Check access for block that exists.
350
        $area = new \block_mockblock\search\area();
351
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid));
352
 
353
        // Check access for nonexistent block.
354
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid + 1));
355
 
356
        // Check if block is not in a course context any longer.
357
        $DB->set_field('block_instances', 'parentcontextid', $pagecontext->id, ['id' => $blockid]);
358
        \core_search\base_block::clear_static();
359
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid));
360
 
361
        // Or what if it is in a course context but has supported vs. unsupported page type.
362
        $DB->set_field('block_instances', 'parentcontextid', $coursecontext->id, ['id' => $blockid]);
363
 
364
        $DB->set_field('block_instances', 'pagetypepattern', 'course-*', ['id' => $blockid]);
365
        \core_search\base_block::clear_static();
366
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid));
367
 
368
        $DB->set_field('block_instances', 'pagetypepattern', '*', ['id' => $blockid]);
369
        \core_search\base_block::clear_static();
370
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid));
371
 
372
        $DB->set_field('block_instances', 'pagetypepattern', 'course-view-frogs', ['id' => $blockid]);
373
        \core_search\base_block::clear_static();
374
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid));
375
 
376
        $DB->set_field('block_instances', 'pagetypepattern', 'anythingelse', ['id' => $blockid]);
377
        \core_search\base_block::clear_static();
378
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid));
379
    }
380
 
381
    /**
382
     * Tests the block version of get_contexts_to_reindex, which is supposed to return all the
383
     * block contexts in order of date added.
384
     */
385
    public function test_get_contexts_to_reindex() {
386
        global $DB;
387
 
388
        $this->resetAfterTest();
389
 
390
        // Create course and activity module.
391
        $generator = $this->getDataGenerator();
392
        $course = $generator->create_course();
393
        $coursecontext = \context_course::instance($course->id);
394
        $page = $generator->create_module('page', ['course' => $course->id]);
395
        $pagecontext = \context_module::instance($page->cmid);
396
 
397
        // Create blocks on course page, with time modified non-sequential.
398
        $configdata = base64_encode(serialize(new \stdClass()));
399
        $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id,
400
                'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0,
401
                'timecreated' => 1, 'timemodified' => 100, 'configdata' => $configdata];
402
        $blockid1 = $DB->insert_record('block_instances', $instance);
403
        $context1 = \context_block::instance($blockid1);
404
        $instance->timemodified = 120;
405
        $blockid2 = $DB->insert_record('block_instances', $instance);
406
        $context2 = \context_block::instance($blockid2);
407
        $instance->timemodified = 110;
408
        $blockid3 = $DB->insert_record('block_instances', $instance);
409
        $context3 = \context_block::instance($blockid3);
410
 
411
        // Create another block on the activity page (not included).
412
        $instance->parentcontextid = $pagecontext->id;
413
        $blockid4 = $DB->insert_record('block_instances', $instance);
414
        \context_block::instance($blockid4);
415
 
416
        // Check list of contexts.
417
        $area = new \block_mockblock\search\area();
418
        $contexts = iterator_to_array($area->get_contexts_to_reindex(), false);
419
        $expected = [
420
            $context2,
421
            $context3,
422
            $context1
423
        ];
424
        $this->assertEquals($expected, $contexts);
425
    }
426
 
427
    /**
428
     * Gets a search document object from the fake search area.
429
     *
430
     * @param int $courseid Course id in document
431
     * @param int $blockinstanceid Block instance id in document
432
     * @return \core_search\document Document object
433
     */
434
    protected function get_doc($courseid, $blockinstanceid) {
435
        $engine = \testable_core_search::instance()->get_engine();
436
        $area = new \block_mockblock\search\area();
437
        $docdata = ['id' => $blockinstanceid, 'courseid' => $courseid,
438
                'areaid' => $area->get_area_id(), 'itemid' => 0];
439
        return $engine->to_document($area, $docdata);
440
    }
441
 
442
    /**
443
     * Test document icon.
444
     */
445
    public function test_get_doc_icon() {
446
        $baseblock = $this->getMockBuilder('\core_search\base_block')
447
            ->disableOriginalConstructor()
448
            ->getMockForAbstractClass();
449
 
450
        $document = $this->getMockBuilder('\core_search\document')
451
            ->disableOriginalConstructor()
452
            ->getMock();
453
 
454
        $result = $baseblock->get_doc_icon($document);
455
 
456
        $this->assertEquals('e/anchor', $result->get_name());
457
        $this->assertEquals('moodle', $result->get_component());
458
    }
459
}