[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/modules/profile/ -> profile.module (source)

   1  <?php
   2  // $Id: profile.module,v 1.236.2.3 2009/01/12 10:09:19 goba Exp $
   3  
   4  /**
   5   * @file
   6   * Support for configurable user profiles.
   7   */
   8  
   9  /**
  10   * Private field, content only available to privileged users.
  11   */
  12  define('PROFILE_PRIVATE', 1);
  13  
  14  /**
  15   * Public field, content shown on profile page but not used on member list pages.
  16   */
  17  define('PROFILE_PUBLIC', 2);
  18  
  19  /**
  20   * Public field, content shown on profile page and on member list pages.
  21   */
  22  define('PROFILE_PUBLIC_LISTINGS', 3);
  23  
  24  /**
  25   * Hidden profile field, only accessible by administrators, modules and themes.
  26   */
  27  define('PROFILE_HIDDEN', 4);
  28  
  29  /**
  30   * Implementation of hook_help().
  31   */
  32  function profile_help($path, $arg) {
  33    switch ($path) {
  34      case 'admin/help#profile':
  35        $output = '<p>'. t('The profile module allows custom fields (such as country, full name, or age) to be defined and displayed in the <em>My Account</em> section. This permits users of a site to share more information about themselves, and can help community-based sites organize users around specific information.') .'</p>';
  36        $output .= '<p>'. t('The following types of fields can be added to a user profile:') .'</p>';
  37        $output .= '<ul><li>'. t('single-line textfield') .'</li>';
  38        $output .= '<li>'. t('multi-line textfield') .'</li>';
  39        $output .= '<li>'. t('checkbox') .'</li>';
  40        $output .= '<li>'. t('list selection') .'</li>';
  41        $output .= '<li>'. t('freeform list') .'</li>';
  42        $output .= '<li>'. t('URL') .'</li>';
  43        $output .= '<li>'. t('date') .'</li></ul>';
  44        $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@profile">Profile module</a>.', array('@profile' => 'http://drupal.org/handbook/modules/profile/')) .'</p>';
  45        return $output;
  46      case 'admin/user/profile':
  47        return '<p>'. t("This page displays a list of the existing custom profile fields to be displayed on a user's <em>My Account</em> page. To provide structure, similar or related fields may be placed inside a category. To add a new category (or edit an existing one), edit a profile field and provide a new category name. To change the category of a field or the order of fields within a category, grab a drag-and-drop handle under the Title column and drag the field to a new location in the list. (Grab a handle by clicking and holding the mouse while hovering over a handle icon.) Remember that your changes will not be saved until you click the <em>Save configuration</em> button at the bottom of the page.") .'</p>';
  48    }
  49  }
  50  
  51  /**
  52   * Implementation of hook_theme()
  53   */
  54  function profile_theme() {
  55    return array(
  56      'profile_block' => array(
  57        'arguments' => array('account' => NULL, 'fields' => array()),
  58        'template' => 'profile-block',
  59      ),
  60      'profile_listing' => array(
  61        'arguments' => array('account' => NULL, 'fields' => array()),
  62        'template' => 'profile-listing',
  63      ),
  64      'profile_wrapper' => array(
  65        'arguments' => array('content' => NULL),
  66        'template' => 'profile-wrapper',
  67      ),
  68      'profile_admin_overview' => array(
  69        'arguments' => array('form' => NULL),
  70        'file' => 'profile.admin.inc',
  71      )
  72    );
  73  }
  74  
  75  /**
  76   * Implementation of hook_menu().
  77   */
  78  function profile_menu() {
  79    $items['profile'] = array(
  80      'title' => 'User list',
  81      'page callback' => 'profile_browse',
  82      'access arguments' => array('access user profiles'),
  83      'type' => MENU_SUGGESTED_ITEM,
  84      'file' => 'profile.pages.inc',
  85    );
  86    $items['admin/user/profile'] = array(
  87      'title' => 'Profiles',
  88      'description' => 'Create customizable fields for your users.',
  89      'page callback' => 'drupal_get_form',
  90      'page arguments' => array('profile_admin_overview'),
  91      'access arguments' => array('administer users'),
  92      'file' => 'profile.admin.inc',
  93    );
  94    $items['admin/user/profile/add'] = array(
  95      'title' => 'Add field',
  96      'page callback' => 'drupal_get_form',
  97      'page arguments' => array('profile_field_form'),
  98      'access arguments' => array('administer users'),
  99      'type' => MENU_CALLBACK,
 100      'file' => 'profile.admin.inc',
 101    );
 102    $items['admin/user/profile/autocomplete'] = array(
 103      'title' => 'Profile category autocomplete',
 104      'page callback' => 'profile_admin_settings_autocomplete',
 105      'access arguments' => array('administer users'),
 106      'type' => MENU_CALLBACK,
 107      'file' => 'profile.admin.inc',
 108    );
 109    $items['admin/user/profile/edit'] = array(
 110      'title' => 'Edit field',
 111      'page callback' => 'drupal_get_form',
 112      'page arguments' => array('profile_field_form'),
 113      'access arguments' => array('administer users'),
 114      'type' => MENU_CALLBACK,
 115      'file' => 'profile.admin.inc',
 116    );
 117    $items['admin/user/profile/delete'] = array(
 118      'title' => 'Delete field',
 119      'page callback' => 'drupal_get_form',
 120      'page arguments' => array('profile_field_delete'),
 121      'access arguments' => array('administer users'),
 122      'type' => MENU_CALLBACK,
 123      'file' => 'profile.admin.inc',
 124    );
 125    $items['profile/autocomplete'] = array(
 126      'title' => 'Profile autocomplete',
 127      'page callback' => 'profile_autocomplete',
 128      'access arguments' => array('access user profiles'),
 129      'type' => MENU_CALLBACK,
 130      'file' => 'profile.pages.inc',
 131    );
 132    return $items;
 133  }
 134  
 135  /**
 136   * Implementation of hook_block().
 137   */
 138  function profile_block($op = 'list', $delta = 0, $edit = array()) {
 139  
 140    if ($op == 'list') {
 141      $blocks[0]['info'] = t('Author information');
 142      $blocks[0]['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
 143      return $blocks;
 144    }
 145    else if ($op == 'configure' && $delta == 0) {
 146      // Compile a list of fields to show
 147      $fields = array();
 148      $result = db_query('SELECT name, title, weight, visibility FROM {profile_fields} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
 149      while ($record = db_fetch_object($result)) {
 150        $fields[$record->name] = check_plain($record->title);
 151      }
 152      $fields['user_profile'] = t('Link to full user profile');
 153      $form['profile_block_author_fields'] = array('#type' => 'checkboxes',
 154        '#title' => t('Profile fields to display'),
 155        '#default_value' => variable_get('profile_block_author_fields', array()),
 156        '#options' => $fields,
 157        '#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the <a href="@profile-admin">profile field configuration</a> are available.', array('@profile-admin' => url('admin/user/profile'))),
 158      );
 159      return $form;
 160    }
 161    else if ($op == 'save' && $delta == 0) {
 162      variable_set('profile_block_author_fields', $edit['profile_block_author_fields']);
 163    }
 164    else if ($op == 'view') {
 165      if (user_access('access user profiles')) {
 166        $output = '';
 167        if ((arg(0) == 'node') && is_numeric(arg(1)) && (arg(2) == NULL)) {
 168          $node = node_load(arg(1));
 169          $account = user_load(array('uid' => $node->uid));
 170  
 171          if ($use_fields = variable_get('profile_block_author_fields', array())) {
 172            // Compile a list of fields to show.
 173            $fields = array();
 174            $result = db_query('SELECT name, title, type, visibility, weight FROM {profile_fields} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
 175            while ($record = db_fetch_object($result)) {
 176              // Ensure that field is displayed only if it is among the defined block fields and, if it is private, the user has appropriate permissions.
 177              if (isset($use_fields[$record->name]) && $use_fields[$record->name]) {
 178                $fields[] = $record;
 179              }
 180            }
 181          }
 182  
 183          if (!empty($fields)) {
 184            $profile = _profile_update_user_fields($fields, $account);
 185            $output .= theme('profile_block', $account, $profile, TRUE);
 186          }
 187  
 188          if (isset($use_fields['user_profile']) && $use_fields['user_profile']) {
 189            $output .= '<div>'. l(t('View full user profile'), 'user/'. $account->uid) .'</div>';
 190          }
 191        }
 192  
 193        if ($output) {
 194          $block['subject'] = t('About %name', array('%name' => $account->name));
 195          $block['content'] = $output;
 196          return $block;
 197        }
 198      }
 199    }
 200  }
 201  
 202  /**
 203   * Implementation of hook_user().
 204   */
 205  function profile_user($type, &$edit, &$user, $category = NULL) {
 206    switch ($type) {
 207      case 'load':
 208        return profile_load_profile($user);
 209      case 'register':
 210        return profile_form_profile($edit, $user, $category, TRUE);
 211      case 'update':
 212      return profile_save_profile($edit, $user, $category);
 213      case 'insert':
 214        return profile_save_profile($edit, $user, $category, TRUE);
 215      case 'view':
 216        return profile_view_profile($user);
 217      case 'form':
 218        return profile_form_profile($edit, $user, $category);
 219      case 'validate':
 220        return profile_validate_profile($edit, $category);
 221      case 'categories':
 222        return profile_categories();
 223      case 'delete':
 224        db_query('DELETE FROM {profile_values} WHERE uid = %d', $user->uid);
 225    }
 226  }
 227  
 228  function profile_load_profile(&$user) {
 229    $result = db_query('SELECT f.name, f.type, v.value FROM {profile_fields} f INNER JOIN {profile_values} v ON f.fid = v.fid WHERE uid = %d', $user->uid);
 230    while ($field = db_fetch_object($result)) {
 231      if (empty($user->{$field->name})) {
 232        $user->{$field->name} = _profile_field_serialize($field->type) ? unserialize($field->value) : $field->value;
 233      }
 234    }
 235  }
 236  
 237  function profile_save_profile(&$edit, &$user, $category, $register = FALSE) {
 238    $result = _profile_get_fields($category, $register);
 239    while ($field = db_fetch_object($result)) {
 240      if (_profile_field_serialize($field->type)) {
 241        $edit[$field->name] = serialize($edit[$field->name]);
 242      }
 243      db_query("DELETE FROM {profile_values} WHERE fid = %d AND uid = %d", $field->fid, $user->uid);
 244      db_query("INSERT INTO {profile_values} (fid, uid, value) VALUES (%d, %d, '%s')", $field->fid, $user->uid, $edit[$field->name]);
 245      // Mark field as handled (prevents saving to user->data).
 246      $edit[$field->name] = NULL;
 247    }
 248  }
 249  
 250  function profile_view_field($user, $field) {
 251    // Only allow browsing of private fields for admins, if browsing is enabled,
 252    // and if a user has permission to view profiles. Note that this check is
 253    // necessary because a user may always see their own profile.
 254    $browse = user_access('access user profiles')
 255           && (user_access('administer users') || $field->visibility != PROFILE_PRIVATE)
 256           && !empty($field->page);
 257  
 258    if (isset($user->{$field->name}) && $value = $user->{$field->name}) {
 259      switch ($field->type) {
 260        case 'textarea':
 261          return check_markup($value);
 262        case 'textfield':
 263        case 'selection':
 264          return $browse ? l($value, 'profile/'. $field->name .'/'. $value) : check_plain($value);
 265        case 'checkbox':
 266          return $browse ? l($field->title, 'profile/'. $field->name) : check_plain($field->title);
 267        case 'url':
 268          return '<a href="'. check_url($value) .'">'. check_plain($value) .'</a>';
 269        case 'date':
 270          $format = substr(variable_get('date_format_short', 'm/d/Y - H:i'), 0, 5);
 271          // Note: Avoid PHP's date() because it does not handle dates before
 272          // 1970 on Windows. This would make the date field useless for e.g.
 273          // birthdays.
 274          $replace = array(
 275            'd' => sprintf('%02d', $value['day']),
 276            'j' => $value['day'],
 277            'm' => sprintf('%02d', $value['month']),
 278            'M' => map_month($value['month']),
 279            'Y' => $value['year'],
 280            'H:i' => NULL,
 281            'g:ia' => NULL,
 282          );
 283          return strtr($format, $replace);
 284        case 'list':
 285          $values = split("[,\n\r]", $value);
 286          $fields = array();
 287          foreach ($values as $value) {
 288            if ($value = trim($value)) {
 289              $fields[] = $browse ? l($value, 'profile/'. $field->name .'/'. $value) : check_plain($value);
 290            }
 291          }
 292          return implode(', ', $fields);
 293      }
 294    }
 295  }
 296  
 297  function profile_view_profile(&$user) {
 298  
 299    profile_load_profile($user);
 300  
 301    // Show private fields to administrators and people viewing their own account.
 302    if (user_access('administer users') || $GLOBALS['user']->uid == $user->uid) {
 303      $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d ORDER BY category, weight', PROFILE_HIDDEN);
 304    }
 305    else {
 306      $result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND visibility != %d ORDER BY category, weight', PROFILE_PRIVATE, PROFILE_HIDDEN);
 307    }
 308  
 309    $fields = array();
 310    while ($field = db_fetch_object($result)) {
 311      if ($value = profile_view_field($user, $field)) {
 312        $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;
 313  
 314        // Create a single fieldset for each category.
 315        if (!isset($user->content[$field->category])) {
 316          $user->content[$field->category] = array(
 317            '#type' => 'user_profile_category',
 318            '#title' => $field->category,
 319          );
 320        }
 321  
 322        $user->content[$field->category][$field->name] = array(
 323          '#type' => 'user_profile_item',
 324          '#title' => $title,
 325          '#value' => $value,
 326          '#weight' => $field->weight,
 327          '#attributes' => array('class' => 'profile-'. $field->name),
 328        );
 329      }
 330    }
 331  }
 332  
 333  function _profile_form_explanation($field) {
 334    $output = $field->explanation;
 335  
 336    if ($field->type == 'list') {
 337      $output .= ' '. t('Put each item on a separate line or separate them by commas. No HTML allowed.');
 338    }
 339  
 340    if ($field->visibility == PROFILE_PRIVATE) {
 341      $output .= ' '. t('The content of this field is kept private and will not be shown publicly.');
 342    }
 343  
 344    return $output;
 345  }
 346  
 347  function profile_form_profile($edit, $user, $category, $register = FALSE) {
 348    $result = _profile_get_fields($category, $register);
 349    $weight = 1;
 350    $fields = array();
 351    while ($field = db_fetch_object($result)) {
 352      $category = $field->category;
 353      if (!isset($fields[$category])) {
 354        $fields[$category] = array('#type' => 'fieldset', '#title' => check_plain($category), '#weight' => $weight++);
 355      }
 356      switch ($field->type) {
 357        case 'textfield':
 358        case 'url':
 359          $fields[$category][$field->name] = array('#type' => 'textfield',
 360            '#title' => check_plain($field->title),
 361            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 362            '#maxlength' => 255,
 363            '#description' => _profile_form_explanation($field),
 364            '#required' => $field->required,
 365          );
 366          if ($field->autocomplete) {
 367            $fields[$category][$field->name]['#autocomplete_path'] = "profile/autocomplete/". $field->fid;
 368          }
 369          break;
 370        case 'textarea':
 371          $fields[$category][$field->name] = array('#type' => 'textarea',
 372            '#title' => check_plain($field->title),
 373            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 374            '#description' => _profile_form_explanation($field),
 375            '#required' => $field->required,
 376          );
 377          break;
 378        case 'list':
 379          $fields[$category][$field->name] = array('#type' => 'textarea',
 380            '#title' => check_plain($field->title),
 381            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 382            '#description' => _profile_form_explanation($field),
 383            '#required' => $field->required,
 384          );
 385          break;
 386        case 'checkbox':
 387          $fields[$category][$field->name] = array('#type' => 'checkbox',
 388            '#title' => check_plain($field->title),
 389            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 390            '#description' => _profile_form_explanation($field),
 391            '#required' => $field->required,
 392          );
 393          break;
 394        case 'selection':
 395          $options = $field->required ? array() : array('--');
 396          $lines = split("[\n\r]", $field->options);
 397          foreach ($lines as $line) {
 398            if ($line = trim($line)) {
 399              $options[$line] = $line;
 400            }
 401          }
 402          $fields[$category][$field->name] = array('#type' => 'select',
 403            '#title' => check_plain($field->title),
 404            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 405            '#options' => $options,
 406            '#description' => _profile_form_explanation($field),
 407            '#required' => $field->required,
 408          );
 409          break;
 410        case 'date':
 411          $fields[$category][$field->name] = array('#type' => 'date',
 412            '#title' => check_plain($field->title),
 413            '#default_value' => isset($edit[$field->name]) ? $edit[$field->name] : '',
 414            '#description' => _profile_form_explanation($field),
 415            '#required' => $field->required,
 416          );
 417          break;
 418      }
 419    }
 420    return $fields;
 421  }
 422  
 423  /**
 424   * Helper function: update an array of user fields by calling profile_view_field
 425   */
 426  function _profile_update_user_fields($fields, $account) {
 427    foreach ($fields as $key => $field) {
 428      $fields[$key]->value = profile_view_field($account, $field);
 429    }
 430    return $fields;
 431  }
 432  
 433  function profile_validate_profile($edit, $category) {
 434    $result = _profile_get_fields($category);
 435    while ($field = db_fetch_object($result)) {
 436      if ($edit[$field->name]) {
 437        if ($field->type == 'url') {
 438          if (!valid_url($edit[$field->name], TRUE)) {
 439            form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => $field->title)));
 440          }
 441        }
 442      }
 443      else if ($field->required && !user_access('administer users')) {
 444        form_set_error($field->name, t('The field %field is required.', array('%field' => $field->title)));
 445      }
 446    }
 447  
 448    return $edit;
 449  }
 450  
 451  function profile_categories() {
 452    $result = db_query("SELECT DISTINCT(category) FROM {profile_fields}");
 453    $data = array();
 454    while ($category = db_fetch_object($result)) {
 455      $data[] = array(
 456        'name' => $category->category,
 457        'title' => $category->category,
 458        'weight' => 3,
 459        'access callback' => 'profile_category_access',
 460        'access arguments' => array(1, $category->category)
 461      );
 462    }
 463    return $data;
 464  }
 465  
 466  /**
 467   * Menu item access callback - check if a user has access to a profile category.
 468   */
 469  function profile_category_access($account, $category) {
 470    if (user_access('administer users') && $account->uid > 0) {
 471      return TRUE;
 472    }
 473    else {
 474      return user_edit_access($account) && db_result(db_query("SELECT COUNT(*) FROM {profile_fields} WHERE category = '%s' AND visibility <> %d", $category, PROFILE_HIDDEN));
 475    }
 476  }
 477  
 478  /**
 479   * Process variables for profile-block.tpl.php.
 480   *
 481   * The $variables array contains the following arguments:
 482   * - $account
 483   * - $fields
 484   *
 485   * @see profile-block.tpl.php
 486   */
 487  function template_preprocess_profile_block(&$variables) {
 488  
 489    $variables['picture'] = theme('user_picture', $variables['account']);
 490    $variables['profile'] = array();
 491    // Supply filtered version of $fields that have values.
 492    foreach ($variables['fields'] as $field) {
 493      if ($field->value) {
 494        $variables['profile'][$field->name]->title = check_plain($field->title);
 495        $variables['profile'][$field->name]->value = $field->value;
 496        $variables['profile'][$field->name]->type = $field->type;
 497      }
 498    }
 499  
 500  }
 501  
 502  /**
 503   * Process variables for profile-listing.tpl.php.
 504   *
 505   * The $variables array contains the following arguments:
 506   * - $account
 507   * - $fields
 508   *
 509   * @see profile-listing.tpl.php
 510   */
 511  function template_preprocess_profile_listing(&$variables) {
 512  
 513    $variables['picture'] = theme('user_picture', $variables['account']);
 514    $variables['name'] = theme('username', $variables['account']);
 515    $variables['profile'] = array();
 516    // Supply filtered version of $fields that have values.
 517    foreach ($variables['fields'] as $field) {
 518      if ($field->value) {
 519        $variables['profile'][$field->name]->title = $field->title;
 520        $variables['profile'][$field->name]->value = $field->value;
 521        $variables['profile'][$field->name]->type = $field->type;
 522      }
 523    }
 524  
 525  }
 526  
 527  /**
 528   * Process variables for profile-wrapper.tpl.php.
 529   *
 530   * The $variables array contains the following arguments:
 531   * - $content
 532   *
 533   * @see profile-wrapper.tpl.php
 534   */
 535  function template_preprocess_profile_wrapper(&$variables) {
 536    $variables['current_field'] = '';
 537    if ($field = arg(1)) {
 538      $variables['current_field'] = $field;
 539      // Supply an alternate template suggestion based on the browsable field.
 540      $variables['template_files'][] = 'profile-wrapper-'. $field;
 541    }
 542  }
 543  
 544  function _profile_field_types($type = NULL) {
 545    $types = array('textfield' => t('single-line textfield'),
 546                   'textarea' => t('multi-line textfield'),
 547                   'checkbox' => t('checkbox'),
 548                   'selection' => t('list selection'),
 549                   'list' => t('freeform list'),
 550                   'url' => t('URL'),
 551                   'date' => t('date'));
 552    return isset($type) ? $types[$type] : $types;
 553  }
 554  
 555  function _profile_field_serialize($type = NULL) {
 556    return $type == 'date';
 557  }
 558  
 559  function _profile_get_fields($category, $register = FALSE) {
 560    $args = array();
 561    $sql = 'SELECT * FROM {profile_fields} WHERE ';
 562    $filters = array();
 563    if ($register) {
 564      $filters[] = 'register = 1';
 565    }
 566    else {
 567      // Use LOWER('%s') instead of PHP's strtolower() to avoid UTF-8 conversion issues.
 568      $filters[] = "LOWER(category) = LOWER('%s')";
 569      $args[] = $category;
 570    }
 571    if (!user_access('administer users')) {
 572      $filters[] = 'visibility != %d';
 573      $args[] = PROFILE_HIDDEN;
 574    }
 575    $sql .= implode(' AND ', $filters);
 576    $sql .= ' ORDER BY category, weight';
 577    return db_query($sql, $args);
 578  }
 579  


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7