profile.module 16.2 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
Dries's avatar
Dries committed
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
   
Dries committed
4
// TODO: add a 'date' field so we can migrate the birthday information.
Dries's avatar
   
Dries committed
5

6
7
8
9
10
11
12
/**
 * Flags to define the visibility of a profile field.
 */
define('PROFILE_PRIVATE', 1);
define('PROFILE_PUBLIC', 2);
define('PROFILE_PUBLIC_LISTINGS', 3);

Dries's avatar
   
Dries committed
13
14
15
/**
 * Implementation of hook_help().
 */
Dries's avatar
   
Dries committed
16
function profile_help($section) {
Dries's avatar
   
Dries committed
17
  switch ($section) {
Dries's avatar
   
Dries committed
18
19
    case 'admin/modules#description':
      return t('Support for configurable user profiles.');
Dries's avatar
   
Dries committed
20
21
22
  }
}

Dries's avatar
   
Dries committed
23
/**
Dries's avatar
   
Dries committed
24
 * Implementation of hook_menu().
Dries's avatar
   
Dries committed
25
 */
Dries's avatar
   
Dries committed
26
function profile_menu() {
27
28
  global $user;

Dries's avatar
   
Dries committed
29
30
31
32
33
34
35
36
  $items = array();
  $items[] = array('path' => 'profile', 'title' => t('browse'),
    'callback' => 'profile_browse',
    'access' => TRUE,
    'type' => MENU_SUGGESTED_ITEM);
  $items[] = array('path' => 'admin/user/configure/profile', 'title' => t('profiles'),
    'callback' => 'profile_admin_overview',
    'access' => user_access('administer users'),
Dries's avatar
   
Dries committed
37
    'type' => MENU_LOCAL_TASK);
Dries's avatar
   
Dries committed
38
  $items[] = array('path' => 'admin/user/configure/profile/add', 'title' => t('add field'),
Dries's avatar
   
Dries committed
39
    'callback' => 'profile_admin_add',
Dries's avatar
   
Dries committed
40
41
42
    'access' => user_access('administer users'),
    'type' => MENU_CALLBACK);
  $items[] = array('path' => 'admin/user/configure/profile/edit', 'title' => t('edit field'),
Dries's avatar
   
Dries committed
43
    'callback' => 'profile_admin_edit',
Dries's avatar
   
Dries committed
44
45
46
    'access' => user_access('administer users'),
    'type' => MENU_CALLBACK);
  $items[] = array('path' => 'admin/user/configure/profile/delete', 'title' => t('delete field'),
Dries's avatar
   
Dries committed
47
    'callback' => 'profile_admin_delete',
Dries's avatar
   
Dries committed
48
49
    'access' => user_access('administer users'),
    'type' => MENU_CALLBACK);
50

Dries's avatar
   
Dries committed
51
  return $items;
Dries's avatar
   
Dries committed
52
}
Dries's avatar
 
Dries committed
53

Dries's avatar
   
Dries committed
54
55
56
/**
 * Menu callback; display a list of user information.
 */
Dries's avatar
   
Dries committed
57
function profile_browse() {
Dries's avatar
   
Dries committed
58

59
60
  $name = strip_tags(arg(1));
  $value = strip_tags(arg(2));
Dries's avatar
   
Dries committed
61

62
  $field = db_fetch_object(db_query("SELECT DISTINCT(fid), type, title, page FROM {profile_fields} WHERE name = '%s'", $name));
Dries's avatar
 
Dries committed
63

Dries's avatar
   
Dries committed
64
  if ($field->fid) {
65
    // Compile a list of fields to show
Dries's avatar
   
Dries committed
66
    $fields = array();
67
    $result = db_query('SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND visibility = %d', $field->fid, PROFILE_PUBLIC_LISTINGS);
Dries's avatar
   
Dries committed
68
69
70
    while ($record = db_fetch_object($result)) {
      $fields[] = $record;
    }
Dries's avatar
 
Dries committed
71

Dries's avatar
Dries committed
72
73
74
75
76
77
    // Determine what query to use:
    switch ($field->type) {
      case 'checkbox':
        $query = 'v.value = 1';
        break;
      case 'selection':
78
        $query = "v.value = '". check_query($value) ."'";
Dries's avatar
Dries committed
79
80
        break;
      case 'list':
81
        $query = "v.value LIKE '%". check_query($value) ."%'";
Dries's avatar
Dries committed
82
83
84
        break;
    }

Dries's avatar
   
Dries committed
85
    // Extract the affected users:
Dries's avatar
   
Dries committed
86
    $result = pager_query("SELECT u.uid FROM {users} u INNER JOIN {profile_values} v ON u.uid = v.uid WHERE v.fid = %d AND $query ORDER BY u.changed DESC", 20, 0, NULL, $field->fid);
Dries's avatar
 
Dries committed
87

Dries's avatar
   
Dries committed
88
    $output = '<div id="profile">';
Dries's avatar
   
Dries committed
89
90
91
92
93
    while ($account = db_fetch_object($result)) {
      $output .= theme('profile_profile', user_load(array('uid' => $account->uid)), $fields);
    }
    $output .= theme('pager', NULL, 20);

Dries's avatar
Dries committed
94
    if ($field->type == 'selection' || $field->type == 'list') {
95
      $title = strtr($field->page, array('%value' => $value));
Dries's avatar
   
Dries committed
96
97
    }
    else {
Dries's avatar
   
Dries committed
98
      $title = $field->page;
Dries's avatar
   
Dries committed
99
    }
Dries's avatar
   
Dries committed
100
    $output .= '</div>';
Dries's avatar
   
Dries committed
101
102
103
104
105

    print theme('page', $output, $title);
  }
  else {
    drupal_not_found();
Dries's avatar
 
Dries committed
106
  }
Dries's avatar
   
Dries committed
107
}
Dries's avatar
 
Dries committed
108

Dries's avatar
   
Dries committed
109
110
111
112
113
114
function profile_load_profile(&$user) {
  $result = db_query('SELECT f.name, v.value FROM {profile_fields} f INNER JOIN {profile_values} v ON f.fid = v.fid WHERE uid = %d', $user->uid);
  while ($field = db_fetch_object($result)) {
    if (empty($user->{$field->name})) {
      $user->{$field->name} = $field->value;
    }
Dries's avatar
   
Dries committed
115
  }
Dries's avatar
 
Dries committed
116
117
}

118
119
function profile_save_profile(&$edit, &$user, $category) {
  $result = db_query("SELECT fid, name FROM {profile_fields} WHERE LOWER(category) = '%s'", strtolower($category));
Dries's avatar
   
Dries committed
120
  while ($field = db_fetch_object($result)) {
121
122
123
    db_query("DELETE FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $user->uid);
    db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]);
    unset($edit[$field->name], $user->{$field->name});
Dries's avatar
   
Dries committed
124
  }
Dries's avatar
 
Dries committed
125
126
}

127
128
129
130
131
132
133
function profile_view_field($user, $field) {
  if ($value = $user->{$field->name}) {
    switch ($field->type) {
      case 'textfield':
      case 'textarea':
        return check_output($value);
      case 'selection':
134
        return l($value, "profile/$field->name/". drupal_specialchars($value));
135
      case 'checkbox':
Dries's avatar
Dries committed
136
        return l($field->title, "profile/$field->name");
137
      case 'url':
138
139
        return '<a href="'. check_url(strip_tags($value)) .'">'. strip_tags($value) .'</a>';
      case 'list':
Dries's avatar
   
Dries committed
140
        $values = split("[,\n\r]", $value);
Dries's avatar
Dries committed
141
142
143
        $fields = array();
        foreach ($values as $value) {
          if ($value = trim(strip_tags($value))) {
144
            $fields[] = l($value, "profile/$field->name/". drupal_specialchars($value));
Dries's avatar
Dries committed
145
146
147
          }
        }
        return implode(', ', $fields);
148
149
150
151
    }
  }
}

Dries's avatar
   
Dries committed
152
function profile_view_profile($user) {
Dries's avatar
 
Dries committed
153

154
  profile_load_profile($user);
Dries's avatar
 
Dries committed
155

156
  $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_PRIVATE);
Dries's avatar
   
Dries committed
157
  while ($field = db_fetch_object($result)) {
158
159
    if ($value = profile_view_field($user, $field)) {
      if ($field->type == 'checkbox') {
Dries's avatar
Dries committed
160
        $fields[$field->category] .= "<p>$value</p>";
161
162
      }
      else {
Dries's avatar
Dries committed
163
        $fields[$field->category] .= form_item($field->title, check_output($value));
Dries's avatar
   
Dries committed
164
      }
Dries's avatar
 
Dries committed
165
166
167
    }
  }

Dries's avatar
Dries committed
168
  return $fields;
Dries's avatar
   
Dries committed
169
}
Dries's avatar
 
Dries committed
170

171
172
function _profile_form_explanation($field) {
  $output = $field->explanation;
Dries's avatar
   
Dries committed
173

174
  if ($field->type == 'list') {
Dries's avatar
   
Dries committed
175
    $output .= ' '. t('Put each item on a separate line or separate them by commas.  No HTML allowed.');
176
177
178
179
180
181
182
183
184
185
186
187
  }

  if ($field->visibility == PROFILE_PRIVATE) {
    $output .= ' '. t('The content of this field is kept private and will not be shown publicly.');
  }

  return $output;
}

function profile_form_profile($edit, $user, $category) {

  $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = '%s' ORDER BY weight", strtolower($category));
Dries's avatar
   
Dries committed
188
189
190
191

  while ($field = db_fetch_object($result)) {
    switch ($field->type) {
      case 'textfield':
192
      case 'url':
193
        $output .= form_textfield($field->title, $field->name, $edit[$field->name], 70, 255, _profile_form_explanation($field), NULL, $field->required);
Dries's avatar
   
Dries committed
194
195
        break;
      case 'textarea':
196
        $output .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, _profile_form_explanation($field), NULL, $field->required);
Dries's avatar
Dries committed
197
198
        break;
      case 'list':
199
        $output .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, _profile_form_explanation($field), NULL, $field->required);
Dries's avatar
   
Dries committed
200
201
        break;
      case 'checkbox':
202
        $output .= form_checkbox($field->title, $field->name, 1, $edit[$field->name], _profile_form_explanation($field), NULL, $field->required);
Dries's avatar
   
Dries committed
203
204
205
        break;
      case 'selection':
        $options = array('--');
Dries's avatar
   
Dries committed
206
        $lines = split("[,\n\r]", $field->options);
Dries's avatar
   
Dries committed
207
208
209
210
211
212
        foreach ($lines as $line) {
          if ($line = trim($line)) {
            $options[$line] = $line;
          }
        }

213
        $output .= form_select($field->title, $field->name, $edit[$field->name], $options, _profile_form_explanation($field), 0, 0, $field->required);
Dries's avatar
   
Dries committed
214
        break;
Dries's avatar
 
Dries committed
215
216
217
    }
  }

218
219
220
  if ($output) {
    return array(array('title' => $category, 'data' => $output));
  }
Dries's avatar
 
Dries committed
221
222
}

223
224
function profile_validate_profile($edit, $category) {
  $result = db_query("SELECT * FROM {profile_fields} WHERE LOWER(category) = '%s' ORDER BY weight", strtolower($category));
225
226

  while ($field = db_fetch_object($result)) {
227
    if ($edit[$field->name]) {
Dries's avatar
   
Dries committed
228
229
230
231
      if ($field->type == 'url') {
        if (!valid_url($edit[$field->name], true)) {
          form_set_error($field->name, t('The value provided for "%field" is not a valid URL.', array('%field' => $field->title)));
         }
232
233
      }
    }
234
    else if ($field->required && !user_access('administer users')) {
Dries's avatar
   
Dries committed
235
      form_set_error($field->name, t('The field "%field" is required.', array('%field' => $field->title)));
Dries's avatar
   
Dries committed
236
    }
237
238
239
240
241
  }

  return $edit;
}

242
243
244
function profile_categories() {
  $result = db_query("SELECT DISTINCT(category) FROM {profile_fields}");
  while ($category = db_fetch_object($result)) {
245
    $data[] = array('name' => drupal_specialchars(strtolower($category->category)), 'title' => strtolower($category->category), 'weight' => 3);
246
247
248
249
  }
  return $data;
}

Dries's avatar
   
Dries committed
250
251
252
/**
 * Implementation of hook_user().
 */
253
function profile_user($type, &$edit, &$user, $category = NULL) {
Dries's avatar
   
Dries committed
254
255
256
257
  switch ($type) {
    case 'load':
      return profile_load_profile($user);
    case 'update':
258
    case 'insert':
259
      return profile_save_profile($edit, $user, $category);
Dries's avatar
   
Dries committed
260
261
    case 'view':
      return profile_view_profile($user);
262
    case 'form':
263
      return profile_form_profile($edit, $user, $category);
Dries's avatar
   
Dries committed
264
    case 'validate':
265
266
267
      return profile_validate_profile($edit, $category);
    case 'categories':
      return profile_categories();
Dries's avatar
   
Dries committed
268
269
  }
}
Dries's avatar
   
Dries committed
270

Dries's avatar
   
Dries committed
271
function profile_validate_form($edit) {
Dries's avatar
 
Dries committed
272

Dries's avatar
   
Dries committed
273
  // Validate the title:
Dries's avatar
 
Dries committed
274

Dries's avatar
   
Dries committed
275
  if (!$edit['title']) {
Dries's avatar
   
Dries committed
276
    form_set_error('title', t('You must enter a title.'));
Dries's avatar
 
Dries committed
277
278
  }

Dries's avatar
   
Dries committed
279
  // Validate the 'form name':
Dries's avatar
 
Dries committed
280

Dries's avatar
   
Dries committed
281
  if (eregi('[^a-z0-9_-]', $edit['name'])) {
Dries's avatar
   
Dries committed
282
    form_set_error('name', t('The specified form name contains one or more illegal characters.  Spaces or any other special characters expect dash (-) and underscore (_) are not allowed.'));
Dries's avatar
 
Dries committed
283
284
  }

Dries's avatar
   
Dries committed
285
  if (in_array($edit['name'], user_fields())) {
Dries's avatar
   
Dries committed
286
    form_set_error('name', t('The specified form name is reserved for use by Drupal.'));
Dries's avatar
 
Dries committed
287
288
  }

Dries's avatar
   
Dries committed
289
290
  // Validate the category:
  if (!$edit['category']) {
Dries's avatar
   
Dries committed
291
    form_set_error('category', t('You must enter a category.'));
Dries's avatar
   
Dries committed
292
  }
Dries's avatar
 
Dries committed
293
294
}

Dries's avatar
   
Dries committed
295
296
297
/**
 * Menu callback; adds a new field to all user profiles.
 */
Dries's avatar
   
Dries committed
298
299
function profile_admin_add($type) {
  $type = _profile_field_types($type);
Dries's avatar
 
Dries committed
300

301

Dries's avatar
   
Dries committed
302
303
  if ($_POST['op']) {
    $data = $_POST['edit'];
Dries's avatar
 
Dries committed
304

Dries's avatar
   
Dries committed
305
306
307
308
309
    // Validate the form:
    profile_validate_form($data);

    if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE title = '%s'", $data['title']))) {
      form_set_error('title', t('the specified title is already in use.'));
310
    }
Dries's avatar
   
Dries committed
311
312
313

    if (db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", $data['name']))) {
      form_set_error('name', t('the specified name is already in use.'));
314
    }
Dries's avatar
   
Dries committed
315

Dries's avatar
   
Dries committed
316
    if (!form_get_errors()) {
317
      db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, visibility, options, page) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s')", $data['title'], $data['name'], $data['explanation'], $data['category'], $type, $data['weight'], $data['required'], $data['visibility'], $data['options'], $data['page']);
Dries's avatar
 
Dries committed
318

Dries's avatar
   
Dries committed
319
      drupal_set_message(t('the field has been created.'));
Dries's avatar
   
Dries committed
320
      drupal_goto('admin/user/configure/profile');
Dries's avatar
   
Dries committed
321
    }
Dries's avatar
   
Dries committed
322
  }
Dries's avatar
   
Dries committed
323
324
325
326
327
  else {
    $data = array('name' => 'profile_');
  }

  print theme('page', _profile_field_form($type, $data), t('Add new %type', array('%type' => $type)));
Dries's avatar
   
Dries committed
328
329
}

Dries's avatar
   
Dries committed
330
331
332
/**
 * Menu callback; displays the profile field editing form.
 */
Dries's avatar
   
Dries committed
333
function profile_admin_edit($fid) {
Dries's avatar
 
Dries committed
334

Dries's avatar
   
Dries committed
335
336
  if ($_POST['op']) {
    $data = $_POST['edit'];
Dries's avatar
 
Dries committed
337

Dries's avatar
   
Dries committed
338
339
    // Validate form:
    profile_validate_form($data);
Dries's avatar
 
Dries committed
340

Dries's avatar
   
Dries committed
341
    if (!form_get_errors()) {
342
      db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, visibility = %d, options = '%s', page = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['required'], $data['visibility'], $data['options'], $data['page'], $fid);
Dries's avatar
   
Dries committed
343
344

      drupal_set_message(t('the field has been updated.'));
Dries's avatar
   
Dries committed
345
      drupal_goto('admin/user/configure/profile');
Dries's avatar
   
Dries committed
346
    }
Dries's avatar
   
Dries committed
347
348
  }
  else {
Dries's avatar
   
Dries committed
349
    $data = db_fetch_array(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
Dries's avatar
 
Dries committed
350
351
  }

Dries's avatar
   
Dries committed
352
  print theme('page', _profile_field_form($data['type'], $data), t('Edit %type', array('%type' => $data['type'])));
Dries's avatar
 
Dries committed
353
354
}

Dries's avatar
   
Dries committed
355
356
357
/**
 * Menu callback; deletes a field from all user profiles.
 */
Dries's avatar
   
Dries committed
358
359
360
function profile_admin_delete($fid) {
  db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid);
  drupal_set_message(t('the field has been deleted.'));
Dries's avatar
   
Dries committed
361
  drupal_goto('admin/user/configure/profile');
Dries's avatar
 
Dries committed
362
363
}

Dries's avatar
   
Dries committed
364
365
function _profile_field_form($type, $edit = array()) {

Dries's avatar
   
Dries committed
366
367
368
369
370
  $group  = form_textfield(t('Category'), 'category', $edit['category'], 70, 128, t('The category the new field should be part of.  Categories are used to group fields logically.  An example category is "Personal information".'));
  $group .= form_textfield(t('Title'), 'title', $edit['title'], 70, 128, t('The title of the new field.  The title will be shown to the user.  An example title is "Favorite color".'));
  $group .= form_textfield(t('Form name'), 'name', $edit['name'], 70, 128, t('The name of the field.  The form name is not shown to the user but used internally in the HTML code and URLs.
Unless you know what you are doing, it is highly recommended that you prefix the form name with <code>profile_</code> to avoid name clashes with other fields.  Spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example name is "profile_favorite_color" or perhaps just "profile_color".'));
  $group .= form_textarea(t('Explanation'), 'explanation', $edit['explanation'], 70, 3, t('An optional explanation to go with the new field.  The explanation will be shown to the user.'));
Dries's avatar
   
Dries committed
371
  if ($type == 'selection') {
Dries's avatar
   
Dries committed
372
    $group .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t('A list of all options.  Put each option on a separate line.  Example options are "red", "blue", "green", etc.'));
Dries's avatar
   
Dries committed
373
  }
Dries's avatar
   
Dries committed
374
  $group .= form_weight(t('Weight'), 'weight', $edit['weight'], 5, t('The weights define the order in which the form fields are shown.  Lighter fields "float up" towards the top of the category.'));
375
  $group .= form_radios(t('Visibility'), 'visibility', $edit['visibility'], array(PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')));
Dries's avatar
Dries committed
376
  if ($type == 'selection' || $type == 'list') {
377
    $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field.  The word <code>%value</code> will be substituted with the corresponding value.  An example page title is "People whose favorite color is %value".  Only applicable if the field is configured to be shown on member list pages.'));
Dries's avatar
   
Dries committed
378
379
  }
  else {
380
    $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t('The title of the page showing all users with the specified field.  Only applicable if the field is configured to be shown on member listings.'));
Dries's avatar
 
Dries committed
381
  }
382
  $group .= form_checkbox(t('Required field.'), 'required', 1, $edit['required']);
Dries's avatar
 
Dries committed
383

384
  $output  = form_group(t('Field settings'), $group);
Dries's avatar
   
Dries committed
385
386
387
388
389
  $output .= form_submit(t('Save field'));

  return form($output);
}

Dries's avatar
   
Dries committed
390
391
392
/**
 * Menu callback; display a listing of all editable profile fields.
 */
Dries's avatar
   
Dries committed
393
394
395
396
function profile_admin_overview() {

  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
  while ($field = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
397
    $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/user/configure/profile/edit/$field->fid"), l(t('delete'), "admin/user/configure/profile/delete/$field->fid"));
Dries's avatar
 
Dries committed
398
  }
Dries's avatar
   
Dries committed
399
400
401
402
403
404
405

  $header = array(t('title'), t('name'), t('type'), t('category'), array('data' => t('operations'), 'colspan' => '2'));

  $output  = theme('table', $header, $rows);
  $output .= '<h2>'. t('Create new field') .'</h2>';
  $output .= '<ul>';
  foreach (_profile_field_types() as $key => $value) {
Dries's avatar
   
Dries committed
406
    $output .= '<li>'. l(t('Add new %type', array('%type' => $value)), "admin/user/configure/profile/add/$key") .'</li>';
Dries's avatar
 
Dries committed
407
  }
Dries's avatar
   
Dries committed
408
409
410
  $output .= '</ul>';

  print theme('page', $output);
Dries's avatar
 
Dries committed
411
412
}

Dries's avatar
   
Dries committed
413
414
415
416
function theme_profile_profile($user, $fields = array()) {

  $output  = "<div class=\"profile\">\n";
  $output .= theme('user_picture', $user);
Dries's avatar
   
Dries committed
417
  $output .= ' <div class="name">'. format_name($user) ."</div>\n";
Dries's avatar
   
Dries committed
418
419

  foreach ($fields as $field) {
420
421
    if ($value = profile_view_field($user, $field)) {
      $output .= " <div class=\"field\">$value</div>\n";
Dries's avatar
 
Dries committed
422
423
    }
  }
Dries's avatar
   
Dries committed
424
425
426
427
428
429
430

  $output .= "</div>\n";

  return $output;
}

function _profile_field_types($type = NULL) {
Dries's avatar
Dries committed
431
  $types = array('textfield', 'textarea', 'checkbox', 'selection', 'list', 'url');
Dries's avatar
   
Dries committed
432
  return isset($type) ? $types[$type] : $types;
Dries's avatar
 
Dries committed
433
434
}

Dries's avatar
   
Dries committed
435
?>