MDL-56629 dataformat_html: Adding UTF-8 charset
[moodle.git] / cohort / externallib.php
CommitLineData
088645e2
AB
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 * External cohort API
19 *
20 * @package core_cohort
21 * @category external
22 * @copyright MediaTouch 2000 srl
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26require_once("$CFG->libdir/externallib.php");
27
28class core_cohort_external extends external_api {
29
30 /**
31 * Returns description of method parameters
32 *
33 * @return external_function_parameters
66d6221f 34 * @since Moodle 2.5
088645e2
AB
35 */
36 public static function create_cohorts_parameters() {
37 return new external_function_parameters(
38 array(
39 'cohorts' => new external_multiple_structure(
40 new external_single_structure(
41 array(
42 'categorytype' => new external_single_structure(
43 array(
44 'type' => new external_value(PARAM_TEXT, 'the name of the field: id (numeric value
66d6221f
DW
45 of course category id) or idnumber (alphanumeric value of idnumber course category)
46 or system (value ignored)'),
088645e2
AB
47 'value' => new external_value(PARAM_RAW, 'the value of the categorytype')
48 )
49 ),
50 'name' => new external_value(PARAM_RAW, 'cohort name'),
51 'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
52 'description' => new external_value(PARAM_RAW, 'cohort description', VALUE_OPTIONAL),
53 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
80f98467 54 'visible' => new external_value(PARAM_BOOL, 'cohort visible', VALUE_OPTIONAL, true),
088645e2
AB
55 )
56 )
57 )
58 )
59 );
60 }
61
62 /**
63 * Create one or more cohorts
64 *
65 * @param array $cohorts An array of cohorts to create.
66 * @return array An array of arrays
66d6221f 67 * @since Moodle 2.5
088645e2
AB
68 */
69 public static function create_cohorts($cohorts) {
70 global $CFG, $DB;
71 require_once("$CFG->dirroot/cohort/lib.php");
72
73 $params = self::validate_parameters(self::create_cohorts_parameters(), array('cohorts' => $cohorts));
74
75 $transaction = $DB->start_delegated_transaction();
76
66d6221f 77 $syscontext = context_system::instance();
088645e2
AB
78 $cohortids = array();
79
80 foreach ($params['cohorts'] as $cohort) {
81 $cohort = (object)$cohort;
82
83 // Category type (context id).
84 $categorytype = $cohort->categorytype;
66d6221f
DW
85 if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
86 throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
87 }
88 if ($categorytype['type'] === 'system') {
89 $cohort->contextid = $syscontext->id;
90 } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
91 $catcontext = context_coursecat::instance($catid);
92 $cohort->contextid = $catcontext->id;
088645e2
AB
93 } else {
94 throw new invalid_parameter_exception('category not exists: category '
95 .$categorytype['type'].' = '.$categorytype['value']);
96 }
97 // Make sure that the idnumber doesn't already exist.
98 if ($DB->record_exists('cohort', array('idnumber' => $cohort->idnumber))) {
99 throw new invalid_parameter_exception('record already exists: idnumber='.$cohort->idnumber);
100 }
101 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
102 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
103 throw new invalid_parameter_exception('Invalid context');
104 }
105 self::validate_context($context);
106 require_capability('moodle/cohort:manage', $context);
107
108 // Validate format.
109 $cohort->descriptionformat = external_validate_format($cohort->descriptionformat);
110 $cohort->id = cohort_add_cohort($cohort);
111
112 list($cohort->description, $cohort->descriptionformat) =
113 external_format_text($cohort->description, $cohort->descriptionformat,
114 $context->id, 'cohort', 'description', $cohort->id);
66d6221f 115 $cohortids[] = (array)$cohort;
088645e2
AB
116 }
117 $transaction->allow_commit();
118
119 return $cohortids;
120 }
121
122 /**
123 * Returns description of method result value
124 *
125 * @return external_description
66d6221f 126 * @since Moodle 2.5
088645e2
AB
127 */
128 public static function create_cohorts_returns() {
129 return new external_multiple_structure(
130 new external_single_structure(
131 array(
132 'id' => new external_value(PARAM_INT, 'cohort id'),
133 'name' => new external_value(PARAM_RAW, 'cohort name'),
134 'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
135 'description' => new external_value(PARAM_RAW, 'cohort description'),
136 'descriptionformat' => new external_format_value('description'),
80f98467 137 'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
088645e2
AB
138 )
139 )
140 );
141 }
142
143 /**
144 * Returns description of method parameters
145 *
146 * @return external_function_parameters
66d6221f 147 * @since Moodle 2.5
088645e2
AB
148 */
149 public static function delete_cohorts_parameters() {
150 return new external_function_parameters(
151 array(
152 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'cohort ID')),
153 )
154 );
155 }
156
157 /**
158 * Delete cohorts
159 *
160 * @param array $cohortids
161 * @return null
66d6221f 162 * @since Moodle 2.5
088645e2
AB
163 */
164 public static function delete_cohorts($cohortids) {
165 global $CFG, $DB;
166 require_once("$CFG->dirroot/cohort/lib.php");
167
168 $params = self::validate_parameters(self::delete_cohorts_parameters(), array('cohortids' => $cohortids));
169
170 $transaction = $DB->start_delegated_transaction();
171
172 foreach ($params['cohortids'] as $cohortid) {
173 // Validate params.
174 $cohortid = validate_param($cohortid, PARAM_INT);
175 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
176
177 // Now security checks.
178 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
179 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
180 throw new invalid_parameter_exception('Invalid context');
181 }
182 self::validate_context($context);
183 require_capability('moodle/cohort:manage', $context);
184 cohort_delete_cohort($cohort);
185 }
186 $transaction->allow_commit();
187
188 return null;
189 }
190
191 /**
192 * Returns description of method result value
193 *
194 * @return null
66d6221f 195 * @since Moodle 2.5
088645e2
AB
196 */
197 public static function delete_cohorts_returns() {
198 return null;
199 }
200
201 /**
202 * Returns description of method parameters
203 *
204 * @return external_function_parameters
66d6221f 205 * @since Moodle 2.5
088645e2
AB
206 */
207 public static function get_cohorts_parameters() {
208 return new external_function_parameters(
209 array(
210 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'Cohort ID')
cfd8c0fe 211 , 'List of cohort id. A cohort id is an integer.', VALUE_DEFAULT, array()),
088645e2
AB
212 )
213 );
214 }
215
216 /**
217 * Get cohorts definition specified by ids
218 *
219 * @param array $cohortids array of cohort ids
220 * @return array of cohort objects (id, courseid, name)
66d6221f 221 * @since Moodle 2.5
088645e2 222 */
cfd8c0fe 223 public static function get_cohorts($cohortids = array()) {
088645e2
AB
224 global $DB;
225
226 $params = self::validate_parameters(self::get_cohorts_parameters(), array('cohortids' => $cohortids));
227
cfd8c0fe
KB
228 if (empty($cohortids)) {
229 $cohorts = $DB->get_records('cohort');
230 } else {
231 $cohorts = $DB->get_records_list('cohort', 'id', $params['cohortids']);
232 }
088645e2 233
cfd8c0fe
KB
234 $cohortsinfo = array();
235 foreach ($cohorts as $cohort) {
088645e2
AB
236 // Now security checks.
237 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
238 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
239 throw new invalid_parameter_exception('Invalid context');
240 }
241 self::validate_context($context);
66d6221f
DW
242 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
243 throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
244 }
088645e2
AB
245
246 list($cohort->description, $cohort->descriptionformat) =
247 external_format_text($cohort->description, $cohort->descriptionformat,
248 $context->id, 'cohort', 'description', $cohort->id);
249
cfd8c0fe 250 $cohortsinfo[] = (array) $cohort;
088645e2 251 }
cfd8c0fe 252 return $cohortsinfo;
088645e2
AB
253 }
254
cfd8c0fe 255
088645e2
AB
256 /**
257 * Returns description of method result value
258 *
259 * @return external_description
66d6221f 260 * @since Moodle 2.5
088645e2
AB
261 */
262 public static function get_cohorts_returns() {
263 return new external_multiple_structure(
264 new external_single_structure(
265 array(
fb5ce7d3 266 'id' => new external_value(PARAM_INT, 'ID of the cohort'),
088645e2
AB
267 'name' => new external_value(PARAM_RAW, 'cohort name'),
268 'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
269 'description' => new external_value(PARAM_RAW, 'cohort description'),
270 'descriptionformat' => new external_format_value('description'),
80f98467 271 'visible' => new external_value(PARAM_BOOL, 'cohort visible'),
088645e2
AB
272 )
273 )
274 );
275 }
276
277 /**
278 * Returns description of method parameters
279 *
280 * @return external_function_parameters
66d6221f 281 * @since Moodle 2.5
088645e2
AB
282 */
283 public static function update_cohorts_parameters() {
284 return new external_function_parameters(
285 array(
286 'cohorts' => new external_multiple_structure(
287 new external_single_structure(
288 array(
fb5ce7d3 289 'id' => new external_value(PARAM_INT, 'ID of the cohort'),
088645e2
AB
290 'categorytype' => new external_single_structure(
291 array(
292 'type' => new external_value(PARAM_TEXT, 'the name of the field: id (numeric value
66d6221f
DW
293 of course category id) or idnumber (alphanumeric value of idnumber course category)
294 or system (value ignored)'),
088645e2
AB
295 'value' => new external_value(PARAM_RAW, 'the value of the categorytype')
296 )
297 ),
298 'name' => new external_value(PARAM_RAW, 'cohort name'),
299 'idnumber' => new external_value(PARAM_RAW, 'cohort idnumber'),
300 'description' => new external_value(PARAM_RAW, 'cohort description', VALUE_OPTIONAL),
301 'descriptionformat' => new external_format_value('description', VALUE_DEFAULT),
80f98467 302 'visible' => new external_value(PARAM_BOOL, 'cohort visible', VALUE_OPTIONAL),
088645e2
AB
303 )
304 )
305 )
306 )
307 );
308 }
309
310 /**
311 * Update cohorts
312 *
313 * @param array $cohorts
314 * @return null
66d6221f 315 * @since Moodle 2.5
088645e2
AB
316 */
317 public static function update_cohorts($cohorts) {
318 global $CFG, $DB;
319 require_once("$CFG->dirroot/cohort/lib.php");
320
321 $params = self::validate_parameters(self::update_cohorts_parameters(), array('cohorts' => $cohorts));
322
323 $transaction = $DB->start_delegated_transaction();
66d6221f 324 $syscontext = context_system::instance();
088645e2
AB
325
326 foreach ($params['cohorts'] as $cohort) {
327 $cohort = (object) $cohort;
328
329 if (trim($cohort->name) == '') {
330 throw new invalid_parameter_exception('Invalid cohort name');
331 }
332
66d6221f
DW
333 $oldcohort = $DB->get_record('cohort', array('id' => $cohort->id), '*', MUST_EXIST);
334 $oldcontext = context::instance_by_id($oldcohort->contextid, MUST_EXIST);
335 require_capability('moodle/cohort:manage', $oldcontext);
336
088645e2
AB
337 // Category type (context id).
338 $categorytype = $cohort->categorytype;
66d6221f
DW
339 if (!in_array($categorytype['type'], array('idnumber', 'id', 'system'))) {
340 throw new invalid_parameter_exception('category type must be id, idnumber or system:' . $categorytype['type']);
341 }
342 if ($categorytype['type'] === 'system') {
343 $cohort->contextid = $syscontext->id;
344 } else if ($catid = $DB->get_field('course_categories', 'id', array($categorytype['type'] => $categorytype['value']))) {
088645e2
AB
345 $cohort->contextid = $DB->get_field('context', 'id', array('instanceid' => $catid,
346 'contextlevel' => CONTEXT_COURSECAT));
347 } else {
348 throw new invalid_parameter_exception('category not exists: category='.$categorytype['value']);
349 }
350
66d6221f
DW
351 if ($cohort->contextid != $oldcohort->contextid) {
352 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
353 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
354 throw new invalid_parameter_exception('Invalid context');
355 }
356
357 self::validate_context($context);
358 require_capability('moodle/cohort:manage', $context);
088645e2 359 }
088645e2
AB
360
361 if (!empty($cohort->description)) {
362 $cohort->descriptionformat = external_validate_format($cohort->descriptionformat);
363 }
364
365 cohort_update_cohort($cohort);
366 }
367
368 $transaction->allow_commit();
369
370 return null;
371 }
372
373 /**
374 * Returns description of method result value
375 *
376 * @return null
66d6221f 377 * @since Moodle 2.5
088645e2
AB
378 */
379 public static function update_cohorts_returns() {
380 return null;
381 }
382
383 /**
384 * Returns description of method parameters
385 *
386 * @return external_function_parameters
66d6221f 387 * @since Moodle 2.5
088645e2
AB
388 */
389 public static function add_cohort_members_parameters() {
390 return new external_function_parameters (
391 array(
392 'members' => new external_multiple_structure (
393 new external_single_structure (
394 array (
395 'cohorttype' => new external_single_structure (
396 array(
397 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the field: id
398 (numeric value of cohortid) or idnumber (alphanumeric value of idnumber) '),
399 'value' => new external_value(PARAM_RAW, 'The value of the cohort')
400 )
401 ),
402 'usertype' => new external_single_structure (
403 array(
404 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the field: id
405 (numeric value of id) or username (alphanumeric value of username) '),
406 'value' => new external_value(PARAM_RAW, 'The value of the cohort')
407 )
408 )
409 )
410 )
411 )
412 )
413 );
414 }
415
416 /**
417 * Add cohort members
418 *
419 * @param array $members of arrays with keys userid, cohortid
66d6221f 420 * @since Moodle 2.5
088645e2
AB
421 */
422 public static function add_cohort_members($members) {
423 global $CFG, $DB;
424 require_once($CFG->dirroot."/cohort/lib.php");
425
426 $params = self::validate_parameters(self::add_cohort_members_parameters(), array('members' => $members));
427
428 $transaction = $DB->start_delegated_transaction();
429 $warnings = array();
430 foreach ($params['members'] as $member) {
431 // Cohort parameters.
432 $cohorttype = $member['cohorttype'];
433 $cohortparam = array($cohorttype['type'] => $cohorttype['value']);
434 // User parameters.
435 $usertype = $member['usertype'];
436 $userparam = array($usertype['type'] => $usertype['value']);
437 try {
438 // Check parameters.
439 if ($cohorttype['type'] != 'id' && $cohorttype['type'] != 'idnumber') {
440 $warning = array();
441 $warning['warningcode'] = '1';
442 $warning['message'] = 'invalid parameter: cohortype='.$cohorttype['type'];
443 $warnings[] = $warning;
444 continue;
445 }
446 if ($usertype['type'] != 'id' && $usertype['type'] != 'username') {
447 $warning = array();
448 $warning['warningcode'] = '1';
449 $warning['message'] = 'invalid parameter: usertype='.$usertype['type'];
450 $warnings[] = $warning;
451 continue;
452 }
453 // Extract parameters.
454 if (!$cohortid = $DB->get_field('cohort', 'id', $cohortparam)) {
455 $warning = array();
456 $warning['warningcode'] = '2';
457 $warning['message'] = 'cohort '.$cohorttype['type'].'='.$cohorttype['value'].' not exists';
458 $warnings[] = $warning;
459 continue;
460 }
461 if (!$userid = $DB->get_field('user', 'id', array_merge($userparam, array('deleted' => 0,
462 'mnethostid' => $CFG->mnet_localhost_id)))) {
463 $warning = array();
464 $warning['warningcode'] = '2';
465 $warning['message'] = 'user '.$usertype['type'].'='.$usertype['value'].' not exists';
466 $warnings[] = $warning;
467 continue;
468 }
469 if ($DB->record_exists('cohort_members', array('cohortid' => $cohortid, 'userid' => $userid))) {
470 $warning = array();
471 $warning['warningcode'] = '3';
472 $warning['message'] = 'record already exists: cohort('.$cohorttype['type'].'='.$cohorttype['value'].' '.
473 $usertype['type'].'='.$usertype['value'].')';
474 $warnings[] = $warning;
475 continue;
476 }
477 $cohort = $DB->get_record('cohort', array('id'=>$cohortid), '*', MUST_EXIST);
478 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
479 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
480 $warning = array();
481 $warning['warningcode'] = '1';
482 $warning['message'] = 'Invalid context: '.$context->contextlevel;
483 $warnings[] = $warning;
484 continue;
485 }
486 self::validate_context($context);
487 } catch (Exception $e) {
488 throw new moodle_exception('Error', 'cohort', '', $e->getMessage());
489 }
66d6221f
DW
490 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
491 throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
492 }
088645e2
AB
493 cohort_add_member($cohortid, $userid);
494 }
495 $transaction->allow_commit();
496 // Return.
497 $result = array();
498 $result['warnings'] = $warnings;
499 return $result;
500 }
501
502 /**
503 * Returns description of method result value
504 *
505 * @return null
66d6221f 506 * @since Moodle 2.5
088645e2
AB
507 */
508 public static function add_cohort_members_returns() {
509 return new external_single_structure(
510 array(
511 'warnings' => new external_warnings()
512 )
513 );
514 }
515
516 /**
517 * Returns description of method parameters
518 *
519 * @return external_function_parameters
66d6221f 520 * @since Moodle 2.5
088645e2
AB
521 */
522 public static function delete_cohort_members_parameters() {
523 return new external_function_parameters(
524 array(
525 'members' => new external_multiple_structure(
526 new external_single_structure(
527 array(
528 'cohortid' => new external_value(PARAM_INT, 'cohort record id'),
529 'userid' => new external_value(PARAM_INT, 'user id'),
530 )
531 )
532 )
533 )
534 );
535 }
536
537 /**
538 * Delete cohort members
539 *
540 * @param array $members of arrays with keys userid, cohortid
66d6221f 541 * @since Moodle 2.5
088645e2
AB
542 */
543 public static function delete_cohort_members($members) {
544 global $CFG, $DB;
545 require_once("$CFG->dirroot/cohort/lib.php");
546
547 // Validate parameters.
548 $params = self::validate_parameters(self::delete_cohort_members_parameters(), array('members' => $members));
549
550 $transaction = $DB->start_delegated_transaction();
551
552 foreach ($params['members'] as $member) {
553 $cohortid = $member['cohortid'];
554 $userid = $member['userid'];
555
556 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
557 $user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0, 'mnethostid' => $CFG->mnet_localhost_id),
558 '*', MUST_EXIST);
559
560 // Now security checks.
561 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
562 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
563 throw new invalid_parameter_exception('Invalid context');
564 }
565 self::validate_context($context);
66d6221f
DW
566 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:assign'), $context)) {
567 throw new required_capability_exception($context, 'moodle/cohort:assign', 'nopermissions', '');
568 }
088645e2
AB
569
570 cohort_remove_member($cohort->id, $user->id);
571 }
572 $transaction->allow_commit();
573 }
574
575 /**
576 * Returns description of method result value
577 *
578 * @return null
66d6221f 579 * @since Moodle 2.5
088645e2
AB
580 */
581 public static function delete_cohort_members_returns() {
582 return null;
583 }
584
585 /**
586 * Returns description of method parameters
587 *
588 * @return external_function_parameters
66d6221f 589 * @since Moodle 2.5
088645e2
AB
590 */
591 public static function get_cohort_members_parameters() {
592 return new external_function_parameters(
593 array(
594 'cohortids' => new external_multiple_structure(new external_value(PARAM_INT, 'Cohort ID')),
595 )
596 );
597 }
598
599 /**
600 * Return all members for a cohort
601 *
602 * @param array $cohortids array of cohort ids
603 * @return array with cohort id keys containing arrays of user ids
66d6221f 604 * @since Moodle 2.5
088645e2
AB
605 */
606 public static function get_cohort_members($cohortids) {
607 global $DB;
608 $params = self::validate_parameters(self::get_cohort_members_parameters(), array('cohortids' => $cohortids));
609
610 $members = array();
611
612 foreach ($params['cohortids'] as $cohortid) {
613 // Validate params.
614 $cohort = $DB->get_record('cohort', array('id' => $cohortid), '*', MUST_EXIST);
615 // Now security checks.
616 $context = context::instance_by_id($cohort->contextid, MUST_EXIST);
617 if ($context->contextlevel != CONTEXT_COURSECAT and $context->contextlevel != CONTEXT_SYSTEM) {
618 throw new invalid_parameter_exception('Invalid context');
619 }
620 self::validate_context($context);
66d6221f
DW
621 if (!has_any_capability(array('moodle/cohort:manage', 'moodle/cohort:view'), $context)) {
622 throw new required_capability_exception($context, 'moodle/cohort:view', 'nopermissions', '');
623 }
088645e2
AB
624
625 $cohortmembers = $DB->get_records_sql("SELECT u.id FROM {user} u, {cohort_members} cm
626 WHERE u.id = cm.userid AND cm.cohortid = ?
627 ORDER BY lastname ASC, firstname ASC", array($cohort->id));
628 $members[] = array('cohortid' => $cohortid, 'userids' => array_keys($cohortmembers));
629 }
630 return $members;
631 }
632
633 /**
634 * Returns description of method result value
635 *
636 * @return external_description
66d6221f 637 * @since Moodle 2.5
088645e2
AB
638 */
639 public static function get_cohort_members_returns() {
640 return new external_multiple_structure(
641 new external_single_structure(
642 array(
643 'cohortid' => new external_value(PARAM_INT, 'cohort record id'),
644 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user id')),
645 )
646 )
647 );
648 }
66d6221f 649}