profile.module 13.3 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

Dries's avatar
 
Dries committed
6
function profile_help($section) {
Dries's avatar
 
Dries committed
7
  switch ($section) {
Dries's avatar
 
Dries committed
8
    case 'admin/system/modules#description':
Dries's avatar
 
Dries committed
9
      $output = t("Support for configurable user profiles.");
Dries's avatar
 
Dries committed
10 11
      break;
  }
Dries's avatar
 
Dries committed
12
  return $output;
Dries's avatar
 
Dries committed
13 14


Dries's avatar
 
Dries committed
15 16
}

Dries's avatar
 
Dries committed
17 18 19
/**
 * Implementation of hook_link().
 */
Dries's avatar
 
Dries committed
20 21 22
function profile_link($type) {
  if ($type == 'system') {
    menu('profile', t('browse'), 'profile_browse', 0, MENU_HIDE);
23

Dries's avatar
 
Dries committed
24 25 26 27
    menu('admin/system/modules/profile', t('profile'), user_access('administer users') ? 'profile_admin_overview' : MENU_DENIED);
    menu('admin/system/modules/profile/add', NULL, user_access('administer users') ? 'profile_admin_add' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED);
    menu('admin/system/modules/profile/edit', NULL, user_access('administer users') ? 'profile_admin_edit' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED);
    menu('admin/system/modules/profile/delete', NULL, user_access('administer users') ? 'profile_admin_delete' : MENU_DENIED, 0, MENU_HIDE, MENU_LOCKED);
Dries's avatar
 
Dries committed
28
  }
Dries's avatar
 
Dries committed
29
}
Dries's avatar
 
Dries committed
30

Dries's avatar
 
Dries committed
31
function profile_browse() {
Dries's avatar
 
Dries committed
32

Dries's avatar
 
Dries committed
33

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

Dries's avatar
 
Dries committed
36 37 38 39 40 41 42
  if ($field->fid) {
    // Compile a list of fields to show:
    $fields = array();
    $result = db_query("SELECT name, title, type FROM {profile_fields} WHERE fid != %d AND overview = 1", $field->fid);
    while ($record = db_fetch_object($result)) {
      $fields[] = $record;
    }
Dries's avatar
 
Dries committed
43

Dries's avatar
Dries committed
44 45 46 47 48 49 50 51 52 53 54 55 56
    // Determine what query to use:
    switch ($field->type) {
      case 'checkbox':
        $query = 'v.value = 1';
        break;
      case 'selection':
        $query = "v.value = '". check_query(arg(2)) ."'";
        break;
      case 'list':
        $query = "v.value LIKE '%". check_query(arg(2)) ."%'";
        break;
    }

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

Dries's avatar
 
Dries committed
60
    $output = '<div id="profile">';
Dries's avatar
 
Dries committed
61 62 63 64 65
    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
66
    if ($field->type == 'selection' || $field->type == 'list') {
Dries's avatar
 
Dries committed
67
      $title = strtr($field->page, array('%value' => arg(2)));
Dries's avatar
 
Dries committed
68 69
    }
    else {
Dries's avatar
 
Dries committed
70
      $title = $field->page;
Dries's avatar
 
Dries committed
71
    }
Dries's avatar
 
Dries committed
72
    $output .= "</div>";
Dries's avatar
 
Dries committed
73 74 75 76 77

    print theme('page', $output, $title);
  }
  else {
    drupal_not_found();
Dries's avatar
 
Dries committed
78
  }
Dries's avatar
 
Dries committed
79
}
Dries's avatar
 
Dries committed
80

Dries's avatar
 
Dries committed
81 82 83 84 85 86
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
87
  }
Dries's avatar
 
Dries committed
88 89
}

Dries's avatar
 
Dries committed
90 91
function profile_save_profile($edit, $user) {
  db_query('DELETE FROM {profile_values} WHERE uid = %d', $user->uid);
92
  $result = db_query('SELECT fid, name FROM {profile_fields}');
Dries's avatar
 
Dries committed
93 94 95 96 97 98
  while ($field = db_fetch_object($result)) {
    if ($edit[$field->name]) {
      db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]);
      unset($edit[$field->name]);
    }
  }
Dries's avatar
 
Dries committed
99 100
}

101 102 103 104 105 106 107
function profile_view_field($user, $field) {
  if ($value = $user->{$field->name}) {
    switch ($field->type) {
      case 'textfield':
      case 'textarea':
        return check_output($value);
      case 'selection':
Dries's avatar
Dries committed
108
        return l($value, "profile/$field->name/". htmlentities($value));
109
      case 'checkbox':
Dries's avatar
Dries committed
110
        return l($field->title, "profile/$field->name");
111
      case 'url':
Dries's avatar
Dries committed
112 113 114 115 116 117 118 119 120
        return "<a href=\"". check_url(strip_tags($value)) ."\">". strip_tags($value) ."</a>";      case 'list':
        $values = split("[\n\r]", $value);
        $fields = array();
        foreach ($values as $value) {
          if ($value = trim(strip_tags($value))) {
            $fields[] = l($value, "profile/$field->name/". htmlentities($value));
          }
        }
        return implode(', ', $fields);
121 122 123 124
    }
  }
}

Dries's avatar
 
Dries committed
125
function profile_view_profile($user) {
Dries's avatar
 
Dries committed
126

127
  profile_load_profile($user);
Dries's avatar
 
Dries committed
128

Dries's avatar
 
Dries committed
129 130
  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
  while ($field = db_fetch_object($result)) {
131 132
    if ($value = profile_view_field($user, $field)) {
      if ($field->type == 'checkbox') {
Dries's avatar
Dries committed
133
        $fields[$field->category] .= "<p>$value</p>";
134 135
      }
      else {
Dries's avatar
Dries committed
136
        $fields[$field->category] .= form_item($field->title, check_output($value));
Dries's avatar
 
Dries committed
137
      }
Dries's avatar
 
Dries committed
138 139 140
    }
  }

Dries's avatar
Dries committed
141
  return $fields;
Dries's avatar
 
Dries committed
142
}
Dries's avatar
 
Dries committed
143

Dries's avatar
 
Dries committed
144 145 146 147 148 149 150
function profile_edit_profile($edit, $user) {

  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');

  while ($field = db_fetch_object($result)) {
    switch ($field->type) {
      case 'textfield':
151
      case 'url':
152
        $fields[$field->category] .= form_textfield($field->title, $field->name, $edit[$field->name], 70, 255, $field->explanation, NULL, $field->required);
Dries's avatar
 
Dries committed
153 154
        break;
      case 'textarea':
155
        $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation, NULL, $field->required);
Dries's avatar
Dries committed
156 157
        break;
      case 'list':
158
        $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 5, $field->explanation ." ". t('Put each entry on a separate line.  No HTML allowed.'), NULL, $field->required);
Dries's avatar
 
Dries committed
159 160
        break;
      case 'checkbox':
161
        $fields[$field->category] .= form_checkbox($field->title, $field->name, 1, $edit[$field->name], $field->explanation, NULL, $field->required);
Dries's avatar
 
Dries committed
162 163 164 165 166 167 168 169 170 171
        break;
      case 'selection':
        $options = array('--');
        $lines = split("[\n\r]", $field->options);
        foreach ($lines as $line) {
          if ($line = trim($line)) {
            $options[$line] = $line;
          }
        }

172
        $fields[$field->category] .= form_select($field->title, $field->name, $edit[$field->name], $options, $field->explanation, 0, 0, $field->required);
Dries's avatar
 
Dries committed
173
        break;
Dries's avatar
 
Dries committed
174 175 176
    }
  }

Dries's avatar
 
Dries committed
177
  return $fields;
Dries's avatar
 
Dries committed
178 179
}

180 181 182 183
function profile_validate_profile($edit) {
  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');

  while ($field = db_fetch_object($result)) {
184 185
    if ($edit[$field->name]) {
      if ($field->type == 'url' && !valid_url($edit[$field->name], true)) {
186 187 188
        return t("The value provided for '%field' is not a valid URL.", array('%field' => $field->title));
      }
    }
Dries's avatar
 
Dries committed
189 190 191
    else if ($field->required) {
      return t("The field '%field' is required.", array('%field' => $field->title));
    }
192 193 194 195 196
  }

  return $edit;
}

Dries's avatar
 
Dries committed
197 198 199 200 201
function profile_user($type, $edit, &$user) {
  switch ($type) {
    case 'load':
      return profile_load_profile($user);
    case 'update':
202
    case 'insert':
Dries's avatar
 
Dries committed
203 204 205
      return profile_save_profile($edit, $user);
    case 'view':
      return profile_view_profile($user);
206
    case 'form':
Dries's avatar
 
Dries committed
207 208
      return profile_edit_profile($edit, $user);
    case 'validate':
209
      return profile_validate_profile($edit);
Dries's avatar
 
Dries committed
210 211
  }
}
Dries's avatar
 
Dries committed
212

Dries's avatar
 
Dries committed
213
function profile_validate_form($edit) {
Dries's avatar
 
Dries committed
214

Dries's avatar
 
Dries committed
215
  // Validate the title:
Dries's avatar
 
Dries committed
216

Dries's avatar
 
Dries committed
217 218
  if (!$edit['title']) {
    return t('You must enter a title.');
Dries's avatar
 
Dries committed
219 220
  }

Dries's avatar
 
Dries committed
221
  // Validate the 'form name':
Dries's avatar
 
Dries committed
222

Dries's avatar
 
Dries committed
223 224
  if (eregi('[^a-z0-9_-]', $edit['name'])) {
    return 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
225 226
  }

Dries's avatar
 
Dries committed
227 228
  if (in_array($edit['name'], user_fields())) {
    return t('The specified form name is reserved for use by Drupal.');
Dries's avatar
 
Dries committed
229 230
  }

Dries's avatar
 
Dries committed
231 232 233 234
  // Validate the category:
  if (!$edit['category']) {
    return t('You must enter a category.');
  }
Dries's avatar
 
Dries committed
235 236
}

Dries's avatar
 
Dries committed
237 238
function profile_admin_add($type) {
  $type = _profile_field_types($type);
Dries's avatar
 
Dries committed
239

240

Dries's avatar
 
Dries committed
241 242
  if ($_POST['op']) {
    $data = $_POST['edit'];
Dries's avatar
 
Dries committed
243

Dries's avatar
 
Dries committed
244 245
    if ($error = profile_validate_form($data)) {
      drupal_set_message($error, 'error');
Dries's avatar
 
Dries committed
246
    }
Dries's avatar
 
Dries committed
247
    else {
Dries's avatar
 
Dries committed
248
      db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, required, overview, 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['overview'], $data['options'], $data['page']);
Dries's avatar
 
Dries committed
249

Dries's avatar
 
Dries committed
250 251
      drupal_set_message(t('the field has been created.'));
    }
Dries's avatar
 
Dries committed
252
  }
Dries's avatar
 
Dries committed
253 254 255 256 257
  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
258 259
}

Dries's avatar
 
Dries committed
260
function profile_admin_edit($fid) {
Dries's avatar
 
Dries committed
261

Dries's avatar
 
Dries committed
262 263
  if ($_POST['op']) {
    $data = $_POST['edit'];
Dries's avatar
 
Dries committed
264

Dries's avatar
 
Dries committed
265 266
    if ($error = profile_validate_form($data)) {
      drupal_set_message($error, 'error');
Dries's avatar
 
Dries committed
267

Dries's avatar
 
Dries committed
268 269
    }
    else {
Dries's avatar
 
Dries committed
270
      db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, required = %d, overview = %d, options = '%s', page = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['required'], $data['overview'], $data['options'], $data['page'], $fid);
Dries's avatar
 
Dries committed
271 272 273

      drupal_set_message(t('the field has been updated.'));
    }
Dries's avatar
 
Dries committed
274 275
  }
  else {
Dries's avatar
 
Dries committed
276
    $data = db_fetch_array(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
Dries's avatar
 
Dries committed
277 278
  }

Dries's avatar
 
Dries committed
279
  print theme('page', _profile_field_form($data['type'], $data), t('Edit %type', array('%type' => $edit['type'])));
Dries's avatar
 
Dries committed
280 281
}

Dries's avatar
 
Dries committed
282 283 284 285
function profile_admin_delete($fid) {
  db_query('DELETE FROM {profile_fields} WHERE fid = %d', $fid);
  drupal_set_message(t('the field has been deleted.'));
  print theme('page', '', t('Delete field'));
Dries's avatar
 
Dries committed
286 287
}

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

Dries's avatar
 
Dries committed
290 291 292
  $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.
293
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'."));
Dries's avatar
 
Dries committed
294 295 296 297 298
  $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."));
  if ($type == 'selection') {
    $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."));
  }
  $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."));
Dries's avatar
 
Dries committed
299
  $group .= form_checkbox(t('Required field.'), 'required', 1, $edit['required']);
Dries's avatar
 
Dries committed
300
  $output = form_group(t('Field settings'), $group);
Dries's avatar
 
Dries committed
301

Dries's avatar
 
Dries committed
302
  $group = '';
Dries's avatar
Dries committed
303
  if ($type == 'selection' || $type == 'list') {
Dries's avatar
 
Dries committed
304 305 306 307
    $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'."));
  }
  else {
    $group .= form_textfield(t('Page title'), 'page', $edit['page'], 70, 128, t("The title of the page showing all users with the specified field."));
Dries's avatar
 
Dries committed
308
  }
Dries's avatar
 
Dries committed
309
  $group .= form_checkbox(t('Should this field be shown on the member listing pages.'), 'overview', 1, $edit['overview']);
Dries's avatar
 
Dries committed
310

Dries's avatar
 
Dries committed
311
  $output .= form_group(t('Browsability'), $group);
Dries's avatar
 
Dries committed
312 313 314 315 316 317 318 319 320 321
  $output .= form_submit(t('Save field'));

  return form($output);
}

function profile_admin_overview() {

  $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight');
  while ($field = db_fetch_object($result)) {
    $rows[] = array($field->title, $field->name, $field->type, $field->category, l(t('edit'), "admin/system/modules/profile/edit/$field->fid"), l(t('delete'), "admin/system/modules/profile/delete/$field->fid"));
Dries's avatar
 
Dries committed
322
  }
Dries's avatar
 
Dries committed
323 324 325 326 327 328 329 330

  $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) {
    $output .= "<li>". l(t('Add new %type', array('%type' => $value)), "admin/system/modules/profile/add/$key") ."</li>";
Dries's avatar
 
Dries committed
331
  }
Dries's avatar
 
Dries committed
332 333 334
  $output .= '</ul>';

  print theme('page', $output);
Dries's avatar
 
Dries committed
335 336
}

Dries's avatar
 
Dries committed
337 338 339 340 341 342 343
function theme_profile_profile($user, $fields = array()) {

  $output  = "<div class=\"profile\">\n";
  $output .= theme('user_picture', $user);
  $output .= " <div class=\"name\">". format_name($user) ."</div>\n";

  foreach ($fields as $field) {
344 345
    if ($value = profile_view_field($user, $field)) {
      $output .= " <div class=\"field\">$value</div>\n";
Dries's avatar
 
Dries committed
346 347
    }
  }
Dries's avatar
 
Dries committed
348 349 350 351 352 353 354

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

  return $output;
}

function _profile_field_types($type = NULL) {
Dries's avatar
Dries committed
355
  $types = array('textfield', 'textarea', 'checkbox', 'selection', 'list', 'url');
Dries's avatar
 
Dries committed
356
  return isset($type) ? $types[$type] : $types;
Dries's avatar
 
Dries committed
357 358
}

Dries's avatar
 
Dries committed
359
?>