uploadmemberscsv.php 7.91 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 244
$smarty = smarty(array('adminuploadcsv'));
$smarty->assign('uploadcsvpagedescription', $uploadcsvpagedescription);
$smarty->assign('uploadcsvform', $form);
$smarty->assign('PAGEHEADING', TITLE);
$smarty->display('admin/groups/uploadcsv.tpl');