uploadmemberscsv.php 7.95 KB
Newer Older
1
2
3
4
5
6
<?php
/**
 *
 * @package    mahara
 * @subpackage admin
 * @author     Catalyst IT Ltd
7
8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 *
 */

define('INTERNAL', 1);
define('INSTITUTIONALADMIN', 1);
define('MENUITEM', 'managegroups/uploadmemberscsv');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
define('TITLE', get_string('uploadgroupmemberscsv', 'admin'));
require_once('pieforms/pieform.php');
require_once(get_config('libroot') . 'group.php');
require_once(get_config('libroot') . 'institution.php');
safe_require('artefact', 'internal');

// Turn on autodetecting of line endings, so mac newlines (\r) will work
ini_set('auto_detect_line_endings', 1);

$FORMAT = array();
$ALLOWEDKEYS = array(
    'shortname',
    'username',
    'role',
);
$MANDATORYFIELDS = array(
    'shortname',
    'username',
    'role',
);
$MEMBERS = array(); // Store the members
$GROUPS = array(); // Map gid to group shortnames

$form = array(
    'name' => 'uploadcsv',
    'elements' => array(
        'institution' => get_institution_selector(),
        'file' => array(
            'type' => 'file',
            'title' => get_string('csvfile', 'admin'),
            'description' => get_string('groupmemberscsvfiledescription', 'admin'),
47
            'accept' => '.csv, text/csv, application/csv, text/comma-separated-values',
48
49
50
51
            'rules' => array(
                'required' => true
            )
        ),
52
53
54
55
56
        'progress_meter_token' => array(
            'type' => 'hidden',
            'value' => 'uploadgroupmemberscsv',
            'readonly' => TRUE,
        ),
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        'submit' => array(
            'type' => 'submit',
            'value' => get_string('uploadgroupmemberscsv', 'admin')
        )
    )
);


/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
 */
function uploadcsv_validate(Pieform $form, $values) {
    global $CSVDATA, $ALLOWEDKEYS, $MANDATORYFIELDS, $FORMAT, $USER, $UPDATES, $MEMBERS, $GROUPS;

    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }

    if ($values['file']['size'] == 0) {
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
        return;
    }

    $institution = $values['institution'];
    if (!$USER->can_edit_institution($institution)) {
        $form->set_error('institution', get_string('notadminforinstitution', 'admin'));
        return;
    }

    require_once('csvfile.php');

    $csvgroups = new CsvFile($values['file']['tmp_name']);
    $csvgroups->set('allowedkeys', $ALLOWEDKEYS);

    $csvgroups->set('mandatoryfields', $MANDATORYFIELDS);
    $csvdata = $csvgroups->get_data();

    if (!empty($csvdata->errors['file'])) {
        $form->set_error('file', $csvdata->errors['file']);
        return;
    }

    $csverrors = new CSVErrors();

    $formatkeylookup = array_flip($csvdata->format);

    $shortnames = array();
    $hadadmin = array();

112
113
    $num_lines = count($csvdata->data);

114
115
116
117
    foreach ($csvdata->data as $key => $line) {
        // If headers exists, increment i = key + 2 for actual line number
        $i = ($csvgroups->get('headerExists')) ? ($key + 2) : ($key + 1);

118
119
120
121
122
        // In adding 5000 groups, this part was approx 8% of the wall time.
        if (!($key % 25)) {
            set_progress_info('uploadgroupmemberscsv', $key, $num_lines * 10, get_string('validating', 'admin'));
        }

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        // Trim non-breaking spaces -- they get left in place by File_CSV
        foreach ($line as &$field) {
            $field = preg_replace('/^(\s|\xc2\xa0)*(.*?)(\s|\xc2\xa0)*$/', '$2', $field);
        }

        $shortname = $line[$formatkeylookup['shortname']];
        $username  = $line[$formatkeylookup['username']];
        $role      = $line[$formatkeylookup['role']];

        $gid = get_field('group', 'id', 'shortname', $shortname, 'institution', $institution);
        if (!$gid) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrornosuchshortname', 'admin', $i, $shortname, $institution));
            continue;
        }

        $uid = get_field_sql('SELECT id FROM {usr} WHERE LOWER(username) = ?', array(strtolower($username)));
        if (!$uid) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrornosuchusername', 'admin', $i, $username));
            continue;
        }

        if ($institution != 'mahara' && !record_exists('usr_institution', 'usr', $uid, 'institution', $institution)) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrorusernotininstitution', 'admin', $i, $username, $institution));
            continue;
        }

        if (!in_array($role, array_keys(group_get_role_info($gid)))) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrorinvalidrole', 'admin', $i, $role));
            continue;
        }

        if (!isset($MEMBERS[$gid])) {
            $MEMBERS[$gid] = array();
        }

        if (isset($MEMBERS[$gid][$uid])) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrorduplicateusername', 'admin', $i, $shortname, $username));
            continue;
        }

        $MEMBERS[$gid][$uid] = $role;
        $GROUPS[$gid] = $shortname;

        if ($role == 'admin') {
            $hasadmin[$shortname] = 1;
        }

    }

    foreach ($GROUPS as $shortname) {
        if (!isset($hasadmin[$shortname])) {
            $csverrors->add($i, get_string('uploadgroupmemberscsverrornoadminlisted', 'admin', $i, $shortname));
        }
    }

    if ($errors = $csverrors->process()) {
        $form->set_error('file', clean_html($errors));
        return;
    }

    $FORMAT = $csvdata->format;
    $CSVDATA = $csvdata->data;
}

/**
 * Add the users to the system. Make sure that they have to change their
 * password on next login also.
 */
function uploadcsv_submit(Pieform $form, $values) {
    global $SESSION, $CSVDATA, $FORMAT, $UPDATES, $USER, $MEMBERS, $GROUPS;

    $formatkeylookup = array_flip($FORMAT);

    $institution = $values['institution'];

    db_begin();

200
201
    $lines_done = 0;
    $num_lines = count($CSVDATA);
202
203

    foreach ($MEMBERS as $gid => $members) {
204
205
        $updates = group_update_members($gid, $members, $lines_done, $num_lines);
        $lines_done += sizeof($members);
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

        if (empty($updates)) {
            unset($UPDATES[$GROUPS[$gid]]);
        }
        else {
            $UPDATES[$GROUPS[$gid]] = $updates;
            log_debug('updated group members ' . $GROUPS[$gid] . ' (' . implode(', ', array_keys((array)$updates)) . ')');
        }
    }

    db_commit();

    // TODO: Fix this to show correct info
    $SESSION->add_ok_msg(get_string('csvfileprocessedsuccessfully', 'admin'));
    if ($UPDATES) {
        $updatemsg = smarty_core();
        $updatemsg->assign('updates', $UPDATES);
        $SESSION->add_info_msg($updatemsg->fetch('admin/groups/memberscsvupdatemessage.tpl'), false);
    }
    else {
        $SESSION->add_ok_msg(get_string('numbergroupsupdated', 'admin', 0));
    }
228
    set_progress_done('uploadgroupmemberscsv');
229
230
231
    redirect('/admin/groups/uploadmemberscsv.php');
}

232
$uploadcsvpagedescription = get_string('uploadgroupmemberscsvpagedescription3', 'admin',
233
234
235
236
237
                                            get_config('wwwroot') . 'admin/groups/uploadcsv.php',
                                            get_string('uploadgroupcsv', 'admin'));

$form = pieform($form);

238
239
set_progress_done('uploadgroupmemberscsv');

240
241
242
243
$smarty = smarty(array('adminuploadcsv'));
$smarty->assign('uploadcsvpagedescription', $uploadcsvpagedescription);
$smarty->assign('uploadcsvform', $form);
$smarty->assign('PAGEHEADING', TITLE);
Naomi Guyer's avatar
Naomi Guyer committed
244
$smarty->assign('PAGEICON', 'fa fa-users');
245
$smarty->display('admin/groups/uploadcsv.tpl');