[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

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

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


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7