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
 * Import outcomes from a file
19
 *
20
 * @package   core_grades
21
 * @copyright 2008 Moodle Pty Ltd (http://moodle.com)
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
require_once(__DIR__.'/../../../config.php');
26
require_once($CFG->dirroot.'/lib/formslib.php');
27
require_once($CFG->dirroot.'/grade/lib.php');
28
require_once($CFG->libdir.'/gradelib.php');
29
require_once('import_outcomes_form.php');
30
 
31
$courseid = optional_param('courseid', 0, PARAM_INT);
32
$action   = optional_param('action', '', PARAM_ALPHA);
33
$scope    = optional_param('scope', 'custom', PARAM_ALPHA);
34
 
35
$url = new moodle_url('/grade/edit/outcome/import.php', array('courseid' => $courseid));
36
$PAGE->set_url($url);
37
$PAGE->set_pagelayout('admin');
38
 
39
/// Make sure they can even access this course
40
if ($courseid) {
41
    if (!$course = $DB->get_record('course', array('id' => $courseid))) {
42
        throw new \moodle_exception('invalidcourseid');
43
    }
44
    require_login($course);
45
    $context = context_course::instance($course->id);
46
 
47
    if (empty($CFG->enableoutcomes)) {
48
        redirect('../../index.php?id='.$courseid);
49
    }
50
    navigation_node::override_active_url(new moodle_url('/grade/edit/outcome/course.php', ['id' => $courseid]));
51
    $PAGE->navbar->add(get_string('manageoutcomes', 'grades'),
52
        new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]));
53
    $PAGE->navbar->add(get_string('importoutcomes', 'grades'),
54
        new moodle_url('/grade/edit/outcome/import.php', ['courseid' => $courseid]));
55
 
56
} else {
57
    require_once $CFG->libdir.'/adminlib.php';
58
    admin_externalpage_setup('outcomes');
59
    $context = context_system::instance();
60
}
61
 
62
require_capability('moodle/grade:manageoutcomes', $context);
63
 
64
$upload_form = new import_outcomes_form();
65
 
66
if ($upload_form->is_cancelled()) {
67
    redirect(new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]));
68
    die;
69
}
70
 
71
print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'),
72
    false, false, false);
73
 
74
if (!$upload_form->get_data()) { // Display the import form.
75
    $upload_form->display();
76
    echo $OUTPUT->footer();
77
    die;
78
}
79
 
80
$imported_file = $CFG->tempdir . '/outcomeimport/importedfile_'.time().'.csv';
81
make_temp_directory('outcomeimport');
82
 
83
// copying imported file
84
if (!$upload_form->save_file('userfile', $imported_file, true)) {
85
    redirect('import.php'. ($courseid ? "?courseid=$courseid" : ''), get_string('importfilemissing', 'grades'));
86
}
87
 
88
/// which scope are we importing the outcomes in?
89
if (isset($courseid) && ($scope  == 'custom')) {
90
    // custom scale
91
    $local_scope = true;
92
} elseif (($scope == 'global') && has_capability('moodle/grade:manage', context_system::instance())) {
93
    // global scale
94
    $local_scope = false;
95
} else {
96
    // shouldn't happen .. user might be trying to access this script without the right permissions.
97
    redirect('index.php', get_string('importerror', 'grades'));
98
}
99
 
100
// open the file, start importing data
101
if ($handle = fopen($imported_file, 'r')) {
102
    $line = 0; // will keep track of current line, to give better error messages.
103
    $file_headers = '';
104
 
105
    // $csv_data needs to have at least these columns, the value is the default position in the data file.
106
    $headers = array('outcome_name' => 0, 'outcome_shortname' => 1, 'scale_name' => 3, 'scale_items' => 4);
107
    $optional_headers = array('outcome_description'=>2, 'scale_description' => 5);
108
    $imported_headers = array(); // will later be initialized with the values found in the file
109
 
110
    $fatal_error = false;
111
    $errormessage = '';
112
 
113
    // data should be separated by a ';'.  *NOT* by a comma!  TODO: version 2.0
114
    // or whenever we can depend on PHP5, set the second parameter (8192) to 0 (unlimited line length) : the database can store over 128k per line.
115
    while ( $csv_data = fgetcsv($handle, 8192, ';', '"')) { // if the line is over 8k, it won't work...
116
        $line++;
117
 
118
        // be tolerant on input, as fgetcsv returns "an array comprising a single null field" on blank lines
119
        if ($csv_data == array(null)) {
120
            continue;
121
        }
122
 
123
        // on first run, grab and analyse the header
124
        if ($file_headers == '') {
125
 
126
            $file_headers = array_flip($csv_data); // save the header line ... TODO: use the header line to let import work with columns in arbitrary order
127
 
128
            $error = false;
129
            foreach($headers as $key => $value) {
130
                // sanity check #1: make sure the file contains all the mandatory headers
131
                if (!array_key_exists($key, $file_headers)) {
132
                    $error = true;
133
                    break;
134
                }
135
            }
136
            if ($error) {
137
                $fatal_error = true;
138
                $errormessage = get_string('importoutcomenofile', 'grades', $line);
139
                break;
140
            }
141
 
142
            foreach(array_merge($headers, $optional_headers) as $header => $position) {
143
                // match given columns to expected columns *into* $headers
144
                $imported_headers[$header] = $file_headers[$header];
145
            }
146
 
147
            continue; // we don't import headers
148
        }
149
 
150
        // sanity check #2: every line must have the same number of columns as there are
151
        // headers.  If not, processing stops.
152
        if ( count($csv_data) != count($file_headers) ) {
153
            $fatal_error = true;
154
            $errormessage = get_string('importoutcomenofile', 'grades', $line);
155
            break;
156
        }
157
 
158
        // sanity check #3: all required fields must be present on the current line.
159
        foreach ($headers as $header => $position) {
160
            if ($csv_data[$imported_headers[$header]] == '') {
161
                $fatal_error = true;
162
                $errormessage = get_string('importoutcomenofile', 'grades', $line);
163
                break;
164
            }
165
        }
166
 
167
        // MDL-17273 errors in csv are not preventing import from happening. We break from the while loop here
168
        if ($fatal_error) {
169
            break;
170
        }
171
        $params = array($csv_data[$imported_headers['outcome_shortname']]);
172
        $wheresql = 'shortname = ? ';
173
 
174
        if ($local_scope) {
175
            $params[] = $courseid;
176
            $wheresql .= ' AND courseid = ?';
177
        } else {
178
            $wheresql .= ' AND courseid IS NULL';
179
        }
180
 
181
        $outcome = $DB->get_records_select('grade_outcomes', $wheresql, $params);
182
 
183
        if ($outcome) {
184
            // already exists, print a message and skip.
185
            echo $OUTPUT->notification(get_string('importskippedoutcome', 'grades',
186
                $csv_data[$imported_headers['outcome_shortname']]), 'info', false);
187
            continue;
188
        }
189
 
190
        // new outcome will be added, search for compatible existing scale...
191
        $params = array($csv_data[$imported_headers['scale_name']], $csv_data[$imported_headers['scale_items']], $courseid);
192
        $wheresql = 'name = ? AND scale = ? AND (courseid = ? OR courseid = 0)';
193
        $scale = $DB->get_records_select('scale', $wheresql, $params);
194
 
195
        if ($scale) {
196
            // already exists in the right scope: use it.
197
            $scale_id = key($scale);
198
        } else {
199
            if (!has_capability('moodle/course:managescales', $context)) {
200
                echo $OUTPUT->notification(get_string('importskippedoutcome', 'grades',
201
                    $csv_data[$imported_headers['outcome_shortname']]), 'warning', false);
202
                continue;
203
            } else {
204
                // scale doesn't exists : create it.
205
                $scale_data = array('name' => $csv_data[$imported_headers['scale_name']],
206
                        'scale' => $csv_data[$imported_headers['scale_items']],
207
                        'description' => $csv_data[$imported_headers['scale_description']],
208
                        'userid' => $USER->id);
209
 
210
                if ($local_scope) {
211
                    $scale_data['courseid'] = $courseid;
212
                } else {
213
                    $scale_data['courseid'] = 0; // 'global' : scale use '0', outcomes use null
214
                }
215
                $scale = new grade_scale($scale_data);
216
                $scale_id = $scale->insert();
217
            }
218
        }
219
 
220
        // add outcome
221
        $outcome_data = array('shortname' => $csv_data[$imported_headers['outcome_shortname']],
222
                'fullname' => $csv_data[$imported_headers['outcome_name']],
223
                'scaleid' => $scale_id,
224
                'description' => $csv_data[$imported_headers['outcome_description']],
225
                'usermodified' => $USER->id);
226
 
227
        if ($local_scope) {
228
            $outcome_data['courseid'] = $courseid;
229
        } else {
230
            $outcome_data['courseid'] = null; // 'global' : scale use '0', outcomes use null
231
        }
232
        $outcome = new grade_outcome($outcome_data);
233
        $outcome_id = $outcome->insert();
234
 
235
        $outcome_success_strings = new StdClass();
236
        $outcome_success_strings->name = $outcome_data['fullname'];
237
        $outcome_success_strings->id = $outcome_id;
238
        echo $OUTPUT->notification(get_string('importoutcomesuccess', 'grades', $outcome_success_strings),
239
            'success', false);
240
    }
241
 
242
    if ($fatal_error) {
243
        echo $OUTPUT->notification($errormessage, 'error', false);
244
        echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', ['courseid' => $courseid]),
245
            get_string('back'), 'get');
246
    } else {
247
        echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]),
248
            get_string('continue'), 'get');
249
    }
250
} else {
251
    echo $OUTPUT->box(get_string('importoutcomenofile', 'grades', 0));
252
}
253
 
254
// finish
255
fclose($handle);
256
// delete temp file
257
unlink($imported_file);
258
 
259
echo $OUTPUT->footer();