diff options
Diffstat (limited to 'modules/profile.module')
-rw-r--r-- | modules/profile.module | 446 |
1 files changed, 220 insertions, 226 deletions
diff --git a/modules/profile.module b/modules/profile.module index a16c47c20..d1e5e5f0c 100644 --- a/modules/profile.module +++ b/modules/profile.module @@ -1,306 +1,300 @@ <?php -// $Id$ - -function _profile_init() { - /* - ** Add here any field you might need. Leave array[0] blank if you - ** need a special tool (like birthday or avatar). - ** TODO: add a clear description/explanation. - */ - - $GLOBALS["profile_fields"] = array( - "realname" => array("textfield", t("Name"), "", 64, 64, ""), - "address" => array("textfield", t("Address"), "", 64, 64, ""), - "city" => array("textfield", t("City"), "", 64, 64, ""), - "state" => array("textfield", t("State, province or region"), "", 64, 64, ""), - "zip" => array("textfield", t("Zip or postal code"), "", 7, 10, ""), - "country" => array("textfield", t("Country"), "", 64, 64, ""), - "birthday" => array("", t("Birthday"), ""), - "gender" => array("select", t("Gender"), "", array(0 => "-", "m" => t("male"), "f" => t("female")), "", 0, 0), - "job" => array("textfield", t("Job title"), "", 64, 64, ""), - "icq" => array("textfield", t("ICQ messenger ID"), "", 12, 12, ""), - "msn" => array("textfield", t("MSN messenger ID"), "", 64, 64, ""), - "yahoo" => array("textfield", t("Yahoo messenger ID"), "", 64, 64, ""), - "aim" => array("textfield", t("AIM messenger ID"), "", 64, 64, ""), - "homepage" => array("textfield", t("URL of homepage"), "", 64, 64, t("Make sure you enter a fully qualified URL: remember to include \"http://\".")), - "biography" => array("textarea", t("Biography"), "", 64, 4, ""), - "interests" => array("textarea", t("Interests"), "", 64, 4, ""), - "publickey" => array("textarea", t("Public key"), "", 64, 4, ""), - "avatar" => array("", t("Avatar or picture"), t("Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.", array("%dimensions" => variable_get("profile_avatar_dimensions", "85x85"), "%size" => variable_get("profile_avatar_file_size", "30")))) - ); - - $GLOBALS["profile_days"] = array_merge(array(0 => t("day")), drupal_map_assoc(range(1, 31))); - $GLOBALS["profile_months"] = array(0 => t("month"), 1 => t("January"), 2 => t("February"), 3 => t("March"), 4 => t("April"), 5 => t("May"), 6 => t("June"), 7 => t("July"), 8 => t("August"), 9 => t("September"), 10 => t("October"), 11 => t("November"), 12 => t("December")); -} -function profile_help($section) { - $output = ""; +// TODO: add a 'date' field so we can migrate the birthday information. +function profile_help($section) { switch ($section) { case 'admin/system/modules#description': $output = t("Support for configurable user profiles."); break; - case 'admin/system/modules/profile': - $output = t("When a user creates an account you can ask for some extra information, as well as letting the user have a small picture, called an avatar. <ul><li>In order for a user to enter information, you <strong>must</strong> check <em>enable</em>.</li><li>In order for other people to see the entered information, you must make it <em>public</em>.</li><li>If an item is <em>public</em>, but not enabled, the user can never give it a value and it will never be seen. <em>Public</em> does <strong>not</strong> imply <em>enable</em>.</li></ul>", array("%edit" => url("user/edit"))); - break; } return $output; + + } -function profile_settings() { - global $profile_fields; +function profile_link($type) { + if ($type == 'system') { + menu('profile', t('browse'), 'profile_browse', 0, MENU_HIDE); - if (!$profile_fields) { - _profile_init(); + if (user_access('administer users')) { + menu('admin/system/modules/profile', t('profile'), 'profile_admin_overview'); + menu('admin/system/modules/profile/add', NULL, 'profile_admin_add', 0, MENU_HIDE); + menu('admin/system/modules/profile/edit', NULL, 'profile_admin_edit', 0, MENU_HIDE); + menu('admin/system/modules/profile/delete', NULL, 'profile_admin_delete', 0, MENU_HIDE); + } } +} - if (!file_check_directory(file_create_path(variable_get('profile_avatar_path', 'avatars')))) { - $error['profile_avatar_path'] = theme('error', t('Directory does not exist, or is not writable.')); - } +function profile_browse() { - $profile_public_fields = variable_get("profile_public_fields", array()); - $profile_private_fields = variable_get("profile_private_fields", array()); - $profile_required_fields = variable_get("profile_required_fields", array()); - - $header = array(t("field"), t("enable"), t("public"), t("required")); - $i = 0; - foreach ($profile_fields as $key => $field) { - $row[$i][] = $field[1]; - $row[$i][] = form_checkbox("", "profile_private_fields][", $key, in_array($key, $profile_private_fields)); - $row[$i][] = form_checkbox("", "profile_public_fields][", $key, in_array($key, $profile_public_fields)); - $row[$i][] = form_checkbox("", "profile_required_fields][", $key, in_array($key, $profile_required_fields)); - $i++; - } + $value = arg(2) ? arg(2) : 1; - $avatar = form_textfield(t("Avatar image path"), "profile_avatar_path", variable_get("profile_avatar_path", "avatars"), 30, 255, t("Subdirectory in the directory '%dir' where avatars will be stored.", array('%dir' => variable_get('file_directory_path', 'files') . FILE_SEPARATOR)) . $error['profile_avatar_path']); - $avatar .= form_textfield(t("Avatar maximum dimensions"), "profile_avatar_dimensions", variable_get("profile_avatar_dimensions", "85x85"), 10, 10, t("Maximum dimensions for avatars.")); - $avatar .= form_textfield(t("Avatar maximum file size"), "profile_avatar_file_size", variable_get("profile_avatar_file_size", "30"), 10, 10, t("Maximum file size for avatars, in kB.")); + // Determine the field to group users by: + $field = db_fetch_object(db_query("SELECT DISTINCT(f.fid), f.type, f.title FROM {profile_fields} f INNER JOIN {profile_values} v ON f.fid = v.fid WHERE f.name = '%s' AND v.value = '%s' ORDER BY f.category, f.weight", arg(1), $value)); - $output = theme("table", $header, $row); - $output .= form_group(t('Avatars'), $avatar); + 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; + } - return $output; -} + // Extract the affected users: + $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 v.value = '". check_query($value) ."' ORDER BY u.changed DESC", 20); -function profile_user($type, $edit, &$user) { - global $profile_fields; - if (!$profile_fields) { - _profile_init(); + $output = ''; + while ($account = db_fetch_object($result)) { + $output .= theme('profile_profile', user_load(array('uid' => $account->uid)), $fields); + } + $output .= theme('pager', NULL, 20); + + if ($field->type == "selection") { + $title = arg(2); + } + else { + $title = $field->title; + } + + print theme('page', $output, $title); + } + else { + drupal_not_found(); } +} - switch ($type) { - case "edit_form": - // when user tries to edit his own data - return _profile_form(object2array($user), "private"); - case "edit_validate": - // validate user data editing - return _profile_validate($edit, "private", $user); - case "view_public": - // when others look at user data - return _profile_user_view($user, "public"); - case "view_private": - // when user looks at his own data - return _profile_user_view($user, "private"); +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; + } } } -function profile_required($title) { - // this pleads "theme, theme" ;) - return $title ." ". theme("mark"); +function profile_save_profile($edit, $user) { + db_query('DELETE FROM {profile_values} WHERE uid = %d', $user->uid); + $result = db_query('SELECT fid, name FROM profile_fields'); + 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]); + } + } } -function _profile_form($edit, $mode) { - global $profile_fields, $user; +function profile_view_profile($user) { - $reg_fields = _profile_active_fields($mode); - $required_fields = _profile_active_fields("required"); + profile_load_profile(&$user); - foreach ($profile_fields as $name => $field) { - if ($field[0] && in_array($name, $reg_fields)) { - $f = "form_". $field[0]; - $t = "profile_". $name; - $output .= $f((in_array($name, $required_fields) ? profile_required($field[1]) : $field[1]), $t, $edit[$t], $field[3], $field[4], $field[5], $field[6]); + $result = db_query('SELECT * FROM {profile_fields} ORDER BY category, weight'); + while ($field = db_fetch_object($result)) { + if ($value = $user->{$field->name}) { + switch ($field->type) { + case 'textfield': + case 'textarea': + $output .= form_item($field->title, check_output($value)); + break; + case 'selection': + $output .= form_item($field->title, l($value, "profile/$field->name/$value")); + break; + case 'checkbox': + $output .= '<p>'. l($field->title, "profile/$field->name/") .'</p>'; + } } } - if (in_array("birthday", $reg_fields)) { - $output .= form_item((in_array("birthday", $required_fields) ? profile_required($profile_fields["birthday"][1]) : $profile_fields["birthday"][1]), _profile_edit_birth(array2object($edit)), $profile_fields["birthday"][2]); - } + return $output; +} - if (in_array("avatar", $reg_fields)) { - if ($edit["profile_avatar"] && file_exists($edit["profile_avatar"])) { - $output .= form_item(t("Avatar"), '<img src="'. file_create_url($edit["profile_avatar"]) .'" alt="" title="" />'); +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': + $fields[$field->category] .= form_textfield($field->title, $field->name, $edit[$field->name], 70, 255, $field->explanation); + break; + case 'textarea': + $fields[$field->category] .= form_textarea($field->title, $field->name, $edit[$field->name], 60, 4, $field->explanation); + break; + case 'checkbox': + $fields[$field->category] .= form_checkbox($field->title, $field->name, 1, $edit[$field->name], $field->explanation); + break; + case 'selection': + $options = array('--'); + $lines = split("[\n\r]", $field->options); + foreach ($lines as $line) { + if ($line = trim($line)) { + $options[$line] = $line; + } + } + + $fields[$field->category] .= form_select($field->title, $field->name, $edit[$field->name], $options, $field->explanation); + break; } - $output .= form_file($profile_fields["avatar"][1], "profile_avatar", 64, $profile_fields["avatar"][2]); } - return array(t('Personal information') => $output); + return $fields; } -function _profile_validate($edit, $mode, $user) { +function profile_user($type, $edit, &$user) { + switch ($type) { + case 'load': + return profile_load_profile($user); + case 'update': + return profile_save_profile($edit, $user); + case 'view': + return profile_view_profile($user); + case 'edit': + return profile_edit_profile($edit, $user); + case 'validate': + return $edit; + } +} - global $profile_fields; +function profile_validate_form($edit) { - $enabled_fields = _profile_active_fields($mode); + // Validate the title: - if (in_array("birthday", $enabled_fields) && ($birth_error = _profile_validate_birth($edit))) { - $error .= $birth_error ."<br />"; + if (!$edit['title']) { + return t('You must enter a title.'); } - if (in_array("avatar", $enabled_fields) && ($avatar_error = _profile_validate_avatar($edit, $user))) { - $error .= $avatar_error ."<br />"; - } + // Validate the 'form name': - foreach (array_keys($profile_fields) as $field) { - // replicate any key which was saved during registration but is not in this form - if (!$edit[$field] && $user->$field) { - $edit[$field] = $user->$field; - } + 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.'); } - // now check for required fields - foreach (_profile_active_fields("required") as $required) { - if ($required != "0" && in_array($required, $enabled_fields)) { - if (!$edit["profile_". $required]) { - $error .= t("This required field is missing: %a", array("%a" => $profile_fields[$required][1])) ."<br />"; - } - } + if (in_array($edit['name'], user_fields())) { + return t('The specified form name is reserved for use by Drupal.'); } - return $error ? $error : $edit; + // Validate the category: + + if (!$edit['category']) { + return t('You must enter a category.'); + } } -function _profile_user_view(&$user, $mode) { - global $profile_fields; +function profile_admin_add($type) { + $type = _profile_field_types($type); - foreach (_profile_active_fields($mode) as $name) { - $field = $profile_fields[$name]; - $t = "profile_". $name; - if (!empty($user->$t)) { - switch ($field[0]) { - case "textfield": - case "textarea": - case "checkbox": - $value = ($t == "profile_homepage") ? "<a href=\"". drupal_specialchars($user->$t) ."\">". check_output($user->$t) ."</a>" : check_output($user->$t); - $output .= form_item($field[1], $value); - break; - case "select": - $output .= form_item($field[1], check_output($profile_fields[$name][3][$user->$t])); - break; - case "": - // special - if ($t == "profile_avatar") { - if (file_exists($user->$t)) { - $output .= form_item(t("Avatar"), '<img src="'. file_create_url($user->$t) .'" alt="" title="" />'); - } - } + if ($_POST['op']) { + $data = $_POST['edit']; - if ($t == "profile_birthday") { - if (isset($user->profile_birthday) && isset($user->profile_birthmonth) && isset($user->profile_birthyear)) { - // this is very european-centric, can we use format_date? - $time = mktime(0, 0, 0, $user->profile_birthmonth, $user->profile_birthday, $user->profile_birthyear); - $output .= form_item(t("Birthday"), format_date($time, "custom", "F j, Y")); - } - } - } + if ($error = profile_validate_form($data)) { + drupal_set_message($error, 'error'); } - } - return $output; -} + else { + db_query("INSERT INTO {profile_fields} (title, name, explanation, category, type, weight, overview, options) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, '%s')", $data['title'], $data['name'], $data['explanation'], $data['category'], $type, $data['weight'], $data['overview'], $data['options']); -function profile_file_download($file) { - if (strpos($file, variable_get("profile_avatar_path", "avatars") . FILE_SEPARATOR . 'avatar-') === 0) { - list($width, $height, $type, $attr) = getimagesize(file_create_path($file)); - $types = array( - IMAGETYPE_GIF => 'image/gif', - IMAGETYPE_JPEG => 'image/jpeg', - IMAGETYPE_PNG => 'image/png', - IMAGETYPE_SWF => 'application/x-shockwave-flash', - IMAGETYPE_PSD => 'image/psd', - IMAGETYPE_BMP => 'image/bmp', - IMAGETYPE_TIFF_II => 'image/tiff', - IMAGETYPE_TIFF_MM => 'image/tiff', - IMAGETYPE_JPC => 'application/octet-stream', - IMAGETYPE_JP2 => 'image/jp2', - IMAGETYPE_JPX => 'application/octet-stream', - IMAGETYPE_JB2 => 'application/octet-stream', - IMAGETYPE_SWC => 'application/x-shockwave-flash', - IMAGETYPE_IFF => 'image/iff', - IMAGETYPE_WBMP => 'image/vnd.wap.wbmp', - IMAGETYPE_XBM => 'image/xbm' - ); - return array('Content-type: '. $types[$type]); + drupal_set_message(t('the field has been created.')); + } } + else { + $data = array('name' => 'profile_'); + } + + print theme('page', _profile_field_form($type, $data), t('Add new %type', array('%type' => $type))); } -function _profile_validate_avatar(&$edit, $user) { - // check that uploaded file is an image, with a maximum file size and maximum height/width +function profile_admin_edit($fid) { - unset($edit["profile_avatar"]); + if ($_POST['op']) { + $data = $_POST['edit']; - if (!$file = file_check_upload('profile_avatar')) { - $edit["profile_avatar"] = $user->profile_avatar; - return; - } + if ($error = profile_validate_form($data)) { + drupal_set_message($error, 'error'); - $extension = strtolower(strrchr($file->name, ".")); - $size = getimagesize($file->path); - list($maxwidth, $maxheight) = explode("x", variable_get("profile_avatar_dimensions", "85x85")); - if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) { - $error = t("The uploaded file was not an image."); - } - else if ($file->size > (variable_get("profile_avatar_file_size", "30") * 1000)) { - $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get("profile_avatar_file_size", "30"))); - } - else if ($size[0] > $maxwidth || $size[1] > $maxheight) { - $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get("profile_avatar_dimensions", "85x85"))); - } - else if ($file = file_save_upload('profile_avatar', variable_get("profile_avatar_path", "avatars") . FILE_SEPARATOR .'avatar-'. $user->uid . $extension, 1)) { - $edit["profile_avatar"] = $file->path; + } + else { + db_query("UPDATE {profile_fields} SET title = '%s', name = '%s', explanation = '%s', category = '%s', weight = %d, overview = %d, options = '%s' WHERE fid = %d", $data['title'], $data['name'], $data['explanation'], $data['category'], $data['weight'], $data['overview'], $data['options'], $fid); + + drupal_set_message(t('the field has been updated.')); + } } else { - $error = t("Failed to upload the avatar image; the '%directory' directory doesn't exist.", array("%directory" => variable_get("profile_avatar_path", "avatars"))); + $data = db_fetch_array(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid)); } - return $error ? "$error<br />" : ""; + print theme('page', _profile_field_form($data['type'], $data), t('Edit %type', array('%type' => $edit['type']))); } -function _profile_active_fields($mode) { - return variable_get("profile_". $mode ."_fields", array()); +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')); } -function _profile_edit_birth($edit = "") { - global $profile_months, $profile_days; - $output = _profile_select("profile_birthday", $edit->profile_birthday, $profile_days); - $output .= " "; - $output .= _profile_select("profile_birthmonth", $edit->profile_birthmonth, $profile_months); - $output .= " "; - $output .= "<input type=\"text\" maxlength=\"4\" name=\"edit[profile_birthyear]\" size=\"5\" value=\"$edit->profile_birthyear\" />"; - return $output; -} +function _profile_field_form($type, $edit = array()) { + + $output = 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'."), NULL, FORM_REQUIRED); + $output .= 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. Because the form name's usage, spaces or any other special characters except dash (-) and underscore (_) are not allowed. An example for, name is 'profile_favorite_color' or just 'profile_color'.")); + $output .= 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.")); + $output .= 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'.")); + $output .= 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.")); + $output .= form_checkbox(t('Display this field on member listsings'), 'overview', 1, $edit['overview']); -function _profile_validate_birth(&$edit) { - if (!$edit["profile_birthday"] && !$edit["profile_birthmonth"] && !$edit["profile_birthyear"]) { - // change this if you want required birth - return; + if ($type == 'selection') { + $output .= form_textarea(t('Selection options'), 'options', $edit['options'], 70, 8, t("A list op all options. Put each option on a separate line. Example options are 'red', 'blue', 'green', etc.")); } - if ($edit["profile_birthyear"] > 1900 && checkdate($edit["profile_birthmonth"], $edit["profile_birthday"], $edit["profile_birthyear"])) { - return; + $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")); } - else { - return t("The specified birthday is not valid.") ."<br />"; + + $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>"; } + $output .= '</ul>'; + + print theme('page', $output); } -function _profile_select($name, $value, $options, $extra = 0, $multiple = 0) { - if (count($options) > 0) { - foreach ($options as $key=>$choice) { - $select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($key == $value ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>"; +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) { + if ($user->{$field->name}) { + if ($field->type == 'checkbox') { + $output .= "<div class=\"field\">". $field->title ."</div>"; + } + else { + $output .= "<div class=\"field\">". $user->{$field->name} ."</div>"; + } } - return "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple " : "") . ($extra ? " $extra" : "") .">$select</select>"; } + + $output .= "</div>\n"; + + return $output; +} + +function _profile_field_types($type = NULL) { + $types = array('textfield', 'textarea', 'checkbox', 'selection'); + return isset($type) ? $types[$type] : $types; } ?> |