Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
/**
18
 * Unit tests for data_get_all_recordsids(), data_get_advance_search_ids(), data_get_record_ids(),
19
 * and data_get_advanced_search_sql()
20
 *
21
 * @package    mod_data
22
 * @category   phpunit
23
 * @copyright  2012 Adrian Greeve
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
 
27
namespace mod_data\search;
28
 
29
defined('MOODLE_INTERNAL') || die();
30
 
31
global $CFG;
32
require_once($CFG->dirroot . '/mod/data/lib.php');
33
require_once($CFG->dirroot . '/lib/datalib.php');
34
require_once($CFG->dirroot . '/lib/csvlib.class.php');
35
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
36
require_once($CFG->dirroot . '/mod/data/tests/generator/lib.php');
37
 
38
/**
39
 * Unit tests for {@see data_get_all_recordids()}.
40
 *                {@see data_get_advanced_search_ids()}
41
 *                {@see data_get_record_ids()}
42
 *                {@see data_get_advanced_search_sql()}
43
 *
44
 * @package    mod_data
45
 * @copyright  2012 Adrian Greeve
46
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
47
 */
48
class search_test extends \advanced_testcase {
49
    /**
50
     * @var stdObject $recorddata An object that holds information from the table data.
51
     */
52
    public $recorddata = null;
53
    /**
54
     * @var int $recordcontentid The content ID.
55
     */
56
    public $recordcontentid = null;
57
    /**
58
     * @var int $recordrecordid The record ID.
59
     */
60
    public $recordrecordid = null;
61
    /**
62
     * @var int $recordfieldid The field ID.
63
     */
64
    public $recordfieldid = null;
65
    /**
66
     * @var array $recordsearcharray An array of stdClass which contains search criteria.
67
     */
68
    public $recordsearcharray = null;
69
 
70
    // CONSTANTS
71
 
72
    /**
73
     * @var int $datarecordcount   The number of records in the database.
74
     */
75
    public $datarecordcount = 100;
76
 
77
    /**
78
     * @var int $groupdatarecordcount  The number of records in the database in groups 0 and 1.
79
     */
80
    public $groupdatarecordcount = 75;
81
 
82
    /**
83
     * @var array $datarecordset   Expected record IDs.
84
     */
85
    public $datarecordset = array('0' => '6');
86
 
87
    /**
88
     * @var array $finalrecord   Final record for comparison with test four.
89
     */
90
    public $finalrecord = array();
91
 
92
    /**
93
     * @var int $approvedatarecordcount  The number of approved records in the database.
94
     */
95
    public $approvedatarecordcount = 89;
96
 
97
    /**
98
     * @var string Area id
99
     */
100
    protected $databaseentryareaid = null;
101
 
102
    /**
103
     * Set up function. In this instance we are setting up database
104
     * records to be used in the unit tests.
105
     */
106
    protected function setUp(): void {
107
        global $DB, $CFG;
108
        parent::setUp();
109
 
110
        $this->resetAfterTest(true);
111
 
112
        set_config('enableglobalsearch', true);
113
 
114
        $this->databaseentryareaid = \core_search\manager::generate_areaid('mod_data', 'entry');
115
 
116
        // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
117
        $search = \testable_core_search::instance();
118
 
119
    }
120
 
121
    /**
122
     * Test 1: The function data_get_all_recordids.
123
     *
124
     * Test 2: This tests the data_get_advance_search_ids() function. The function takes a set
125
     * of all the record IDs in the database and then with the search details ($this->recordsearcharray)
126
     * returns a comma seperated string of record IDs that match the search criteria.
127
     *
128
     * Test 3: This function tests data_get_recordids(). This is the function that is nested in the last
129
     * function (see data_get_advance_search_ids). This function takes a couple of
130
     * extra parameters. $alias is the field alias used in the sql query and $commaid
131
     * is a comma seperated string of record IDs.
132
     *
133
     * Test 3.1: This tests that if no recordids are provided (In a situation where a search is done on an empty database)
134
     * That an empty array is returned.
135
     *
136
     * Test 4: data_get_advanced_search_sql provides an array which contains an sql string to be used for displaying records
137
     * to the user when they use the advanced search criteria and the parameters that go with the sql statement. This test
138
     * takes that information and does a search on the database, returning a record.
139
     *
140
     * Test 5: Returning to data_get_all_recordids(). Here we are ensuring that the total amount of record ids is reduced to
141
     * match the group conditions that are provided. There are 25 entries which relate to group 2. They are removed
142
     * from the total so we should only have 75 records total.
143
     *
144
     * Test 6: data_get_all_recordids() again. This time we are testing approved database records. We only want to
145
     * display the records that have been approved. In this record set we have 89 approved records.
146
     */
11 efrain 147
    public function test_advanced_search_sql_section(): void {
1 efrain 148
        global $DB;
149
 
150
        // we already have 2 users, we need 98 more - let's ignore the fact that guest can not post anywhere
151
        // We reset the user sequence here to ensure we get the expected numbers.
152
        // TODO: Invent a better way for managing data file input against database sequence id's.
153
        $DB->get_manager()->reset_sequence('user');
154
        for($i=3;$i<=100;$i++) {
155
            $this->getDataGenerator()->create_user();
156
        }
157
 
158
        // create database module - there should be more of these I guess
159
        $course = $this->getDataGenerator()->create_course();
160
        $data = $this->getDataGenerator()->create_module('data', array('course'=>$course->id));
161
        $this->recorddata = $data;
162
 
163
        // Set up data for the test database.
164
        $files = array(
165
                'data_fields'  => __DIR__.'/../fixtures/test_data_fields.csv',
166
                'data_records' => __DIR__.'/../fixtures/test_data_records.csv',
167
                'data_content' => __DIR__.'/../fixtures/test_data_content.csv',
168
        );
169
        $this->dataset_from_files($files)->to_database();
170
        // Set dataid to the correct value now the data has been inserted by csv file.
171
        $DB->execute('UPDATE {data_fields} SET dataid = ?', array($data->id));
172
        $DB->execute('UPDATE {data_records} SET dataid = ?', array($data->id));
173
 
174
        // Create the search array which contains our advanced search criteria.
175
        $fieldinfo = array('0' => new \stdClass(),
176
                '1' => new \stdClass(),
177
                '2' => new \stdClass(),
178
                '3' => new \stdClass(),
179
                '4' => new \stdClass());
180
        $fieldinfo['0']->id = 1;
181
        $fieldinfo['0']->data = '3.721,46.6126';
182
        $fieldinfo['1']->id = 2;
183
        $fieldinfo['1']->data = 'Hahn Premium';
184
        $fieldinfo['2']->id = 5;
185
        $fieldinfo['2']->data = 'Female';
186
        $fieldinfo['3']->id = 7;
187
        $fieldinfo['3']->data = 'kel';
188
        $fieldinfo['4']->id = 9;
189
        $fieldinfo['4']->data = 'VIC';
190
 
191
        foreach($fieldinfo as $field) {
192
            $searchfield = data_get_field_from_id($field->id, $data);
193
            if ($field->id == 2) {
194
                $searchfield->field->param1 = 'Hahn Premium';
195
                $val = array();
196
                $val['selected'] = array('0' => 'Hahn Premium');
197
                $val['allrequired'] = 0;
198
            } else {
199
                $val = $field->data;
200
            }
201
            $search_array[$field->id] = new \stdClass();
202
            list($search_array[$field->id]->sql, $search_array[$field->id]->params) = $searchfield->generate_sql('c' . $field->id, $val);
203
        }
204
 
205
        $this->recordsearcharray = $search_array;
206
 
207
        // Setting up the comparison stdClass for the last test.
208
        $user = $DB->get_record('user', array('id'=>6));
209
        $this->finalrecord[6] = new \stdClass();
210
        $this->finalrecord[6]->id = 6;
211
        $this->finalrecord[6]->approved = 1;
212
        $this->finalrecord[6]->timecreated = 1234567891;
213
        $this->finalrecord[6]->timemodified = 1234567892;
214
        $this->finalrecord[6]->userid = 6;
215
        $this->finalrecord[6]->firstname = $user->firstname;
216
        $this->finalrecord[6]->lastname = $user->lastname;
217
        $this->finalrecord[6]->firstnamephonetic = $user->firstnamephonetic;
218
        $this->finalrecord[6]->lastnamephonetic = $user->lastnamephonetic;
219
        $this->finalrecord[6]->middlename = $user->middlename;
220
        $this->finalrecord[6]->alternatename = $user->alternatename;
221
        $this->finalrecord[6]->picture = $user->picture;
222
        $this->finalrecord[6]->imagealt = $user->imagealt;
223
        $this->finalrecord[6]->email = $user->email;
224
 
225
        // Test 1
226
        $recordids = data_get_all_recordids($this->recorddata->id);
227
        $this->assertEquals(count($recordids), $this->datarecordcount);
228
 
229
        // Test 2
230
        $key = array_keys($this->recordsearcharray);
231
        $alias = $key[0];
232
        $newrecordids = data_get_recordids($alias, $this->recordsearcharray, $this->recorddata->id, $recordids);
233
        $this->assertEquals($this->datarecordset, $newrecordids);
234
 
235
        // Test 3
236
        $newrecordids = data_get_advance_search_ids($recordids, $this->recordsearcharray, $this->recorddata->id);
237
        $this->assertEquals($this->datarecordset, $newrecordids);
238
 
239
        // Test 3.1
240
        $resultrecordids = data_get_advance_search_ids(array(), $this->recordsearcharray, $this->recorddata->id);
241
        $this->assertEmpty($resultrecordids);
242
 
243
        // Test 4
244
        $sortorder = 'ORDER BY r.timecreated ASC , r.id ASC';
245
        $html = data_get_advanced_search_sql('0', $this->recorddata, $newrecordids, '', $sortorder);
246
        $allparams = array_merge($html['params'], array('dataid' => $this->recorddata->id));
247
        $records = $DB->get_records_sql($html['sql'], $allparams);
248
        $this->assertEquals($records, $this->finalrecord);
249
 
250
        // Test 5
251
        $groupsql = " AND (r.groupid = :currentgroup OR r.groupid = 0)";
252
        $params = array('currentgroup' => 1);
253
        $recordids = data_get_all_recordids($this->recorddata->id, $groupsql, $params);
254
        $this->assertEquals($this->groupdatarecordcount, count($recordids));
255
 
256
        // Test 6
257
        $approvesql = ' AND r.approved=1 ';
258
        $recordids = data_get_all_recordids($this->recorddata->id, $approvesql, $params);
259
        $this->assertEquals($this->approvedatarecordcount, count($recordids));
260
    }
261
 
11 efrain 262
    public function test_advanced_search_tags(): void {
1 efrain 263
        $this->resetAfterTest();
264
        $this->setAdminUser();
265
 
266
        // Setup test data.
267
        $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data');
268
        $course1 = $this->getDataGenerator()->create_course();
269
 
270
        $fieldrecord = new \stdClass();
271
        $fieldrecord->name = 'field-1';
272
        $fieldrecord->type = 'text';
273
        $fieldrecord->titlefield = true;
274
 
275
        $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id, 'approval' => true));
276
        $field1 = $datagenerator->create_field($fieldrecord, $data1);
277
 
278
        $record11 = $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 0, ['Cats', 'Dogs']);
279
        $record12 = $datagenerator->create_entry($data1, [$field1->field->id => 'value12'], 0, ['Cats', 'mice']);
280
        $record13 = $datagenerator->create_entry($data1, [$field1->field->id => 'value13'], 0, ['Bats']);
281
 
282
        $searcharray = [];
283
        $searcharray[DATA_TAGS] = new \stdClass();
284
        $searcharray[DATA_TAGS]->params = [];
285
        $searcharray[DATA_TAGS]->rawtagnames = ['Cats'];
286
        $searcharray[DATA_TAGS]->sql = '';
287
 
288
        $recordids = data_get_all_recordids($data1->id);
289
        $newrecordids = data_get_advance_search_ids($recordids, $searcharray, $data1->id);
290
 
291
        $this->assertContainsEquals($record11, $newrecordids);
292
        $this->assertContainsEquals($record12, $newrecordids);
293
        $this->assertNotContainsEquals($record13, $newrecordids);
294
    }
295
 
296
    /**
297
     * Indexing database entries contents.
298
     *
299
     * @return void
300
     */
11 efrain 301
    public function test_data_entries_indexing(): void {
1 efrain 302
        global $DB;
303
 
304
        // Returns the instance as long as the area is supported.
305
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
306
        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
307
 
308
        $user1 = self::getDataGenerator()->create_user();
309
 
310
        $course1 = self::getDataGenerator()->create_course();
311
 
312
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
313
 
314
        $record = new \stdClass();
315
        $record->course = $course1->id;
316
 
317
        $this->setUser($user1);
318
 
319
        // Available for both student and teacher.
320
        $data1 = $this->getDataGenerator()->create_module('data', $record);
321
 
322
        // Excluding LatLong and Picture as we aren't indexing LatLong and Picture fields any way
323
        // ...and they're complex and not of any use to consider for this test.
324
        // Excluding File as we are indexing files seperately and its complex to implement.
325
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
326
 
327
        $this->create_default_data_fields($fieldtypes, $data1);
328
 
329
        $data1record1id = $this->create_default_data_record($data1);
330
        // All records.
331
        $recordset = $searcharea->get_recordset_by_timestamp(0);
332
 
333
        $this->assertTrue($recordset->valid());
334
 
335
        $nrecords = 0;
336
        foreach ($recordset as $record) {
337
            $this->assertInstanceOf('stdClass', $record);
338
            $doc = $searcharea->get_document($record);
339
            $this->assertInstanceOf('\core_search\document', $doc);
340
            $nrecords++;
341
        }
342
 
343
        // If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
344
        $recordset->close();
345
        $this->assertEquals(1, $nrecords);
346
 
347
        // The +2 is to prevent race conditions.
348
        $recordset = $searcharea->get_recordset_by_timestamp(time() + 2);
349
 
350
        // No new records.
351
        $this->assertFalse($recordset->valid());
352
        $recordset->close();
353
 
354
        // Create a second database, also with one record.
355
        $data2 = $this->getDataGenerator()->create_module('data', ['course' => $course1->id]);
356
        $this->create_default_data_fields($fieldtypes, $data2);
357
        $this->create_default_data_record($data2);
358
 
359
        // Test indexing with contexts.
360
        $rs = $searcharea->get_document_recordset(0, \context_module::instance($data1->cmid));
361
        $this->assertEquals(1, iterator_count($rs));
362
        $rs->close();
363
        $rs = $searcharea->get_document_recordset(0, \context_module::instance($data2->cmid));
364
        $this->assertEquals(1, iterator_count($rs));
365
        $rs->close();
366
        $rs = $searcharea->get_document_recordset(0, \context_course::instance($course1->id));
367
        $this->assertEquals(2, iterator_count($rs));
368
        $rs->close();
369
    }
370
 
371
    /**
372
     * Document contents.
373
     *
374
     * @return void
375
     */
11 efrain 376
    public function test_data_entries_document(): void {
1 efrain 377
        global $DB;
378
 
379
        // Returns the instance as long as the area is supported.
380
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
381
        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
382
 
383
        $user1 = self::getDataGenerator()->create_user();
384
 
385
        $course = self::getDataGenerator()->create_course();
386
 
387
        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
388
 
389
        $record = new \stdClass();
390
        $record->course = $course->id;
391
 
392
        $this->setAdminUser();
393
 
394
        // First Case.
395
        $data1 = $this->getDataGenerator()->create_module('data', $record);
396
 
397
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
398
 
399
        $this->create_default_data_fields($fieldtypes, $data1);
400
 
401
        $data1record1id = $this->create_default_data_record($data1);
402
 
403
        $data1entry1 = $this->get_entry_for_id($data1record1id);
404
 
405
        $data1doc = $searcharea->get_document($data1entry1);
406
 
407
        $this->assertEquals($data1doc->get('courseid'), $course->id);
408
        $this->assertEquals($data1doc->get('title'), 'text for testing');
409
        $this->assertEquals($data1doc->get('content'), 'menu1');
410
        $this->assertEquals($data1doc->get('description1'), 'radioopt1');
411
        $this->assertEquals($data1doc->get('description2'), 'opt1 opt2 opt3 opt4 multimenu1 multimenu2 multimenu3 multimenu4 text area testing http://example.url');
412
 
413
        // Second Case.
414
        $data2 = $this->getDataGenerator()->create_module('data', $record);
415
 
416
        $fieldtypes = array(
417
                array('checkbox', 1),
418
                array('textarea', 0),
419
                array('menu', 0),
420
                array('number', 1),
421
                array('url', 0),
422
                array('text', 0)
423
        );
424
 
425
        $this->create_default_data_fields($fieldtypes, $data2);
426
 
427
        $data2record1id = $this->create_default_data_record($data2);
428
 
429
        $data2entry1 = $this->get_entry_for_id($data2record1id);
430
 
431
        $data2doc = $searcharea->get_document($data2entry1);
432
 
433
        $this->assertEquals($data2doc->get('courseid'), $course->id);
434
        $this->assertEquals($data2doc->get('title'), 'opt1 opt2 opt3 opt4');
435
        $this->assertEquals($data2doc->get('content'), 'text for testing');
436
        $this->assertEquals($data2doc->get('description1'), 'menu1');
437
        $this->assertEquals($data2doc->get('description2'), 'text area testing http://example.url');
438
 
439
        // Third Case.
440
        $data3 = $this->getDataGenerator()->create_module('data', $record);
441
 
442
        $fieldtypes = array( 'url' );
443
 
444
        $this->create_default_data_fields($fieldtypes, $data3);
445
 
446
        $data3record1id = $this->create_default_data_record($data3);
447
 
448
        $data3entry1 = $this->get_entry_for_id($data3record1id);
449
 
450
        $this->assertFalse($searcharea->get_document($data3entry1));
451
 
452
        // Fourth Case.
453
        $data4 = $this->getDataGenerator()->create_module('data', $record);
454
 
455
        $fieldtypes = array( array('date', 1), array('text', 1));
456
 
457
        $this->create_default_data_fields($fieldtypes, $data4);
458
 
459
        $data4record1id = $this->create_default_data_record($data4);
460
 
461
        $data4entry1 = $this->get_entry_for_id($data4record1id);
462
 
463
        $this->assertFalse($searcharea->get_document($data4entry1));
464
 
465
        // Fifth Case.
466
        $data5 = $this->getDataGenerator()->create_module('data', $record);
467
 
468
        $fieldtypes = array(
469
                array('checkbox', 0),
470
                array('number', 1),
471
                array('text', 0),
472
                array('date', 1),
473
                array('textarea', 0),
474
                array('url', 1));
475
 
476
        $this->create_default_data_fields($fieldtypes, $data5);
477
 
478
        $data5record1id = $this->create_default_data_record($data5);
479
 
480
        $data5entry1 = $this->get_entry_for_id($data5record1id);
481
 
482
        $data5doc = $searcharea->get_document($data5entry1);
483
 
484
        $this->assertEquals($data5doc->get('courseid'), $course->id);
485
        $this->assertEquals($data5doc->get('title'), 'http://example.url');
486
        $this->assertEquals($data5doc->get('content'), 'text for testing');
487
        $this->assertEquals($data5doc->get('description1'), 'opt1 opt2 opt3 opt4');
488
        $this->assertEquals($data5doc->get('description2'), 'text area testing');
489
 
490
        // Sixth Case.
491
        $data6 = $this->getDataGenerator()->create_module('data', $record);
492
 
493
        $fieldtypes = array( array('date', 1), array('number', 1));
494
 
495
        $this->create_default_data_fields($fieldtypes, $data6);
496
 
497
        $data6record1id = $this->create_default_data_record($data6);
498
 
499
        $data6entry1 = $this->get_entry_for_id($data6record1id);
500
 
501
        $data6doc = $searcharea->get_document($data6entry1);
502
 
503
        $this->assertFalse($data6doc);
504
 
505
        // Seventh Case.
506
        $data7 = $this->getDataGenerator()->create_module('data', $record);
507
 
508
        $fieldtypes = array( array('date', 1), array('number', 1),
509
                array('text', 0), array('textarea', 0));
510
 
511
        $this->create_default_data_fields($fieldtypes, $data7);
512
 
513
        $data7record1id = $this->create_default_data_record($data7);
514
 
515
        $data7entry1 = $this->get_entry_for_id($data7record1id);
516
 
517
        $data7doc = $searcharea->get_document($data7entry1);
518
 
519
        $this->assertEquals($data7doc->get('courseid'), $course->id);
520
        $this->assertEquals($data7doc->get('title'), 'text for testing');
521
        $this->assertEquals($data7doc->get('content'), 'text area testing');
522
 
523
        // Eight Case.
524
        $data8 = $this->getDataGenerator()->create_module('data', $record);
525
 
526
        $fieldtypes = array('url', 'url', 'url', 'text');
527
 
528
        $this->create_default_data_fields($fieldtypes, $data8);
529
 
530
        $data8record1id = $this->create_default_data_record($data8);
531
 
532
        $data8entry1 = $this->get_entry_for_id($data8record1id);
533
 
534
        $data8doc = $searcharea->get_document($data8entry1);
535
 
536
        $this->assertEquals($data8doc->get('courseid'), $course->id);
537
        $this->assertEquals($data8doc->get('title'), 'text for testing');
538
        $this->assertEquals($data8doc->get('content'), 'http://example.url');
539
        $this->assertEquals($data8doc->get('description1'), 'http://example.url');
540
        $this->assertEquals($data8doc->get('description2'), 'http://example.url');
541
 
542
        // Ninth Case.
543
        $data9 = $this->getDataGenerator()->create_module('data', $record);
544
 
545
        $fieldtypes = array('radiobutton', 'menu', 'multimenu');
546
 
547
        $this->create_default_data_fields($fieldtypes, $data9);
548
 
549
        $data9record1id = $this->create_default_data_record($data9);
550
 
551
        $data9entry1 = $this->get_entry_for_id($data9record1id);
552
 
553
        $data9doc = $searcharea->get_document($data9entry1);
554
 
555
        $this->assertEquals($data9doc->get('courseid'), $course->id);
556
        $this->assertEquals($data9doc->get('title'), 'radioopt1');
557
        $this->assertEquals($data9doc->get('content'), 'menu1');
558
        $this->assertEquals($data9doc->get('description1'), 'multimenu1 multimenu2 multimenu3 multimenu4');
559
 
560
        // Tenth Case.
561
        $data10 = $this->getDataGenerator()->create_module('data', $record);
562
 
563
        $fieldtypes = array('checkbox', 'textarea', 'multimenu');
564
 
565
        $this->create_default_data_fields($fieldtypes, $data10);
566
 
567
        $data10record1id = $this->create_default_data_record($data10);
568
 
569
        $data10entry1 = $this->get_entry_for_id($data10record1id);
570
 
571
        $data10doc = $searcharea->get_document($data10entry1);
572
 
573
        $this->assertEquals($data10doc->get('courseid'), $course->id);
574
        $this->assertEquals($data10doc->get('title'), 'opt1 opt2 opt3 opt4');
575
        $this->assertEquals($data10doc->get('content'), 'text area testing');
576
        $this->assertEquals($data10doc->get('description1'), 'multimenu1 multimenu2 multimenu3 multimenu4');
577
 
578
    }
579
 
580
    /**
581
     * Group support for data entries.
582
     */
11 efrain 583
    public function test_data_entries_group_support(): void {
1 efrain 584
        global $DB;
585
 
586
        // Get the search area and test generators.
587
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
588
        $generator = $this->getDataGenerator();
589
        $datagenerator = $generator->get_plugin_generator('mod_data');
590
 
591
        // Create a course, a user, and two groups.
592
        $course = $generator->create_course();
593
        $user = $generator->create_user();
594
        $generator->enrol_user($user->id, $course->id, 'teacher');
595
        $group1 = $generator->create_group(['courseid' => $course->id]);
596
        $group2 = $generator->create_group(['courseid' => $course->id]);
597
 
598
        // Separate groups database.
599
        $data = self::getDataGenerator()->create_module('data', ['course' => $course->id,
600
                'groupmode' => SEPARATEGROUPS]);
601
        $fieldtypes = ['text', 'textarea'];
602
        $this->create_default_data_fields($fieldtypes, $data);
603
        $fields = $DB->get_records('data_fields', array('dataid' => $data->id));
604
        foreach ($fields as $field) {
605
            switch ($field->type) {
606
                case 'text' :
607
                    $textid = $field->id;
608
                    break;
609
                case 'textarea' :
610
                    $textareaid = $field->id;
611
                    break;
612
            }
613
        }
614
 
615
        // As admin, create entries with each group and all groups.
616
        $this->setAdminUser();
617
        $fieldvalues = [$textid => 'Title', $textareaid => 'Content'];
618
        $e1 = $datagenerator->create_entry($data, $fieldvalues, $group1->id);
619
        $e2 = $datagenerator->create_entry($data, $fieldvalues, $group2->id);
620
        $e3 = $datagenerator->create_entry($data, $fieldvalues);
621
 
622
        // Do the indexing of all 3 entries.
623
        $rs = $searcharea->get_recordset_by_timestamp(0);
624
        $results = [];
625
        foreach ($rs as $rec) {
626
            $results[$rec->id] = $rec;
627
        }
628
        $rs->close();
629
        $this->assertCount(3, $results);
630
 
631
        // Check each has the correct groupid.
632
        $doc = $searcharea->get_document($results[$e1]);
633
        $this->assertTrue($doc->is_set('groupid'));
634
        $this->assertEquals($group1->id, $doc->get('groupid'));
635
        $doc = $searcharea->get_document($results[$e2]);
636
        $this->assertTrue($doc->is_set('groupid'));
637
        $this->assertEquals($group2->id, $doc->get('groupid'));
638
        $doc = $searcharea->get_document($results[$e3]);
639
        $this->assertFalse($doc->is_set('groupid'));
640
 
641
        // While we're here, also test that the search area requests restriction by group.
642
        $modinfo = get_fast_modinfo($course);
643
        $this->assertTrue($searcharea->restrict_cm_access_by_group($modinfo->get_cm($data->cmid)));
644
 
645
        // In visible groups mode, it won't request restriction by group.
646
        set_coursemodule_groupmode($data->cmid, VISIBLEGROUPS);
647
        $modinfo = get_fast_modinfo($course);
648
        $this->assertFalse($searcharea->restrict_cm_access_by_group($modinfo->get_cm($data->cmid)));
649
    }
650
 
651
    /**
652
     * Document accesses.
653
     *
654
     * @return void
655
     */
11 efrain 656
    public function test_data_entries_access(): void {
1 efrain 657
        global $DB;
658
 
659
        // Returns the instance as long as the area is supported.
660
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
661
        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
662
 
663
        $user1 = self::getDataGenerator()->create_user();
664
        $user2 = self::getDataGenerator()->create_user();
665
        $user3 = self::getDataGenerator()->create_user();
666
        $userteacher1 = self::getDataGenerator()->create_user();
667
 
668
        $course1 = self::getDataGenerator()->create_course();
669
        $course2 = self::getDataGenerator()->create_course();
670
 
671
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student');
672
        $this->getDataGenerator()->enrol_user($user2->id, $course1->id, 'student');
673
        $this->getDataGenerator()->enrol_user($userteacher1->id, $course1->id, 'teacher');
674
 
675
        $this->getDataGenerator()->enrol_user($user3->id, $course2->id, 'student');
676
 
677
        $record = new \stdClass();
678
        $record->course = $course1->id;
679
 
680
        $this->setUser($userteacher1);
681
 
682
        $data1 = $this->getDataGenerator()->create_module('data', $record);
683
 
684
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
685
 
686
        $this->create_default_data_fields($fieldtypes, $data1);
687
 
688
        $this->setUser($user1);
689
        $data1record1id = $this->create_default_data_record($data1);
690
 
691
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
692
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
693
 
694
        $this->setUser($user2);
695
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
696
 
697
        $this->setUser($user3);
698
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data1record1id));
699
 
700
        $this->setUser($userteacher1);
701
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
702
 
703
        $this->setAdminUser();
704
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data1record1id));
705
 
706
        $this->setGuestUser();
707
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data1record1id));
708
 
709
        // Case with groups.
710
        $user1 = self::getDataGenerator()->create_user();
711
        $user2 = self::getDataGenerator()->create_user();
712
        $user3 = self::getDataGenerator()->create_user();
713
        $userteacher1 = self::getDataGenerator()->create_user();
714
 
715
        $course = self::getDataGenerator()->create_course(array('groupmode' => 1, 'groupmodeforce' => 1));
716
 
717
        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
718
        $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
719
        $this->getDataGenerator()->enrol_user($userteacher1->id, $course->id, 'teacher');
720
        $this->getDataGenerator()->enrol_user($user3->id, $course->id, 'student');
721
 
722
        $groupa = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupA'));
723
        $groupb = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'name' => 'groupB'));
724
 
725
        $this->getDataGenerator()->create_group_member(array('userid' => $user1->id, 'groupid' => $groupa->id));
726
        $this->getDataGenerator()->create_group_member(array('userid' => $user2->id, 'groupid' => $groupa->id));
727
        $this->getDataGenerator()->create_group_member(array('userid' => $userteacher1->id, 'groupid' => $groupa->id));
728
 
729
        $this->getDataGenerator()->create_group_member(array('userid' => $user3->id, 'groupid' => $groupb->id));
730
 
731
        $record = new \stdClass();
732
        $record->course = $course->id;
733
 
734
        $this->setUser($userteacher1);
735
 
736
        $data2 = $this->getDataGenerator()->create_module('data', $record);
737
 
738
        $cm = get_coursemodule_from_instance('data', $data2->id, $course->id);
739
        $cm->groupmode = '1';
740
        $cm->effectivegroupmode = '1';
741
 
742
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
743
 
744
        $this->create_default_data_fields($fieldtypes, $data2);
745
 
746
        $this->setUser($user1);
747
 
748
        $data2record1id = $this->create_default_data_record($data2, $groupa->id);
749
 
750
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
751
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
752
 
753
        $this->setUser($user2);
754
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
755
 
756
        $this->setUser($user3);
757
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data2record1id));
758
 
759
        $this->setUser($userteacher1);
760
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
761
 
762
        $this->setAdminUser();
763
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data2record1id));
764
 
765
        $this->setGuestUser();
766
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data2record1id));
767
 
768
        // Case with approval.
769
        $user1 = self::getDataGenerator()->create_user();
770
        $user2 = self::getDataGenerator()->create_user();
771
        $userteacher1 = self::getDataGenerator()->create_user();
772
 
773
        $course = self::getDataGenerator()->create_course();
774
 
775
        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
776
        $this->getDataGenerator()->enrol_user($user2->id, $course->id, 'student');
777
        $this->getDataGenerator()->enrol_user($userteacher1->id, $course->id, 'teacher');
778
 
779
        $record = new \stdClass();
780
        $record->course = $course->id;
781
 
782
        $this->setUser($userteacher1);
783
 
784
        $data3 = $this->getDataGenerator()->create_module('data', $record);
785
 
786
        $DB->update_record('data', array('id' => $data3->id, 'approval' => 1));
787
 
788
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
789
 
790
        $this->create_default_data_fields($fieldtypes, $data3);
791
 
792
        $this->setUser($user1);
793
 
794
        $data3record1id = $this->create_default_data_record($data3);
795
 
796
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
797
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
798
 
799
        $this->setUser($user2);
800
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
801
 
802
        $this->setUser($userteacher1);
803
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
804
 
805
        $this->setAdminUser();
806
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
807
 
808
        $this->setGuestUser();
809
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
810
 
811
        $DB->update_record('data_records', array('id' => $data3record1id, 'approved' => 1));
812
 
813
        $this->setUser($user1);
814
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
815
        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-1));
816
 
817
        $this->setUser($user2);
818
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
819
 
820
        $this->setUser($userteacher1);
821
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
822
 
823
        $this->setAdminUser();
824
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data3record1id));
825
 
826
        $this->setGuestUser();
827
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data3record1id));
828
 
829
        // Case with requiredentriestoview.
830
        $this->setAdminUser();
831
 
832
        $record->requiredentriestoview = 2;
833
 
834
        $data4 = $this->getDataGenerator()->create_module('data', $record);
835
        $fieldtypes = array( 'checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url' );
836
 
837
        $this->create_default_data_fields($fieldtypes, $data4);
838
 
839
        $data4record1id = $this->create_default_data_record($data4);
840
 
841
        $this->setUser($user1);
842
        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($data4record1id));
843
 
844
        $data4record2id = $this->create_default_data_record($data4);
845
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data4record1id));
846
        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($data4record2id));
847
    }
848
 
849
    /**
850
     * Test for file contents.
851
     *
852
     * @return void
853
     */
11 efrain 854
    public function test_attach_files(): void {
1 efrain 855
        global $DB, $USER;
856
 
857
        $fs = get_file_storage();
858
 
859
        // Returns the instance as long as the area is supported.
860
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
861
        $this->assertInstanceOf('\mod_data\search\entry', $searcharea);
862
 
863
        $user1 = self::getDataGenerator()->create_user();
864
 
865
        $course = self::getDataGenerator()->create_course();
866
 
867
        $this->getDataGenerator()->enrol_user($user1->id, $course->id, 'student');
868
 
869
        $record = new \stdClass();
870
        $record->course = $course->id;
871
 
872
        $this->setAdminUser();
873
 
874
        // Creating database activity instance.
875
        $data1 = $this->getDataGenerator()->create_module('data', $record);
876
 
877
        // Creating file field.
878
        $record = new \stdClass;
879
        $record->type = 'file';
880
        $record->dataid = $data1->id;
881
        $record->required = 0;
882
        $record->name = 'FileFld';
883
        $record->description = 'Just another file field';
884
        $record->param3 = 0;
885
        $record->param1 = '';
886
        $record->param2 = '';
887
 
888
        $data1filefieldid = $DB->insert_record('data_fields', $record);
889
 
890
        // Creating text field.
891
        $record = new \stdClass;
892
        $record->type = 'text';
893
        $record->dataid = $data1->id;
894
        $record->required = 0;
895
        $record->name = 'TextFld';
896
        $record->description = 'Just another text field';
897
        $record->param3 = 0;
898
        $record->param1 = '';
899
        $record->param2 = '';
900
 
901
        $data1textfieldid = $DB->insert_record('data_fields', $record);
902
 
903
        // Creating textarea field.
904
        $record = new \stdClass;
905
        $record->type = 'textarea';
906
        $record->dataid = $data1->id;
907
        $record->required = 0;
908
        $record->name = 'TextAreaFld';
909
        $record->description = 'Just another textarea field';
910
        $record->param1 = '';
911
        $record->param2 = 60;
912
        $record->param3 = 35;
913
        $record->param3 = 1;
914
        $record->param3 = 0;
915
 
916
        $data1textareafieldid = $DB->insert_record('data_fields', $record);
917
 
918
        // Creating 1st entry.
919
        $record = new \stdClass;
920
        $record->userid = $USER->id;
921
        $record->dataid = $data1->id;
922
        $record->groupid = 0;
923
 
924
        $data1record1id = $DB->insert_record('data_records', $record);
925
 
926
        $record = new \stdClass;
927
        $record->fieldid = $data1filefieldid;
928
        $record->recordid = $data1record1id;
929
        $record->content = 'myfile1.txt';
930
        $data1contentfileid1 = $DB->insert_record('data_content', $record);
931
 
932
        $filerecord = [
933
            'contextid' => \context_module::instance($data1->cmid)->id,
934
            'component' => 'mod_data',
935
            'filearea'  => 'content',
936
            'itemid'    => $data1contentfileid1,
937
            'filepath'  => '/',
938
            'filename'  => 'myfile1.txt'
939
        ];
940
 
941
        $data1record1file = $fs->create_file_from_string($filerecord, 'Some contents 1');
942
 
943
        $record = new \stdClass;
944
        $record->fieldid = $data1textfieldid;
945
        $record->recordid = $data1record1id;
946
        $record->content = 'sample text';
947
        $DB->insert_record('data_content', $record);
948
 
949
        $record = new \stdClass;
950
        $record->fieldid = $data1textareafieldid;
951
        $record->recordid = $data1record1id;
952
        $record->content = '<br>sample text<p /><br/>';
953
        $record->content1 = 1;
954
        $DB->insert_record('data_content', $record);
955
 
956
        // Creating 2nd entry.
957
        $record = new \stdClass;
958
        $record->userid = $USER->id;
959
        $record->dataid = $data1->id;
960
        $record->groupid = 0;
961
        $data1record2id = $DB->insert_record('data_records', $record);
962
 
963
        $record = new \stdClass;
964
        $record->fieldid = $data1filefieldid;
965
        $record->recordid = $data1record2id;
966
        $record->content = 'myfile2.txt';
967
        $data1contentfileid2 = $DB->insert_record('data_content', $record);
968
 
969
        $filerecord['itemid'] = $data1contentfileid2;
970
        $filerecord['filename'] = 'myfile2.txt';
971
        $data1record2file = $fs->create_file_from_string($filerecord, 'Some contents 2');
972
 
973
        $record = new \stdClass;
974
        $record->fieldid = $data1textfieldid;
975
        $record->recordid = $data1record2id;
976
        $record->content = 'sample text';
977
        $DB->insert_record('data_content', $record);
978
 
979
        $record = new \stdClass;
980
        $record->fieldid = $data1textareafieldid;
981
        $record->recordid = $data1record2id;
982
        $record->content = '<br>sample text<p /><br/>';
983
        $record->content1 = 1;
984
        $DB->insert_record('data_content', $record);
985
 
986
        // Now get all the posts and see if they have the right files attached.
987
        $searcharea = \core_search\manager::get_search_area($this->databaseentryareaid);
988
        $recordset = $searcharea->get_recordset_by_timestamp(0);
989
        $nrecords = 0;
990
        foreach ($recordset as $record) {
991
            $doc = $searcharea->get_document($record);
992
            $searcharea->attach_files($doc);
993
            $files = $doc->get_files();
994
            // Now check that each doc has the right files on it.
995
            switch ($doc->get('itemid')) {
996
                case ($data1record1id):
997
                    $this->assertCount(1, $files);
998
                    $this->assertEquals($data1record1file->get_id(), $files[$data1record1file->get_id()]->get_id());
999
                    break;
1000
                case ($data1record2id):
1001
                    $this->assertCount(1, $files);
1002
                    $this->assertEquals($data1record2file->get_id(), $files[$data1record2file->get_id()]->get_id());
1003
                    break;
1004
                default:
1005
                    $this->fail('Unexpected entry returned');
1006
                    break;
1007
            }
1008
            $nrecords++;
1009
        }
1010
        $recordset->close();
1011
        $this->assertEquals(2, $nrecords);
1012
    }
1013
 
1014
    /**
1015
     * Creates default fields for a database instance
1016
     *
1017
     * @param array $fieldtypes
1018
     * @param mod_data $data
1019
     * @return void
1020
     */
1021
    protected function create_default_data_fields($fieldtypes, $data) {
1022
        $count = 1;
1023
 
1024
        // Creating test Fields with default parameter values.
1025
        foreach ($fieldtypes as $fieldtype) {
1026
 
1027
            // Creating variables dynamically.
1028
            $fieldname = 'field-'.$count;
1029
            $record = new \stdClass();
1030
            $record->name = $fieldname;
1031
 
1032
            if (is_array($fieldtype)) {
1033
                $record->type = $fieldtype[0];
1034
                $record->required = $fieldtype[1];
1035
            } else {
1036
                $record->type = $fieldtype;
1037
                $record->required = 0;
1038
            }
1039
 
1040
            ${$fieldname} = $this->getDataGenerator()->get_plugin_generator('mod_data')->create_field($record, $data);
1041
            $count++;
1042
        }
1043
    }
1044
 
1045
    /**
1046
     * Creates default database entry content values for default field param values
1047
     *
1048
     * @param mod_data $data
1049
     * @param int $groupid
1050
     * @return int
1051
     */
1052
    protected function create_default_data_record($data, $groupid = 0) {
1053
        global $DB;
1054
 
1055
        $fields = $DB->get_records('data_fields', array('dataid' => $data->id));
1056
 
1057
        $fieldcontents = array();
1058
        foreach ($fields as $fieldrecord) {
1059
            switch ($fieldrecord->type) {
1060
                case 'checkbox':
1061
                    $fieldcontents[$fieldrecord->id] = array('opt1', 'opt2', 'opt3', 'opt4');
1062
                    break;
1063
 
1064
                case 'multimenu':
1065
                    $fieldcontents[$fieldrecord->id] = array('multimenu1', 'multimenu2', 'multimenu3', 'multimenu4');
1066
                    break;
1067
 
1068
                case 'date':
1069
                    $fieldcontents[$fieldrecord->id] = '27-07-2016';
1070
                    break;
1071
 
1072
                case 'menu':
1073
                    $fieldcontents[$fieldrecord->id] = 'menu1';
1074
                    break;
1075
 
1076
                case 'radiobutton':
1077
                    $fieldcontents[$fieldrecord->id] = 'radioopt1';
1078
                    break;
1079
 
1080
                case 'number':
1081
                    $fieldcontents[$fieldrecord->id] = '12345';
1082
                    break;
1083
 
1084
                case 'text':
1085
                    $fieldcontents[$fieldrecord->id] = 'text for testing';
1086
                    break;
1087
 
1088
                case 'textarea':
1089
                    $fieldcontents[$fieldrecord->id] = '<p>text area testing<br /></p>';
1090
                    break;
1091
 
1092
                case 'url':
1093
                    $fieldcontents[$fieldrecord->id] = array('example.url', 'sampleurl');
1094
                    break;
1095
 
1096
                default:
1097
                    $this->fail('Unexpected field type');
1098
                    break;
1099
            }
1100
 
1101
        }
1102
 
1103
        return $this->getDataGenerator()->get_plugin_generator('mod_data')->create_entry($data, $fieldcontents, $groupid);
1104
    }
1105
 
1106
    /**
1107
     * Creates default database entry content values for default field param values
1108
     *
1109
     * @param int $recordid
1110
     * @return stdClass
1111
     */
1112
    protected function get_entry_for_id($recordid ) {
1113
        global $DB;
1114
 
1115
        $sql = "SELECT dr.*, d.course
1116
                  FROM {data_records} dr
1117
                  JOIN {data} d ON d.id = dr.dataid
1118
                 WHERE dr.id = :drid";
1119
        return $DB->get_record_sql($sql, array('drid' => $recordid));
1120
    }
1121
 
1122
}