MDL-8096 - refactored and cleanedup custom profiles, user edit form fixes
[moodle.git] / user / profile / definelib.php
CommitLineData
bb6d3d34 1<?php //$Id$
2
3class profile_define_base {
4
5 /**
6 * Prints out the form snippet for creating or editing a profile field
7 * @param object instance of the moodleform class
8 */
9 function define_form(&$form) {
10 $form->addElement('header', '_commonsettings', get_string('profilecommonsettings', 'admin'));
11 $this->define_form_common($form);
12
13 $form->addElement('header', '_specificsettings', get_string('profilespecificsettings', 'admin'));
14 $this->define_form_specific($form);
15 }
16
17 /**
18 * Prints out the form snippet for the part of creating or
19 * editing a profile field common to all data types
20 * @param object instance of the moodleform class
21 */
22 function define_form_common(&$form) {
23
24 $strrequired = get_string('required');
25
26 $form->addElement('text', 'shortname', get_string('profileshortname', 'admin'), 'maxlength="100" size="30"');
27 $form->addRule('shortname', $strrequired, 'required', null, 'client');
28 $form->setType('shortname', PARAM_ALPHANUM);
29
30 $form->addElement('text', 'name', get_string('profilename', 'admin'), 'size="30"');
31 $form->addRule('name', $strrequired, 'required', null, 'client');
32 $form->setType('name', PARAM_MULTILANG);
33
34 $form->addElement('htmleditor', 'description', get_string('profiledescription', 'admin'));
35 $form->setHelpButton('description', array('text', get_string('helptext')));
36 $form->setType('description', PARAM_MULTILANG);
37
38 $form->addElement('selectyesno', 'required', get_string('profilerequired', 'admin'));
39
40 $form->addElement('selectyesno', 'locked', get_string('profilelocked', 'admin'));
41
42 $choices = array();
43 $choices[PROFILE_VISIBLE_NONE] = get_string('profilevisiblenone', 'admin');
44 $choices[PROFILE_VISIBLE_PRIVATE] = get_string('profilevisibleprivate', 'admin');
45 $choices[PROFILE_VISIBLE_ALL] = get_string('profilevisibleall', 'admin');
46 $form->addElement('select', 'visible', get_string('profilevisible', 'admin'), $choices);
47 $form->setHelpButton('visible', array('profilevisible', get_string('profilevisible','admin')));
48 $form->setDefault('visible', PROFILE_VISIBLE_ALL);
49
50 $choices = profile_list_categories();
51 $form->addElement('select', 'categoryid', get_string('profilecategory', 'admin'), $choices);
52 }
53
54 /**
55 * Prints out the form snippet for the part of creating or
56 * editing a profile field specific to the current data type
57 * @param object instance of the moodleform class
58 */
59 function define_form_specific(&$form) {
60 /// do nothing - overwrite if necessary
61 }
62
63 /**
64 * Validate the data from the add/edit profile field form.
65 * Generally this method should not be overwritten by child
66 * classes.
67 * @param object data from the add/edit profile field form
68 * @return array associative array of error messages
69 */
70 function define_validate($data) {
71
72 $data = (object)$data;
73 $err = array();
74
75 $err += $this->define_validate_common($data);
76 $err += $this->define_validate_specific($data);
77
78 if (count($err) == 0){
79 return true;
80 } else {
81 return $err;
82 }
83 }
84
85 /**
86 * Validate the data from the add/edit profile field form
87 * that is common to all data types. Generally this method
88 * should not be overwritten by child classes.
89 * @param object data from the add/edit profile field form
90 * @return array associative array of error messages
91 */
92 function define_validate_common($data) {
93 $err = array();
94
95 /// Check the shortname is unique
96 if (($field = get_record('user_info_field', 'shortname', $data->shortname)) and ($field->id <> $data->id)) {
97 //if (record_exists_select('user_info_field', 'shortname='.$data->shortname.' AND id<>'.$data->id)) {
98 $err['shortname'] = get_string('profileshortnamenotunique', 'admin');
99 }
100
101 /// No further checks necessary as the form class will take care of it
102
103 return $err;
104 }
105
106 /**
107 * Validate the data from the add/edit profile field form
108 * that is specific to the current data type
109 * @param object data from the add/edit profile field form
110 * @return array associative array of error messages
111 */
112 function define_validate_specific($data) {
113 /// do nothing - overwrite if necessary
114 return array();
115 }
116
117 /**
118 * Alter form based on submitted or existing data
119 * @param object form
120 */
121 function define_after_data(&$mform) {
122 /// do nothing - overwrite if necessary
123 }
124
125 /**
126 * Add a new profile field or save changes to current field
127 * @param object data from the add/edit profile field form
128 * @return boolean status of the insert/update record
129 */
130 function define_save($data) {
131
132 $data = $this->define_save_preprocess($data); /// hook for child classes
133
134 $old = get_record('user_info_field', 'id', $data->id);
135
136 /// check to see if the category has changed
137 if (!$old or $old->categoryid != $data->categoryid) {
138 $data->sortorder = count_records_select('user_info_field', 'categoryid='.$data->categoryid) + 1;
139 }
140
141
142 if (empty($data->id)) {
143 unset($data->id);
144 if (!$data->id = insert_record('user_info_field', $data)) {
145 error('Error creating new field');
146 }
147 } else {
148 if (!update_record('user_info_field', $data)) {
149 error('Error updating field');
150 }
151 }
152 }
153
154 /**
155 * Preprocess data from the add/edit profile field form
156 * before it is saved. This method is a hook for the child
157 * classes to overwrite.
158 * @param object data from the add/edit profile field form
159 * @return object processed data object
160 */
161 function define_save_preprocess($data) {
162 /// do nothing - overwrite if necessary
163 return $data;
164 }
165
166}
167
168
169
170/**
171 * Reorder the profile fields within a given category starting
172 * at the field at the given startorder
173 */
174function profile_reorder_fields() {
175 if ($categories = get_records_select('user_info_category')) {
176 $i = 1;
177 foreach ($categories as $category) {
178 if ($fields = get_records_select('user_info_field', 'categoryid='.$category->id, 'sortorder ASC')) {
179 foreach ($fields as $field) {
180 $f = new object();
181 $f->if = $field->id;
182 $f->sortorder = $i++;
183 update_record('user_info_field', $f);
184 }
185 }
186 }
187 }
188}
189
190/**
191 * Reorder the profile categoriess starting at the category
192 * at the given startorder
193 */
194function profile_reorder_categories() {
195 $i = 1;
196 if ($categories = get_records_select('user_info_category', '', 'sortorder ASC')) {
197 foreach ($categories as $cat) {
198 $c = new object();
199 $c->id = $cat->id;
200 $c->sortorder = $i++;
201 update_record('user_info_category', $c);
202 }
203 }
204}
205
206/**
207 * Delete a profile category
208 * @param integer id of the category to be deleted
209 * @return boolean success of operation
210 */
211function profile_delete_category($id) {
212 /// Retrieve the category
213 if (!$category = get_record('user_info_category', 'id', $id)) {
214 error('Incorrect category id');
215 }
216
217 if (!$categories = get_records_select('user_info_category', '', 'sortorder ASC')) {
218 error('Error no categories!?!?');
219 }
220
221 unset($categories[$category->id]);
222
223 if (!count($categories)) {
224 return; //we can not delete the last category
225 }
226
227 /// Does the category contain any fields
228 if (count_records('user_info_field', 'categoryid', $category->id)) {
229 if (array_key_exists($category->sortorder-1, $categories)) {
230 $newcategory = $categories[$category->sortorder-1];
231 } else if (array_key_exists($category->sortorder+1, $categories)) {
232 $newcategory = $categories[$category->sortorder+1];
233 } else {
234 $newcategory = reset($categories); // get first category if sortorder broken
235 }
236
237 $sortorder = count_records('user_info_field', 'categoryid', $newcategory->id) + 1;
238
239 if ($fields = get_records_select('user_info_field', 'categoryid='.$category->id, 'sortorder ASC')) {
240 foreach ($fields as $field) {
241 $f = new object();
242 $f->id = $field->id;
243 $f->sortorder = $sortorder++;
244 $f->categoryid = $newcategory->id;
245 update_record('user_info_field', $f);
246 echo "<pre>";var_dump($f);echo"</pre>";
247 }
248 }
249 }
250
251 /// Finally we get to delete the category
252 if (!delete_records('user_info_category', 'id', $category->id)) {
253 error('Error while deliting category');
254 }
255 profile_reorder_categories();
256 return true;
257}
258
259
260function profile_delete_field($id) {
261
262 /// Remove any user data associated with this field
263 if (!delete_records('user_info_data', 'fieldid', $id)) {
264 error('Error deleting custom field data');
265 }
266
267 /// Try to remove the record from the database
268 delete_records('user_info_field', 'id', $id);
269
270 /// Reorder the remaining fields in the same category
271 profile_reorder_fields();
272}
273
274/**
275 * Change the sortorder of a field
276 * @param integer id of the field
277 * @param string direction of move
278 * @return boolean success of operation
279 */
280function profile_move_field ($id, $move) {
281 /// Get the field object
282 if (!$field = get_record('user_info_field', 'id', $id, '', '', '', '', 'id, sortorder, categoryid')) {
283 return false;
284 }
285 /// Count the number of fields in this category
286 $fieldcount = count_records_select('user_info_field', 'categoryid='.$field->categoryid);
287
288 /// Calculate the new sortorder
289 if ( ($move == 'up') and ($field->sortorder > 1)) {
290 $neworder = $field->sortorder - 1;
291 } elseif ( ($move == 'down') and ($field->sortorder < $fieldcount)) {
292 $neworder = $field->sortorder + 1;
293 } else {
294 return false;
295 }
296
297 /// Retrieve the field object that is currently residing in the new position
298 if ($swapfield = get_record('user_info_field', 'categoryid', $field->categoryid, 'sortorder', $neworder, '', '', 'id, sortorder')) {
299
300 /// Swap the sortorders
301 $swapfield->sortorder = $field->sortorder;
302 $field->sortorder = $neworder;
303
304 /// Update the field records
305 update_record('user_info_field', $field);
306 update_record('user_info_field', $swapfield);
307 }
308
309 profile_reorder_fields();
310}
311
312/**
313 * Change the sortorder of a category
314 * @param integer id of the category
315 * @param string direction of move
316 * @return boolean success of operation
317 */
318function profile_move_category ($id, $move) {
319 /// Get the category object
320 if (!($category = get_record('user_info_category', 'id', $id, '', '', '', '', 'id, sortorder'))) {
321 return false;
322 }
323
324 /// Count the number of categories
325 $categorycount = count_records('user_info_category');
326
327 /// Calculate the new sortorder
328 if ( ($move == 'up') and ($category->sortorder > 1)) {
329 $neworder = $category->sortorder - 1;
330 } elseif ( ($move == 'down') and ($category->sortorder < $categorycount)) {
331 $neworder = $category->sortorder + 1;
332 } else {
333 return false;
334 }
335
336 /// Retrieve the category object that is currently residing in the new position
337 if ($swapcategory = get_record('user_info_category', 'sortorder', $neworder, '', '', '', '', 'id, sortorder')) {
338
339 /// Swap the sortorders
340 $swapcategory->sortorder = $category->sortorder;
341 $category->sortorder = $neworder;
342
343 /// Update the category records
344 if (update_record('user_info_category', $category) and update_record('user_info_category', $swapcategory)) {
345 return true;
346 }
347 }
348
349 return false;
350}
351
352/**
353 * Retrieve a list of all the available data types
354 * @return array a list of the datatypes suitable to use in a select statement
355 */
356function profile_list_datatypes() {
357 global $CFG;
358
359 $datatypes = array();
360
361 if ($dirlist = get_directory_list($CFG->dirroot.'/user/profile/field', '', false, true, false)) {
362 foreach ($dirlist as $type) {
363 $datatypes[$type] = get_string('profilefieldtype'.$type, 'admin');
364 }
365 }
366 return $datatypes;
367}
368
369/**
370 * Retrieve a list of categories and ids suitable for use in a form
371 * @return array
372 */
373function profile_list_categories() {
374 if (!$categories = get_records_select_menu('user_info_category', '', 'sortorder ASC', 'id, name')) {
375 $categories = array();
376 }
377 return $categories;
378}
379
380
381/// Are we adding or editing a cateogory?
382function profile_edit_category($id, $redirect, $adminroot) {
383 global $CFG;
384
385 require_once('index_category_form.php');
386 $categoryform = new category_form();
387
388 if ($category = get_record('user_info_category', 'id', $id)) {
389 $categoryform->set_data($category);
390 }
391
392 if ($categoryform->is_cancelled()) {
393 redirect($redirect);
394 } else {
395 if ($data = $categoryform->get_data()) {
396 if (empty($data->id)) {
397 unset($data->id);
398 $data->sortorder = count_records('user_info_category') + 1;
399 if (!insert_record('user_info_category', $data, false)) {
400 error('There was a problem adding the record to the database');
401 }
402 } else {
403 if (!update_record('user_info_category', $data)) {
404 error('There was a problem updating the record in the database');
405 }
406 }
407 profile_reorder_categories();
408 redirect($redirect);
409
410 }
411
412 if (empty($id)) {
413 $strheading = get_string('profilecreatenewcategory', 'admin');
414 } else {
415 $strheading = get_string('profileeditcategory', 'admin', $category->name);
416 }
417
418 /// Print the page
419 admin_externalpage_print_header($adminroot);
420 print_heading($strheading);
421 $categoryform->display();
422 admin_externalpage_print_footer($adminroot);
423 die;
424 }
425
426}
427
428function profile_edit_field($id, $datatype, $redirect, $adminroot) {
429 global $CFG;
430
431 if (!$field = get_record('user_info_field', 'id', $id)) {
432 $field = new object();
433 $field->datatype = $datatype;
434 }
435
436 require_once('index_field_form.php');
437 $fieldform = new field_form(null, $field->datatype);
438 $fieldform->set_data($field);
439
440 if ($fieldform->is_cancelled()) {
441 redirect($redirect);
442
443 } else {
444 if ($data = $fieldform->get_data()) {
445 require_once($CFG->dirroot.'/user/profile/field/'.$datatype.'/define.class.php');
446 $newfield = 'profile_define_'.$datatype;
447 $formfield = new $newfield();
448 $formfield->define_save($data);
449 profile_reorder_fields();
450 profile_reorder_categories();
451 redirect($redirect);
452 }
453
454 $datatypes = profile_list_datatypes();
455
456 if (empty($id)) {
457 $strheading = get_string('profilecreatenewfield', 'admin', $datatypes[$datatype]);
458 } else {
459 $strheading = get_string('profileeditfield', 'admin', $field->name);
460 }
461
462 /// Print the page
463 admin_externalpage_print_header($adminroot);
464 print_heading($strheading);
465 $fieldform->display();
466 admin_externalpage_print_footer($adminroot);
467 die;
468 }
469}
470
471?>