Proyectos de Subversion Moodle

Rev

| 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
 * A class for loading and preparing grade data from import.
19
 *
20
 * @package   gradeimport_csv
21
 * @copyright 2014 Adrian Greeve <adrian@moodle.com>
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
defined('MOODLE_INTERNAL') || die();
26
 
27
/**
28
 * A class for loading and preparing grade data from import.
29
 *
30
 * @package   gradeimport_csv
31
 * @copyright 2014 Adrian Greeve <adrian@moodle.com>
32
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 */
34
class gradeimport_csv_load_data {
35
 
36
    /** @var string $error csv import error. */
37
    protected $error;
38
    /** @var int $iid Unique identifier for these csv records. */
39
    protected $iid;
40
    /** @var array $headers Column names for the data. */
41
    protected $headers;
42
    /** @var array $previewdata A subsection of the csv imported data. */
43
    protected $previewdata;
44
 
45
    // The map_user_data_with_value variables.
46
    /** @var array $newgrades Grades to be inserted into the gradebook. */
47
    protected $newgrades;
48
    /** @var array $newfeedbacks Feedback to be inserted into the gradebook. */
49
    protected $newfeedbacks;
50
    /** @var int $studentid Student ID*/
51
    protected $studentid;
52
 
53
    // The prepare_import_grade_data() variables.
54
    /** @var bool $status The current status of the import. True = okay, False = errors. */
55
    protected $status;
56
    /** @var int $importcode The code for this batch insert. */
57
    protected $importcode;
58
    /** @var array $gradebookerrors An array of errors from trying to import into the gradebook. */
59
    protected $gradebookerrors;
60
    /** @var array $newgradeitems An array of new grade items to be inserted into the gradebook. */
61
    protected $newgradeitems;
62
 
63
    /**
64
     * Load CSV content for previewing.
65
     *
66
     * @param string $text The grade data being imported.
67
     * @param string $encoding The type of encoding the file uses.
68
     * @param string $separator The separator being used to define each field.
69
     * @param int $previewrows How many rows are being previewed.
70
     */
71
    public function load_csv_content($text, $encoding, $separator, $previewrows) {
72
        $this->raise_limits();
73
 
74
        $this->iid = csv_import_reader::get_new_iid('grade');
75
        $csvimport = new csv_import_reader($this->iid, 'grade');
76
 
77
        $csvimport->load_csv_content($text, $encoding, $separator);
78
        $this->error = $csvimport->get_error();
79
 
80
        // If there are no import errors then proceed.
81
        if (empty($this->error)) {
82
 
83
            // Get header (field names).
84
            $this->headers = $csvimport->get_columns();
85
            $this->trim_headers();
86
 
87
            $csvimport->init();
88
            $this->previewdata = array();
89
 
90
            for ($numlines = 0; $numlines <= $previewrows; $numlines++) {
91
                $lines = $csvimport->next();
92
                if ($lines) {
93
                    $this->previewdata[] = $lines;
94
                }
95
            }
96
        }
97
    }
98
 
99
    /**
100
     * Gets all of the grade items in this course.
101
     *
102
     * @param int $courseid Course id;
103
     * @return array An array of grade items for the course.
104
     */
105
    public static function fetch_grade_items($courseid) {
106
        $gradeitems = null;
107
        if ($allgradeitems = grade_item::fetch_all(array('courseid' => $courseid))) {
108
            foreach ($allgradeitems as $gradeitem) {
109
                // Skip course type and category type.
110
                if ($gradeitem->itemtype == 'course' || $gradeitem->itemtype == 'category') {
111
                    continue;
112
                }
113
 
114
                $displaystring = null;
115
                if (!empty($gradeitem->itemmodule)) {
116
                    $displaystring = get_string('modulename', $gradeitem->itemmodule).get_string('labelsep', 'langconfig')
117
                            .$gradeitem->get_name();
118
                } else {
119
                    $displaystring = $gradeitem->get_name();
120
                }
121
                $gradeitems[$gradeitem->id] = $displaystring;
122
            }
123
        }
124
        return $gradeitems;
125
    }
126
 
127
    /**
128
     * Cleans the column headers from the CSV file.
129
     */
130
    protected function trim_headers() {
131
        foreach ($this->headers as $i => $h) {
132
            $h = trim($h); // Remove whitespace.
133
            $h = clean_param($h, PARAM_RAW); // Clean the header.
134
            $this->headers[$i] = $h;
135
        }
136
    }
137
 
138
    /**
139
     * Raises the php execution time and memory limits for importing the CSV file.
140
     */
141
    protected function raise_limits() {
142
        // Large files are likely to take their time and memory. Let PHP know
143
        // that we'll take longer, and that the process should be recycled soon
144
        // to free up memory.
145
        core_php_time_limit::raise();
146
        raise_memory_limit(MEMORY_EXTRA);
147
    }
148
 
149
    /**
150
     * Inserts a record into the grade_import_values table. This also adds common record information.
151
     *
152
     * @param stdClass $record The grade record being inserted into the database.
153
     * @param int $studentid The student ID.
154
     * @param grade_item $gradeitem Grade item.
155
     * @return mixed true or insert id on success. Null if the grade value is too high or too low or grade item not exist.
156
     */
157
    protected function insert_grade_record(stdClass $record, int $studentid, grade_item $gradeitem): mixed {
158
        global $DB, $USER, $CFG;
159
        $record->importcode = $this->importcode;
160
        $record->userid     = $studentid;
161
        $record->importer   = $USER->id;
162
        // If the record final grade is set then check that the grade value isn't too high.
163
        // Final grade will not be set if we are inserting feedback.
164
        $gradepointmaximum = $gradeitem->grademax;
165
        $gradepointminimum = $gradeitem->grademin;
166
 
167
        $finalgradeinrange =
168
            isset($record->finalgrade) && $record->finalgrade <= $gradepointmaximum && $record->finalgrade >= $gradepointminimum;
169
        if (!isset($record->finalgrade) || $finalgradeinrange || $CFG->unlimitedgrades) {
170
            return $DB->insert_record('grade_import_values', $record);
171
        } else {
172
            if ($record->finalgrade > $gradepointmaximum) {
173
                $this->cleanup_import(get_string('gradevaluetoobig', 'grades', format_float($gradepointmaximum)));
174
            } else {
175
                $this->cleanup_import(get_string('gradevaluetoosmall', 'grades', format_float($gradepointminimum)));
176
            }
177
            return null;
178
        }
179
    }
180
 
181
    /**
182
     * Insert the new grade into the grade item buffer table.
183
     *
184
     * @param array $header The column headers from the CSV file.
185
     * @param int $key Current row identifier.
186
     * @param string $value The value for this row (final grade).
187
     * @return stdClass new grade that is ready for commiting to the gradebook.
188
     */
189
    protected function import_new_grade_item($header, $key, $value) {
190
        global $DB, $USER;
191
 
192
        // First check if header is already in temp database.
193
        if (empty($this->newgradeitems[$key])) {
194
 
195
            $newgradeitem = new stdClass();
196
            $newgradeitem->itemname = $header[$key];
197
            $newgradeitem->importcode = $this->importcode;
198
            $newgradeitem->importer = $USER->id;
199
 
200
            // Insert into new grade item buffer.
201
            $this->newgradeitems[$key] = $DB->insert_record('grade_import_newitem', $newgradeitem);
202
        }
203
        $newgrade = new stdClass();
204
        $newgrade->newgradeitem = $this->newgradeitems[$key];
205
 
206
        $trimmed = trim($value);
207
        if ($trimmed === '' or $trimmed == '-') {
208
            // Blank or dash grade means null, ie "no grade".
209
            $newgrade->finalgrade = null;
210
        } else {
211
            // We have an actual grade.
212
            $newgrade->finalgrade = $value;
213
        }
214
        $this->newgrades[] = $newgrade;
215
        return $newgrade;
216
    }
217
 
218
    /**
219
     * Check that the user is in the system.
220
     *
221
     * @param string $value The value, from the csv file, being mapped to identify the user.
222
     * @param array $userfields Contains the field and label being mapped from.
223
     * @return int Returns the user ID if it exists, otherwise null.
224
     */
225
    protected function check_user_exists($value, $userfields) {
226
        global $DB;
227
 
228
        $user = null;
229
        $errorkey = false;
230
        // The user may use the incorrect field to match the user. This could result in an exception.
231
        try {
232
            $field = $userfields['field'];
233
            // Fields that can be queried in a case-insensitive manner.
234
            $caseinsensitivefields = [
235
                'email',
236
                'username',
237
            ];
238
            // Build query predicate.
239
            if (in_array($field, $caseinsensitivefields)) {
240
                // Case-insensitive.
241
                $select = $DB->sql_equal($field, ':' . $field, false);
242
            } else {
243
                // Exact-value.
244
                $select = "{$field} = :{$field}";
245
            }
246
 
247
            // Validate if the user id value is numerical.
248
            if ($field === 'id' && !is_numeric($value)) {
249
                $errorkey = 'usermappingerror';
250
            }
251
            // Make sure the record exists and that there's only one matching record found.
252
            $user = $DB->get_record_select('user', $select, array($userfields['field'] => $value), '*', MUST_EXIST);
253
        } catch (dml_missing_record_exception $missingex) {
254
            $errorkey = 'usermappingerror';
255
        } catch (dml_multiple_records_exception $multiex) {
256
            $errorkey = 'usermappingerrormultipleusersfound';
257
        }
258
        // Field may be fine, but no records were returned.
259
        if ($errorkey) {
260
            $usermappingerrorobj = new stdClass();
261
            $usermappingerrorobj->field = $userfields['label'];
262
            $usermappingerrorobj->value = $value;
263
            $this->cleanup_import(get_string($errorkey, 'grades', $usermappingerrorobj));
264
            unset($usermappingerrorobj);
265
            return null;
266
        }
267
        return $user->id;
268
    }
269
 
270
    /**
271
     * Check to see if the feedback matches a grade item.
272
     *
273
     * @param int $courseid The course ID.
274
     * @param int $itemid The ID of the grade item that the feedback relates to.
275
     * @param string $value The actual feedback being imported.
276
     * @return object Creates a feedback object with the item ID and the feedback value.
277
     */
278
    protected function create_feedback($courseid, $itemid, $value) {
279
        // Case of an id, only maps id of a grade_item.
280
        // This was idnumber.
281
        if (!new grade_item(array('id' => $itemid, 'courseid' => $courseid))) {
282
            // Supplied bad mapping, should not be possible since user
283
            // had to pick mapping.
284
            $this->cleanup_import(get_string('importfailed', 'grades'));
285
            return null;
286
        }
287
 
288
        // The itemid is the id of the grade item.
289
        $feedback = new stdClass();
290
        $feedback->itemid   = $itemid;
291
        $feedback->feedback = $value;
292
        return $feedback;
293
    }
294
 
295
    /**
296
     * This updates existing grade items.
297
     *
298
     * @param int $courseid The course ID.
299
     * @param array $map Mapping information provided by the user.
300
     * @param int $key The line that we are currently working on.
301
     * @param bool $verbosescales Form setting for grading with scales.
302
     * @param string $value The grade value.
303
     * @return array grades to be updated.
304
     */
305
    protected function update_grade_item($courseid, $map, $key, $verbosescales, $value) {
306
        // Case of an id, only maps id of a grade_item.
307
        // This was idnumber.
308
        if (!$gradeitem = new grade_item(array('id' => $map[$key], 'courseid' => $courseid))) {
309
            // Supplied bad mapping, should not be possible since user
310
            // had to pick mapping.
311
            $this->cleanup_import(get_string('importfailed', 'grades'));
312
            return null;
313
        }
314
 
315
        // Check if grade item is locked if so, abort.
316
        if ($gradeitem->is_locked()) {
317
            $this->cleanup_import(get_string('gradeitemlocked', 'grades'));
318
            return null;
319
        }
320
 
321
        $newgrade = new stdClass();
322
        $newgrade->itemid = $gradeitem->id;
323
        if ($gradeitem->gradetype == GRADE_TYPE_SCALE and $verbosescales) {
324
            if ($value === '' or $value == '-') {
325
                $value = null; // No grade.
326
            } else {
327
                $scale = $gradeitem->load_scale();
328
                $scales = explode(',', $scale->scale);
329
                $scales = array_map('trim', $scales); // Hack - trim whitespace around scale options.
330
                array_unshift($scales, '-'); // Scales start at key 1.
331
                $key = array_search($value, $scales);
332
                if ($key === false) {
333
                    $this->cleanup_import(get_string('badgrade', 'grades'));
334
                    return null;
335
                }
336
                $value = $key;
337
            }
338
            $newgrade->finalgrade = $value;
339
        } else {
340
            if ($value === '' or $value == '-') {
341
                $value = null; // No grade.
342
            } else {
343
                // If the value has a local decimal or can correctly be unformatted, do it.
344
                $validvalue = unformat_float($value, true);
345
                if ($validvalue !== false) {
346
                    $value = $validvalue;
347
                } else {
348
                    // Non numeric grade value supplied, possibly mapped wrong column.
349
                    $this->cleanup_import(get_string('badgrade', 'grades'));
350
                    return null;
351
                }
352
            }
353
            $newgrade->finalgrade = $value;
354
        }
355
        $this->newgrades[] = $newgrade;
356
        return $this->newgrades;
357
    }
358
 
359
    /**
360
     * Clean up failed CSV grade import. Clears the temp table for inserting grades.
361
     *
362
     * @param string $notification The error message to display from the unsuccessful grade import.
363
     */
364
    protected function cleanup_import($notification) {
365
        $this->status = false;
366
        import_cleanup($this->importcode);
367
        $this->gradebookerrors[] = $notification;
368
    }
369
 
370
    /**
371
     * Check user mapping.
372
     *
373
     * @param string $mappingidentifier The user field that we are matching together.
374
     * @param string $value The value we are checking / importing.
375
     * @param array $header The column headers of the csv file.
376
     * @param array $map Mapping information provided by the user.
377
     * @param int $key Current row identifier.
378
     * @param int $courseid The course ID.
379
     * @param int $feedbackgradeid The ID of the grade item that the feedback relates to.
380
     * @param bool $verbosescales Form setting for grading with scales.
381
     */
382
    protected function map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid,
383
            $verbosescales) {
384
 
385
        // Fields that the user can be mapped from.
386
        $userfields = array(
387
            'userid' => array(
388
                'field' => 'id',
389
                'label' => 'id',
390
            ),
391
            'useridnumber' => array(
392
                'field' => 'idnumber',
393
                'label' => 'idnumber',
394
            ),
395
            'useremail' => array(
396
                'field' => 'email',
397
                'label' => 'email address',
398
            ),
399
            'username' => array(
400
                'field' => 'username',
401
                'label' => 'username',
402
            ),
403
        );
404
 
405
        switch ($mappingidentifier) {
406
            case 'userid':
407
            case 'useridnumber':
408
            case 'useremail':
409
            case 'username':
410
                $this->studentid = $this->check_user_exists($value, $userfields[$mappingidentifier]);
411
            break;
412
            case 'new':
413
                $this->import_new_grade_item($header, $key, $value);
414
            break;
415
            case 'feedback':
416
                if ($feedbackgradeid) {
417
                    $feedback = $this->create_feedback($courseid, $feedbackgradeid, $value);
418
                    if (isset($feedback)) {
419
                        $this->newfeedbacks[] = $feedback;
420
                    }
421
                }
422
            break;
423
            default:
424
                // Existing grade items.
425
                if (!empty($map[$key])) {
426
                    $this->newgrades = $this->update_grade_item($courseid, $map, $key, $verbosescales, $value,
427
                            $mappingidentifier);
428
                }
429
                // Otherwise, we ignore this column altogether because user has chosen
430
                // to ignore them (e.g. institution, address etc).
431
            break;
432
        }
433
    }
434
 
435
    /**
436
     * Checks and prepares grade data for inserting into the gradebook.
437
     *
438
     * @param array $header Column headers of the CSV file.
439
     * @param object $formdata Mapping information from the preview page.
440
     * @param object $csvimport csv import reader object for iterating over the imported CSV file.
441
     * @param int $courseid The course ID.
442
     * @param bool $separatemode If we have groups are they separate?
443
     * @param mixed $currentgroup current group information.
444
     * @param bool $verbosescales Form setting for grading with scales.
445
     * @return bool True if the status for importing is okay, false if there are errors.
446
     */
447
    public function prepare_import_grade_data($header, $formdata, $csvimport, $courseid, $separatemode, $currentgroup,
448
            $verbosescales) {
449
        global $DB, $USER;
450
 
451
        // The import code is used for inserting data into the grade tables.
452
        $this->importcode = $formdata->importcode;
453
        $this->status = true;
454
        $this->headers = $header;
455
        $this->studentid = null;
456
        $this->gradebookerrors = null;
457
        $forceimport = $formdata->forceimport;
458
        // Temporary array to keep track of what new headers are processed.
459
        $this->newgradeitems = array();
460
        $this->trim_headers();
461
        $timeexportkey = null;
462
        $map = array();
463
        // Loops mapping_0, mapping_1 .. mapping_n and construct $map array.
464
        foreach ($header as $i => $head) {
465
            if (isset($formdata->{'mapping_'.$i})) {
466
                $map[$i] = $formdata->{'mapping_'.$i};
467
            }
468
            if ($head == get_string('timeexported', 'gradeexport_txt')) {
469
                $timeexportkey = $i;
470
            }
471
        }
472
 
473
        // If mapping information is supplied.
474
        $map[clean_param($formdata->mapfrom, PARAM_RAW)] = clean_param($formdata->mapto, PARAM_RAW);
475
 
476
        // Check for mapto collisions.
477
        $maperrors = array();
478
        foreach ($map as $i => $j) {
479
            if (($j == 0) || ($j == 'new')) {
480
                // You can have multiple ignores or multiple new grade items.
481
                continue;
482
            } else {
483
                if (!isset($maperrors[$j])) {
484
                    $maperrors[$j] = true;
485
                } else {
486
                    // Collision.
487
                    throw new \moodle_exception('cannotmapfield', '', '', $j);
488
                }
489
            }
490
        }
491
 
492
        $this->raise_limits();
493
 
494
        $csvimport->init();
495
 
496
        while ($line = $csvimport->next()) {
497
            if (count($line) <= 1) {
498
                // There is no data on this line, move on.
499
                continue;
500
            }
501
 
502
            // Array to hold all grades to be inserted.
503
            $this->newgrades = array();
504
            // Array to hold all feedback.
505
            $this->newfeedbacks = array();
506
            // Each line is a student record.
507
            foreach ($line as $key => $value) {
508
 
509
                $value = clean_param($value, PARAM_RAW);
510
                $value = trim($value);
511
 
512
                /*
513
                 * the options are
514
                 * 1) userid, useridnumber, usermail, username - used to identify user row
515
                 * 2) new - new grade item
516
                 * 3) id - id of the old grade item to map onto
517
                 * 3) feedback_id - feedback for grade item id
518
                 */
519
 
520
                // Explode the mapping for feedback into a label 'feedback' and the identifying number.
521
                $mappingbase = explode("_", $map[$key]);
522
                $mappingidentifier = $mappingbase[0];
523
                // Set the feedback identifier if it exists.
524
                if (isset($mappingbase[1])) {
525
                    $feedbackgradeid = (int)$mappingbase[1];
526
                } else {
527
                    $feedbackgradeid = '';
528
                }
529
 
530
                $this->map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid,
531
                        $verbosescales);
532
                if ($this->status === false) {
533
                    return $this->status;
534
                }
535
            }
536
 
537
            // No user mapping supplied at all, or user mapping failed.
538
            if (empty($this->studentid) || !is_numeric($this->studentid)) {
539
                // User not found, abort whole import.
540
                $this->cleanup_import(get_string('usermappingerrorusernotfound', 'grades'));
541
                break;
542
            }
543
 
544
            if ($separatemode and !groups_is_member($currentgroup, $this->studentid)) {
545
                // Not allowed to import into this group, abort.
546
                $this->cleanup_import(get_string('usermappingerrorcurrentgroup', 'grades'));
547
                break;
548
            }
549
 
550
            // Insert results of this students into buffer.
551
            if ($this->status and !empty($this->newgrades)) {
552
 
553
                foreach ($this->newgrades as $newgrade) {
554
 
555
                    // Check if grade_grade is locked and if so, abort.
556
                    if (!empty($newgrade->itemid) and $gradegrade = new grade_grade(array('itemid' => $newgrade->itemid,
557
                            'userid' => $this->studentid))) {
558
                        if ($gradegrade->is_locked()) {
559
                            // Individual grade locked.
560
                            $this->cleanup_import(get_string('gradelocked', 'grades'));
561
                            return $this->status;
562
                        }
563
                        // Check if the force import option is disabled and the last exported date column is present.
564
                        if (!$forceimport && !empty($timeexportkey)) {
565
                            $exportedtime = $line[$timeexportkey];
566
                            if (clean_param($exportedtime, PARAM_INT) != $exportedtime || $exportedtime > time() ||
567
                                    $exportedtime < strtotime("-1 year", time())) {
568
                                // The date is invalid, or in the future, or more than a year old.
569
                                $this->cleanup_import(get_string('invalidgradeexporteddate', 'grades'));
570
                                return $this->status;
571
 
572
                            }
573
                            $timemodified = $gradegrade->get_dategraded();
574
                            if (!empty($timemodified) && ($exportedtime < $timemodified)) {
575
                                // The item was graded after we exported it, we return here not to override it.
576
                                $user = core_user::get_user($this->studentid);
577
                                $this->cleanup_import(get_string('gradealreadyupdated', 'grades', fullname($user)));
578
                                return $this->status;
579
                            }
580
                        }
581
                    }
582
                    if (isset($newgrade->itemid)) {
583
                        $gradeitem = new grade_item(['id' => $newgrade->itemid]);
584
                    } else if (isset($newgrade->newgradeitem)) {
585
                        $gradeitem = new grade_item(['id' => $newgrade->newgradeitem]);
586
                    }
587
                    $insertid = isset($gradeitem) ? self::insert_grade_record($newgrade, $this->studentid, $gradeitem) : null;
588
                    // Check to see if the insert was successful.
589
                    if (empty($insertid)) {
590
                        return null;
591
                    }
592
                }
593
            }
594
 
595
            // Updating/inserting all comments here.
596
            if ($this->status and !empty($this->newfeedbacks)) {
597
                foreach ($this->newfeedbacks as $newfeedback) {
598
                    $sql = "SELECT *
599
                              FROM {grade_import_values}
600
                             WHERE importcode=? AND userid=? AND itemid=? AND importer=?";
601
                    if ($feedback = $DB->get_record_sql($sql, array($this->importcode, $this->studentid, $newfeedback->itemid,
602
                            $USER->id))) {
603
                        $newfeedback->id = $feedback->id;
604
                        $DB->update_record('grade_import_values', $newfeedback);
605
 
606
                    } else {
607
                        // The grade item for this is not updated.
608
                        $newfeedback->importonlyfeedback = true;
609
                        $insertid = self::insert_grade_record($newfeedback, $this->studentid, new grade_item(['id' => $newfeedback->itemid]));
610
                        // Check to see if the insert was successful.
611
                        if (empty($insertid)) {
612
                            return null;
613
                        }
614
                    }
615
                }
616
            }
617
        }
618
        return $this->status;
619
    }
620
 
621
    /**
622
     * Returns the headers parameter for this class.
623
     *
624
     * @return array returns headers parameter for this class.
625
     */
626
    public function get_headers() {
627
        return $this->headers;
628
    }
629
 
630
    /**
631
     * Returns the error parameter for this class.
632
     *
633
     * @return string returns error parameter for this class.
634
     */
635
    public function get_error() {
636
        return $this->error;
637
    }
638
 
639
    /**
640
     * Returns the iid parameter for this class.
641
     *
642
     * @return int returns iid parameter for this class.
643
     */
644
    public function get_iid() {
645
        return $this->iid;
646
    }
647
 
648
    /**
649
     * Returns the preview_data parameter for this class.
650
     *
651
     * @return array returns previewdata parameter for this class.
652
     */
653
    public function get_previewdata() {
654
        return $this->previewdata;
655
    }
656
 
657
    /**
658
     * Returns the gradebookerrors parameter for this class.
659
     *
660
     * @return array returns gradebookerrors parameter for this class.
661
     */
662
    public function get_gradebookerrors() {
663
        return $this->gradebookerrors;
664
    }
665
}