Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
// This file is part of Moodle - http://moodle.org/
4
//
5
// Moodle is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// Moodle is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
require_once($CFG->libdir.'/gradelib.php');
19
 
20
/**
21
 * Returns new improtcode for current user
22
 * @return int importcode
23
 */
24
function get_new_importcode() {
25
    global $USER, $DB;
26
 
27
    $importcode = time();
28
    while ($DB->get_record('grade_import_values', array('importcode' => $importcode, 'importer' => $USER->id))) {
29
        $importcode--;
30
    }
31
 
32
    return $importcode;
33
}
34
 
35
/**
36
 * given an import code, commits all entries in buffer tables
37
 * (grade_import_value and grade_import_newitem)
38
 * If this function is called, we assume that all data collected
39
 * up to this point is fine and we can go ahead and commit
40
 * @param int $courseid - ID of the course.
41
 * @param int $importcode - Import batch identifier.
42
 * @param bool $importfeedback - Whether to import feedback as well.
43
 * @param bool $verbose - Print feedback and continue button.
44
 * @return bool success
45
 */
46
function grade_import_commit($courseid, $importcode, $importfeedback=true, $verbose=true) {
47
    global $CFG, $USER, $DB, $OUTPUT;
48
 
49
    $failed = false;
50
    $executionerrors = false;
51
    $commitstart = time(); // start time in case we need to roll back
52
    $newitemids = array(); // array to hold new grade_item ids from grade_import_newitem table, mapping array
53
 
54
    /// first select distinct new grade_items with this batch
55
    $params = array($importcode, $USER->id);
56
    if ($newitems = $DB->get_records_sql("SELECT *
57
                                           FROM {grade_import_newitem}
58
                                          WHERE importcode = ? AND importer=?", $params)) {
59
 
60
        // instances of the new grade_items created, cached
61
        // in case grade_update fails, so that we can remove them
62
        $instances = array();
63
        foreach ($newitems as $newitem) {
64
            // get all grades with this item
65
 
66
            $gradeimportparams = array('newgradeitem' => $newitem->id, 'importcode' => $importcode, 'importer' => $USER->id);
67
            if ($grades = $DB->get_records('grade_import_values', $gradeimportparams)) {
68
                /// create a new grade item for this - must use false as second param!
69
                /// TODO: we need some bounds here too
70
                $gradeitem = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual', 'itemname'=>$newitem->itemname), false);
71
                $gradeitem->insert('import');
72
                $instances[] = $gradeitem;
73
 
74
                // insert each individual grade to this new grade item
75
                foreach ($grades as $grade) {
76
                    if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import',
77
                        $grade->feedback, FORMAT_MOODLE, null, null, true)) {
78
                        $failed = true;
79
                        break 2;
80
                    }
81
                }
82
            }
83
        }
84
 
85
        if ($failed) {
86
            foreach ($instances as $instance) {
87
                $gradeitem->delete('import');
88
            }
89
            import_cleanup($importcode);
90
            return false;
91
        }
92
    }
93
 
94
    /// then find all existing items
95
 
96
    if ($gradeitems = $DB->get_records_sql("SELECT DISTINCT (itemid)
97
                                             FROM {grade_import_values}
98
                                            WHERE importcode = ? AND importer=? AND itemid > 0",
99
                                            array($importcode, $USER->id))) {
100
 
101
        $modifieditems = array();
102
 
103
        foreach ($gradeitems as $itemid=>$notused) {
104
 
105
            if (!$gradeitem = new grade_item(array('id'=>$itemid))) {
106
                // not supposed to happen, but just in case
107
                import_cleanup($importcode);
108
                return false;
109
            }
110
            // get all grades with this item
111
            $gradeimportparams = array('itemid' => $itemid, 'importcode' => $importcode, 'importer' => $USER->id);
112
            if ($grades = $DB->get_records('grade_import_values', $gradeimportparams)) {
113
 
114
                // make the grades array for update_grade
115
                foreach ($grades as $grade) {
116
                    if (!$importfeedback || $grade->feedback === null) {
117
                        $grade->feedback = false; // ignore it
118
                    }
119
                    if ($grade->importonlyfeedback) {
120
                        // False means do not change. See grade_itme::update_final_grade().
121
                        $grade->finalgrade = false;
122
                    }
123
                    if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import',
124
                            $grade->feedback, FORMAT_MOODLE, null, null, true)) {
125
                        $errordata = new stdClass();
126
                        $errordata->itemname = $gradeitem->itemname;
127
                        $errordata->userid = $grade->userid;
128
                        $executionerrors[] = get_string('errorsettinggrade', 'grades', $errordata);
129
                        $failed = true;
130
                        break 2;
131
                    }
132
                }
133
                //$itemdetails -> idnumber = $gradeitem->idnumber;
134
                $modifieditems[] = $itemid;
135
 
136
            }
137
        }
138
 
139
        if ($failed) {
140
            if ($executionerrors && $verbose) {
141
                echo $OUTPUT->notification(get_string('gradeimportfailed', 'grades'));
142
                foreach ($executionerrors as $errorstr) {
143
                    echo $OUTPUT->notification($errorstr);
144
                }
145
            }
146
            import_cleanup($importcode);
147
            return false;
148
        }
149
    }
150
 
151
    if ($verbose) {
152
        echo $OUTPUT->notification(get_string('importsuccess', 'grades'), 'notifysuccess');
153
        $unenrolledusers = get_unenrolled_users_in_import($importcode, $courseid);
154
        if ($unenrolledusers) {
155
            $list = array();
156
            foreach ($unenrolledusers as $u) {
157
                $u->fullname = fullname($u);
158
                $list[] = get_string('usergrade', 'grades', $u);
159
            }
160
            echo $OUTPUT->notification(get_string('unenrolledusersinimport', 'grades', html_writer::alist($list)), 'notifysuccess');
161
        }
162
        echo $OUTPUT->continue_button($CFG->wwwroot.'/grade/index.php?id='.$courseid);
163
    }
164
    // clean up
165
    import_cleanup($importcode);
166
 
167
    return true;
168
}
169
 
170
/**
171
 * This function returns an array of grades that were included in the import,
172
 * but where the user does not currently have a graded role on the course. These grades
173
 * are still stored in the database, but will not be visible in the gradebook unless
174
 * this user subsequently enrols on the course in a graded roles.
175
 *
176
 * The returned objects have fields useridnumber and gradeidnumber, plus enough user name fields to pass to {@see fullname}
177
 *
178
 * @param integer $importcode import batch identifier
179
 * @param integer $courseid the course we are importing to.
180
 * @return mixed and array of user objects, or false if none.
181
 */
182
function get_unenrolled_users_in_import($importcode, $courseid) {
183
    global $CFG, $DB;
184
 
185
    $coursecontext = context_course::instance($courseid);
186
 
187
    // We want to query both the current context and parent contexts.
188
    list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
189
 
190
    // Users with a gradeable role.
191
    list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr');
192
 
193
    $usernamefields = core_user\fields::for_name()->get_sql('u', false, '', '', false);
194
 
195
    // Enrolled users.
196
    $context = context_course::instance($courseid);
197
    list($enrolledsql, $enrolledparams) = get_enrolled_sql($context);
198
    list($sort, $sortparams) = users_order_by_sql('u');
199
 
200
    $sql = "SELECT giv.id, {$usernamefields->selects}, u.idnumber AS useridnumber,
201
                   COALESCE(gi.idnumber, gin.itemname) AS gradeidnumber
202
              FROM {grade_import_values} giv
203
              JOIN {user} u
204
                   ON giv.userid = u.id
205
              LEFT JOIN {grade_items} gi
206
                        ON gi.id = giv.itemid
207
              LEFT JOIN {grade_import_newitem} gin
208
                        ON gin.id = giv.newgradeitem
209
              LEFT JOIN ($enrolledsql) je
210
                        ON je.id = u.id
211
              LEFT JOIN {role_assignments} ra
212
                        ON (giv.userid = ra.userid AND ra.roleid $gradebookrolessql AND ra.contextid $relatedctxsql)
213
             WHERE giv.importcode = :importcode
214
                   AND (ra.id IS NULL OR je.id IS NULL)
215
          ORDER BY gradeidnumber, $sort";
216
    $params = array_merge($gradebookrolesparams, $enrolledparams, $sortparams, $relatedctxparams);
217
    $params['importcode'] = $importcode;
218
 
219
    return $DB->get_records_sql($sql, $params);
220
}
221
 
222
/**
223
 * removes entries from grade import buffer tables grade_import_value and grade_import_newitem
224
 * after a successful import, or during an import abort
225
 * @param string importcode - import batch identifier
226
 */
227
function import_cleanup($importcode) {
228
    global $USER, $DB;
229
 
230
    // remove entries from buffer table
231
    $DB->delete_records('grade_import_values', array('importcode' => $importcode, 'importer' => $USER->id));
232
    $DB->delete_records('grade_import_newitem', array('importcode' => $importcode, 'importer' => $USER->id));
233
}
234
 
235