diff --git a/modules/comment/comment.module b/modules/comment/comment.module index f9af40a..d35885f 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -140,6 +140,17 @@ function comment_entity_info() { } /** + * Implements hook_entity_prepare_view(). + * + * Load user account objects into comment entities. + */ +function comment_entity_prepare_view($prepare, $entity_type) { + if ($entity_type == 'comment') { + user_attach_accounts($prepare); + } +} + +/** * Menu loader callback for Field UI paths. * * Return a comment bundle name from a node type in the URL. @@ -1686,7 +1697,7 @@ class CommentController extends DrupalDefaultEntityController { $query->addField('n', 'type', 'node_type'); $query->innerJoin('users', 'u', 'base.uid = u.uid'); $query->addField('u', 'name', 'registered_name'); - $query->fields('u', array('uid', 'signature', 'signature_format', 'picture')); + $query->fields('u', array('uid', 'signature', 'signature_format')); return $query; } @@ -2271,7 +2282,11 @@ function template_preprocess_comment(&$variables) { $variables['changed'] = format_date($comment->changed); $variables['new'] = !empty($comment->new) ? t('new') : ''; - $variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $comment)) : ''; + $variables['picture'] = array(); + if (theme_get_setting('toggle_comment_user_picture') ) { + // To change user picture settings (e.g. image style), edit the 'compact' view mode on User entity. + $variables['picture'] = user_view($comment->account, 'compact'); + } $variables['signature'] = $comment->signature; $uri = entity_uri('comment', $comment); diff --git a/modules/comment/comment.pages.inc b/modules/comment/comment.pages.inc index 7e88bff..1f17986 100644 --- a/modules/comment/comment.pages.inc +++ b/modules/comment/comment.pages.inc @@ -47,7 +47,7 @@ function comment_reply($node, $pid = NULL) { if ($pid) { if (user_access('access comments')) { // Load the comment whose cid = $pid - $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( + $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( ':cid' => $pid, ':status' => COMMENT_PUBLISHED, ))->fetchObject(); diff --git a/modules/comment/comment.tpl.php b/modules/comment/comment.tpl.php index a483813..ec239fe 100644 --- a/modules/comment/comment.tpl.php +++ b/modules/comment/comment.tpl.php @@ -20,7 +20,7 @@ * - $permalink: Comment permalink. * - $submitted: Submission information created from $author and $created during * template_preprocess_comment(). - * - $picture: Authors picture. + * - $picture: Authors picture. Use render() when printing it. * - $signature: Authors signature. * - $status: Comment status. Possible values are: * comment-unpublished, comment-published or comment-preview. @@ -58,7 +58,7 @@ */ ?>
> - + diff --git a/modules/node/node.module b/modules/node/node.module index 0c3cfb7..74851c8 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -232,6 +232,17 @@ function node_entity_info() { } /** + * Implements hook_entity_prepare_view(). + * + * Load user account objects into node entities. + */ +function node_entity_prepare_view($prepare, $entity_type) { + if ($entity_type == 'node') { + user_attach_accounts($prepare); + } +} + +/** * Implements hook_field_display_ENTITY_TYPE_alter(). */ function node_field_display_node_alter(&$display, $context) { @@ -1468,7 +1479,11 @@ function template_preprocess_node(&$variables) { if (variable_get('node_submitted_' . $node->type, TRUE)) { $variables['display_submitted'] = TRUE; $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['name'], '!datetime' => $variables['date'])); - $variables['user_picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', array('account' => $node)) : ''; + $variables['user_picture'] = array(); + if (theme_get_setting('toggle_node_user_picture')) { + // To change user picture settings (e.g. image style), edit the 'compact' view mode on User entity. + $variables['user_picture'] = user_view($node->account, 'compact'); + } } else { $variables['display_submitted'] = FALSE; diff --git a/modules/node/node.pages.inc b/modules/node/node.pages.inc index d92e8b7..b2af11e 100644 --- a/modules/node/node.pages.inc +++ b/modules/node/node.pages.inc @@ -335,7 +335,6 @@ function node_preview($node) { // user ID 0 denotes the anonymous user. if ($user = user_load_by_name($node->name)) { $node->uid = $user->uid; - $node->picture = $user->picture; } else { $node->uid = 0; // anonymous user @@ -344,7 +343,6 @@ function node_preview($node) { elseif ($node->uid) { $user = user_load($node->uid); $node->name = $user->name; - $node->picture = $user->picture; } $node->changed = REQUEST_TIME; diff --git a/modules/node/node.tpl.php b/modules/node/node.tpl.php index 06dc199..2a78ac8 100644 --- a/modules/node/node.tpl.php +++ b/modules/node/node.tpl.php @@ -10,7 +10,7 @@ * or print a subset such as render($content['field_example']). Use * hide($content['field_example']) to temporarily suppress the printing of a * given element. - * - $user_picture: The node author's picture from user-picture.tpl.php. + * - $user_picture: The node author's picture. Use render() when printing. * - $date: Formatted creation date. Preprocess functions can reformat it by * calling format_date() with the desired parameters on the $created variable. * - $name: Themed username of node author output from theme_username(). @@ -80,7 +80,7 @@ ?>
> - + diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc index b08f418..8bc70bb 100644 --- a/modules/system/system.admin.inc +++ b/modules/system/system.admin.inc @@ -416,7 +416,7 @@ function system_theme_settings($form, &$form_state, $key = '') { // Some features are not always available $disabled = array(); - if (!variable_get('user_pictures', 0)) { + if (!user_picture_enabled()) { $disabled['toggle_node_user_picture'] = TRUE; $disabled['toggle_comment_user_picture'] = TRUE; } @@ -1489,7 +1489,7 @@ function system_site_information_settings() { '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)), '#description' => t('The maximum number of posts displayed on overview pages such as the front page.'), '#access' => (variable_get('site_frontpage')=='node'), - ); + ); $form['error_page'] = array( '#type' => 'fieldset', '#title' => t('Error pages'), diff --git a/modules/user/user-picture.tpl.php b/modules/user/user-picture.tpl.php deleted file mode 100644 index a33d266..0000000 --- a/modules/user/user-picture.tpl.php +++ /dev/null @@ -1,21 +0,0 @@ - - -
- -
- diff --git a/modules/user/user-profile.tpl.php b/modules/user/user-profile.tpl.php index a1611c8..ce4f2b1 100644 --- a/modules/user/user-profile.tpl.php +++ b/modules/user/user-profile.tpl.php @@ -8,12 +8,11 @@ * e.g., example.com/user/123. 123 being the users ID. * * Use render($user_profile) to print all profile items, or print a subset - * such as render($user_profile['user_picture']). Always call - * render($user_profile) at the end in order to print all remaining items. If - * the item is a category, it will contain all its profile items. By default, - * $user_profile['summary'] is provided, which contains data on the user's - * history. Other data can be included by modules. $user_profile['user_picture'] - * is available for showing the account picture. + * such as render($content['field_example']). Always call render($user_profile) + * at the end in order to print all remaining items. If the item is a category, + * it will contain all its profile items. By default, $user_profile['summary'] + * is provided which contains data on the user's history. Other data can be + * included by modules. * * Available variables: * - $user_profile: An array of profile items. Use render() to print them. diff --git a/modules/user/user-rtl.css b/modules/user/user-rtl.css index 642c943..07a402d 100644 --- a/modules/user/user-rtl.css +++ b/modules/user/user-rtl.css @@ -27,8 +27,7 @@ div.password-confirm { clear: right; } -/* Generated by user.module but used by profile.module: */ -.profile .user-picture { +.profile .field-name-field-user-picture { float: left; margin: 0 0 1em 1em; } diff --git a/modules/user/user.admin.inc b/modules/user/user.admin.inc index 4789e7e..1a7186e 100644 --- a/modules/user/user.admin.inc +++ b/modules/user/user.admin.inc @@ -347,79 +347,6 @@ function user_admin_settings() { '#title' => t('Enable signatures.'), '#default_value' => variable_get('user_signatures', 0), ); - // If picture support is enabled, check whether the picture directory exists. - if (variable_get('user_pictures', 0)) { - $picture_path = file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures'); - if (!file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY)) { - form_set_error('user_picture_path', t('The directory %directory does not exist or is not writable.', array('%directory' => $picture_path))); - watchdog('file system', 'The directory %directory does not exist or is not writable.', array('%directory' => $picture_path), WATCHDOG_ERROR); - } - } - $picture_support = variable_get('user_pictures', 0); - $form['personalization']['user_pictures'] = array( - '#type' => 'checkbox', - '#title' => t('Enable user pictures.'), - '#default_value' => $picture_support, - ); - drupal_add_js(drupal_get_path('module', 'user') . '/user.js'); - $form['personalization']['pictures'] = array( - '#type' => 'container', - '#states' => array( - // Hide the additional picture settings when user pictures are disabled. - 'invisible' => array( - 'input[name="user_pictures"]' => array('checked' => FALSE), - ), - ), - ); - $form['personalization']['pictures']['user_picture_path'] = array( - '#type' => 'textfield', - '#title' => t('Picture directory'), - '#default_value' => variable_get('user_picture_path', 'pictures'), - '#size' => 30, - '#maxlength' => 255, - '#description' => t('Subdirectory in the file upload directory where pictures will be stored.'), - ); - $form['personalization']['pictures']['user_picture_default'] = array( - '#type' => 'textfield', - '#title' => t('Default picture'), - '#default_value' => variable_get('user_picture_default', ''), - '#size' => 30, - '#maxlength' => 255, - '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'), - ); - if (module_exists('image')) { - $form['personalization']['pictures']['settings']['user_picture_style'] = array( - '#type' => 'select', - '#title' => t('Picture display style'), - '#options' => image_style_options(TRUE), - '#default_value' => variable_get('user_picture_style', ''), - '#description' => t('The style selected will be used on display, while the original image is retained. Styles may be configured in the Image styles administration area.', array('!url' => url('admin/config/media/image-styles'))), - ); - } - $form['personalization']['pictures']['user_picture_dimensions'] = array( - '#type' => 'textfield', - '#title' => t('Picture upload dimensions'), - '#default_value' => variable_get('user_picture_dimensions', '85x85'), - '#size' => 10, - '#maxlength' => 10, - '#field_suffix' => ' ' . t('pixels'), - '#description' => t('Pictures larger than this will be scaled down to this size.'), - ); - $form['personalization']['pictures']['user_picture_file_size'] = array( - '#type' => 'textfield', - '#title' => t('Picture upload file size'), - '#default_value' => variable_get('user_picture_file_size', '30'), - '#size' => 10, - '#maxlength' => 10, - '#field_suffix' => ' ' . t('KB'), - '#description' => t('Maximum allowed file size for uploaded pictures. Upload size is normally limited only by the PHP maximum post and file upload settings, and images are automatically scaled down to the dimensions specified above.'), - ); - $form['personalization']['pictures']['user_picture_guidelines'] = array( - '#type' => 'textarea', - '#title' => t('Picture guidelines'), - '#default_value' => variable_get('user_picture_guidelines', ''), - '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."), - ); $form['email_title'] = array( '#type' => 'item', @@ -1034,4 +961,3 @@ function user_admin_role_delete_confirm_submit($form, &$form_state) { drupal_set_message(t('The role has been deleted.')); $form_state['redirect'] = 'admin/people/permissions/roles'; } - diff --git a/modules/user/user.api.php b/modules/user/user.api.php index 0b4f38f..72ff958 100644 --- a/modules/user/user.api.php +++ b/modules/user/user.api.php @@ -327,10 +327,6 @@ function hook_user_logout($account) { * @see hook_entity_view() */ function hook_user_view($account, $view_mode, $langcode) { - $account->content['user_picture'] = array( - '#markup' => theme('user_picture', array('account' => $account)), - '#weight' => -10, - ); if (!isset($account->content['summary'])) { $account->content['summary'] = array(); } diff --git a/modules/user/user.css b/modules/user/user.css index a303307..a77e212 100644 --- a/modules/user/user.css +++ b/modules/user/user.css @@ -78,12 +78,11 @@ div.password-suggestions ul { width: 36.3em; } -/* Generated by user.module but used by profile.module: */ .profile { clear: both; margin: 1em 0; } -.profile .user-picture { +.profile .field-name-field-user-picture { float: right; /* LTR */ margin: 0 1em 1em 0; /* LTR */ } diff --git a/modules/user/user.entity.inc b/modules/user/user.entity.inc index 5549c77..23eefac 100644 --- a/modules/user/user.entity.inc +++ b/modules/user/user.entity.inc @@ -13,10 +13,7 @@ class UserController extends DrupalDefaultEntityController { function attachLoad(&$queried_users, $revision_id = FALSE) { - // Build an array of user picture IDs so that these can be fetched later. - $picture_fids = array(); foreach ($queried_users as $key => $record) { - $picture_fids[] = $record->picture; $queried_users[$key]->data = unserialize($record->data); $queried_users[$key]->roles = array(); if ($record->uid) { @@ -33,18 +30,6 @@ class UserController extends DrupalDefaultEntityController { $queried_users[$record->uid]->roles[$record->rid] = $record->name; } - // Add the full file objects for user pictures if enabled. - if (!empty($picture_fids) && variable_get('user_pictures', 1) == 1) { - $pictures = file_load_multiple($picture_fids); - foreach ($queried_users as $account) { - if (!empty($account->picture) && isset($pictures[$account->picture])) { - $account->picture = $pictures[$account->picture]; - } - else { - $account->picture = NULL; - } - } - } // Call the default attachLoad() method. This will add fields and call // hook_user_load(). parent::attachLoad($queried_users, $revision_id); diff --git a/modules/user/user.install b/modules/user/user.install index 370427f..d551ef5 100644 --- a/modules/user/user.install +++ b/modules/user/user.install @@ -209,12 +209,6 @@ function user_schema() { 'default' => '', 'description' => "User's default language.", ), - 'picture' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => "Foreign key: {file_managed}.fid of user's picture.", - ), 'init' => array( 'type' => 'varchar', 'length' => 254, @@ -335,3 +329,35 @@ function user_install() { ->execute(); } } + + +/** + * @addtogroup updates-7.x-to-8.x Updates from 7.x to 8.x + * @{ + * Update functions from 7.x to 8.x. + */ + +/** + * Migrate user pictures to Field API. + */ +function user_update_8000() { + $results = db_select('users', 'u') + ->fields('u', array('uid', 'picture')) + ->condition('picture', 0, '>') + ->execute() + ->fetchAllKeyed(); + if ($uids = array_keys($results)) { + $accounts = user_load_multiple($uids); + foreach ($results as $uid => $fid) { + if ($file = file_load($fid)) { + $edit['field_user_picture'][LANGUAGE_NONE][0] = (array)$file; + user_save($accounts[$uid], $edit); + } + } + } +} + +/** + * @} End of "addtogroup updates-7.x-to-8.x" + * The next series of updates should start at 9000. + */ diff --git a/modules/user/user.module b/modules/user/user.module index 14e1459..57ef74c 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -49,7 +49,7 @@ function user_help($path, $arg) { $output .= '
' . t('User roles and permissions') . '
'; $output .= '
' . t('Roles are used to group and classify users; each user can be assigned one or more roles. By default there are two roles: anonymous user (users that are not logged in) and authenticated user (users that are registered and logged in). Depending on choices you made when you installed Drupal, the installation process may have defined more roles, and you can create additional custom roles on the Roles page. After creating roles, you can set permissions for each role on the Permissions page. Granting a permission allows users who have been assigned a particular role to perform an action on the site, such as viewing a particular type of content, editing or creating content, administering settings for a particular module, or using a particular function of the site (such as search).', array('@permissions_user' => url('admin/people/permissions'), '@roles' => url('admin/people/permissions/roles'))) . '
'; $output .= '
' . t('Account settings') . '
'; - $output .= '
' . t('The Account settings page allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization (including signatures and user pictures), and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '
'; + $output .= '
' . t('The Account settings page allows you to manage settings for the displayed name of the anonymous user role, personal contact forms, user registration, and account cancellation. On this page you can also manage settings for account personalization (including signatures), and adapt the text for the e-mail messages that are sent automatically during the user registration process.', array('@accounts' => url('admin/config/people/accounts'))) . '
'; $output .= ''; return $output; case 'admin/people/create': @@ -107,10 +107,6 @@ function user_module_invoke($type, &$edit, $account, $category = NULL) { */ function user_theme() { return array( - 'user_picture' => array( - 'variables' => array('account' => NULL), - 'template' => 'user-picture', - ), 'user_profile' => array( 'render element' => 'elements', 'template' => 'user-profile', @@ -176,6 +172,10 @@ function user_entity_info() { 'label' => t('User account'), 'custom settings' => FALSE, ), + 'compact' => array( + 'label' => t('Compact'), + 'custom settings' => TRUE, + ) ), ), ); @@ -192,6 +192,41 @@ function user_uri($user) { } /** + * Populate $entity->account for each prepared entity. + * + * Called by hook_entity_prepare_view() implementations. + * + * @param $entities + * The entities keyed by entity ID. + */ +function user_attach_accounts($entities) { + $uids = array(); + foreach ($entities as $entity) { + $uids[] = $entity->uid; + } + $uids = array_unique($uids); + $accounts = user_load_multiple($uids); + foreach ($entities as $id => $entity) { + $entities[$id]->account = new stdClass; + if (isset($accounts[$entity->uid])) { + $entities[$id]->account = $accounts[$entity->uid]; + } + } +} + +/** + * Does this site support core's user picture feature. + * + * Alternate user picture implementations (e.g. gravatar) should provide own + * add/edit/delete forms and populate 'picture' variable during preprocess stage. + * This approach preserves compatibility with node/comment templates. + */ +function user_picture_enabled() { + $instances = field_info_instances('user', 'user'); + return isset($instances['field_user_picture']) && !$instances['field_user_picture']['deleted']; +} + +/** * Implements hook_field_info_alter(). */ function user_field_info_alter(&$info) { @@ -420,34 +455,6 @@ function user_save($account, $edit = array(), $category = 'account') { module_invoke_all('entity_presave', $account, 'user'); if (is_object($account) && !$account->is_new) { - // Process picture uploads. - if (!empty($account->picture->fid) && (!isset($account->original->picture->fid) || $account->picture->fid != $account->original->picture->fid)) { - $picture = $account->picture; - // If the picture is a temporary file move it to its final location and - // make it permanent. - if (!$picture->status) { - $info = image_get_info($picture->uri); - $picture_directory = file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures'); - - // Prepare the pictures directory. - file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY); - $destination = file_stream_wrapper_uri_normalize($picture_directory . '/picture-' . $account->uid . '-' . REQUEST_TIME . '.' . $info['extension']); - - // Move the temporary file into the final location. - if ($picture = file_move($picture, $destination, FILE_EXISTS_RENAME)) { - $picture->status = FILE_STATUS_PERMANENT; - $account->picture = file_save($picture); - file_usage_add($picture, 'user', 'user', $account->uid); - } - } - // Delete the previous picture if it was deleted or replaced. - if (!empty($account->original->picture->fid)) { - file_usage_delete($account->original->picture, 'user', 'user', $account->uid); - file_delete($account->original->picture); - } - } - $account->picture = empty($account->picture->fid) ? 0 : $account->picture->fid; - // Do not allow 'uid' to be changed. $account->uid = $account->original->uid; // Save changes to the user table. @@ -622,29 +629,6 @@ function user_validate_mail($mail) { } /** - * Validates an image uploaded by a user. - * - * @see user_account_form() - */ -function user_validate_picture(&$form, &$form_state) { - // If required, validate the uploaded picture. - $validators = array( - 'file_validate_is_image' => array(), - 'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')), - 'file_validate_size' => array(variable_get('user_picture_file_size', '30') * 1024), - ); - - // Save the file as a temporary file. - $file = file_save_upload('picture_upload', $validators); - if ($file === FALSE) { - form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures')))); - } - elseif ($file !== NULL) { - $form_state['values']['picture_upload'] = $file; - } -} - -/** * Generate a random alphanumeric password. */ function user_password($length = 10) { @@ -809,45 +793,6 @@ function user_permission() { } /** - * Implements hook_file_download(). - * - * Ensure that user pictures (avatars) are always downloadable. - */ -function user_file_download($uri) { - if (strpos(file_uri_target($uri), variable_get('user_picture_path', 'pictures') . '/picture-') === 0) { - $info = image_get_info($uri); - return array('Content-Type' => $info['mime_type']); - } -} - -/** - * Implements hook_file_move(). - */ -function user_file_move($file, $source) { - // If a user's picture is replaced with a new one, update the record in - // the users table. - if (isset($file->fid) && isset($source->fid) && $file->fid != $source->fid) { - db_update('users') - ->fields(array( - 'picture' => $file->fid, - )) - ->condition('picture', $source->fid) - ->execute(); - } -} - -/** - * Implements hook_file_delete(). - */ -function user_file_delete($file) { - // Remove any references to the file. - db_update('users') - ->fields(array('picture' => 0)) - ->condition('picture', $file->fid) - ->execute(); -} - -/** * Implements hook_search_info(). */ function user_search_info() { @@ -945,7 +890,6 @@ function user_user_view($account) { * * @see user_account_form_validate() * @see user_validate_current_pass() - * @see user_validate_picture() * @see user_validate_mail() */ function user_account_form(&$form, &$form_state) { @@ -1089,34 +1033,6 @@ function user_account_form(&$form, &$form_state) { '#description' => t('Your signature will be publicly displayed at the end of your comments.'), '#format' => isset($account->signature_format) ? $account->signature_format : NULL, ); - - // Picture/avatar. - $form['picture'] = array( - '#type' => 'fieldset', - '#title' => t('Picture'), - '#weight' => 1, - '#access' => (!$register && variable_get('user_pictures', 0)), - ); - $form['picture']['picture'] = array( - '#type' => 'value', - '#value' => isset($account->picture) ? $account->picture : NULL, - ); - $form['picture']['picture_current'] = array( - '#markup' => theme('user_picture', array('account' => $account)), - ); - $form['picture']['picture_delete'] = array( - '#type' => 'checkbox', - '#title' => t('Delete picture'), - '#access' => !empty($account->picture->fid), - '#description' => t('Check this box to delete your current picture.'), - ); - $form['picture']['picture_upload'] = array( - '#type' => 'file', - '#title' => t('Upload picture'), - '#size' => 48, - '#description' => t('Your virtual face or picture. Pictures larger than @dimensions pixels will be scaled down.', array('@dimensions' => variable_get('user_picture_dimensions', '85x85'))) . ' ' . filter_xss_admin(variable_get('user_picture_guidelines', '')), - ); - $form['#validate'][] = 'user_validate_picture'; } /** @@ -1201,13 +1117,6 @@ function user_account_form_validate($form, &$form_state) { */ function user_user_presave(&$edit, $account, $category) { if ($category == 'account' || $category == 'register') { - if (!empty($edit['picture_upload'])) { - $edit['picture'] = $edit['picture_upload']; - } - // Delete picture if requested, and if no replacement picture was given. - elseif (!empty($edit['picture_delete'])) { - $edit['picture'] = NULL; - } // Prepare user roles. if (isset($edit['roles'])) { $edit['roles'] = array_filter($edit['roles']); @@ -1381,55 +1290,6 @@ function user_block_view($delta = '') { } /** - * Process variables for user-picture.tpl.php. - * - * The $variables array contains the following arguments: - * - $account: A user, node or comment object with 'name', 'uid' and 'picture' - * fields. - * - * @see user-picture.tpl.php - */ -function template_preprocess_user_picture(&$variables) { - $variables['user_picture'] = ''; - if (variable_get('user_pictures', 0)) { - $account = $variables['account']; - if (!empty($account->picture)) { - // @TODO: Ideally this function would only be passed file objects, but - // since there's a lot of legacy code that JOINs the {users} table to - // {node} or {comments} and passes the results into this function if we - // a numeric value in the picture field we'll assume it's a file id - // and load it for them. Once we've got user_load_multiple() and - // comment_load_multiple() functions the user module will be able to load - // the picture files in mass during the object's load process. - if (is_numeric($account->picture)) { - $account->picture = file_load($account->picture); - } - if (!empty($account->picture->uri)) { - $filepath = $account->picture->uri; - } - } - elseif (variable_get('user_picture_default', '')) { - $filepath = variable_get('user_picture_default', ''); - } - if (isset($filepath)) { - $alt = t("@user's picture", array('@user' => format_username($account))); - // If the image does not have a valid Drupal scheme (for eg. HTTP), - // don't load image styles. - if (module_exists('image') && file_valid_uri($filepath) && $style = variable_get('user_picture_style', '')) { - $variables['user_picture'] = theme('image_style', array('style_name' => $style, 'path' => $filepath, 'alt' => $alt, 'title' => $alt)); - } - else { - $variables['user_picture'] = theme('image', array('path' => $filepath, 'alt' => $alt, 'title' => $alt)); - } - if (!empty($account->uid) && user_access('access user profiles')) { - $attributes = array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE); - $variables['user_picture'] = l($variables['user_picture'], "user/$account->uid", $attributes); - } - } - } -} - -/** * Returns HTML for a list of users. * * @param $variables @@ -2447,8 +2307,6 @@ function user_view_page($account) { * Profile categories keyed by their human-readable names. * - $page['content']['Profile Category']['profile_machine_name']: * Profile fields keyed by their machine-readable names. - * - $page['content']['user_picture']: - * User's rendered picture. * - $page['content']['summary']: * Contains the default "History" profile data for a user. * - $page['content']['#account']: @@ -3515,6 +3373,9 @@ function user_form_process_password_confirm($element) { /** * Implements hook_node_load(). + * + * @todo: Deprecated by node_entity_prepare_view(). Update code that depends on + * these properties. */ function user_node_load($nodes, $types) { // Build an array of all uids for node authors, keyed by nid. @@ -3523,13 +3384,12 @@ function user_node_load($nodes, $types) { $uids[$nid] = $node->uid; } - // Fetch name, picture, and data for these users. - $user_fields = db_query("SELECT uid, name, picture, data FROM {users} WHERE uid IN (:uids)", array(':uids' => $uids))->fetchAllAssoc('uid'); + // Fetch name and data for these users. + $user_fields = db_query("SELECT uid, name, data FROM {users} WHERE uid IN (:uids)", array(':uids' => $uids))->fetchAllAssoc('uid'); // Add these values back into the node objects. foreach ($uids as $nid => $uid) { $nodes[$nid]->name = $user_fields[$uid]->name; - $nodes[$nid]->picture = $user_fields[$uid]->picture; $nodes[$nid]->data = $user_fields[$uid]->data; } } diff --git a/modules/user/user.test b/modules/user/user.test index 6ecbfac..cfbed55 100644 --- a/modules/user/user.test +++ b/modules/user/user.test @@ -167,7 +167,6 @@ class UserRegistrationTestCase extends DrupalWebTestCase { $this->assertEqual($new_user->status, variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) == USER_REGISTER_VISITORS ? 1 : 0, t('Correct status field.')); $this->assertEqual($new_user->timezone, variable_get('date_default_timezone'), t('Correct time zone field.')); $this->assertEqual($new_user->language, '', t('Correct language field.')); - $this->assertEqual($new_user->picture, '', t('Correct picture field.')); $this->assertEqual($new_user->init, $mail, t('Correct init field.')); } @@ -250,13 +249,49 @@ class UserRegistrationTestCase extends DrupalWebTestCase { // Check user fields. $accounts = user_load_multiple(array(), array('name' => $name, 'mail' => $mail)); $new_user = reset($accounts); - $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][0]['value'], $value, t('@js : The field value was correclty saved.', array('@js' => $js))); + $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][0]['value'], $value, t('@js : The field value was correctly saved.', array('@js' => $js))); $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][1]['value'], $value + 1, t('@js : The field value was correclty saved.', array('@js' => $js))); $this->assertEqual($new_user->test_user_field[LANGUAGE_NONE][2]['value'], $value + 2, t('@js : The field value was correclty saved.', array('@js' => $js))); } } } +class UserOnNodePage extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Embedded user on node page.', + 'description' => 'Verify that author details are shown on node and comment render.', + 'group' => 'User' + ); + } + + function testUserViewOnNodePage() { + $this->user = $this->drupalCreateUser(); + $this->drupalLogin($this->user); + $edit = array( + 'mail' => $this->user->mail, + ); + $test_image = current($this->drupalGetTestFiles('image')); + $edit['files[field_user_picture_' . LANGUAGE_NONE . '_0]'] = drupal_realpath($test_image->uri); + $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save')); + unset($edit); + + $node = $this->drupalCreateNode(array('type' => 'article')); + // Set display preferences so pictures are enabled for this content type. + variable_set('theme_settings', array('toggle_node_user_picture' => TRUE)); + variable_set('node_submitted_' . $node->type, TRUE); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw('field-name-field-user-picture', 'User picture is shown on node render.'); + + // Disable picture for nodes and enable for comments. + variable_set('theme_settings', array('toggle_comment_user_picture' => TRUE)); + + $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'] = $this->randomString(); + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertRaw('field-name-field-user-picture', 'User picture is shown on comment render.'); + } +} + class UserValidationTestCase extends DrupalWebTestCase { public static function getInfo() { return array( @@ -849,248 +884,6 @@ class UserCancelTestCase extends DrupalWebTestCase { } } -class UserPictureTestCase extends DrupalWebTestCase { - protected $user; - protected $_directory_test; - - public static function getInfo() { - return array( - 'name' => 'Upload user picture', - 'description' => 'Assure that dimension check, extension check and image scaling work as designed.', - 'group' => 'User' - ); - } - - function setUp() { - parent::setUp(); - // Enable user pictures. - variable_set('user_pictures', 1); - - $this->user = $this->drupalCreateUser(); - - // Test if directories specified in settings exist in filesystem. - $file_dir = 'public://'; - $file_check = file_prepare_directory($file_dir, FILE_CREATE_DIRECTORY); - // TODO: Test public and private methods? - - $picture_dir = variable_get('user_picture_path', 'pictures'); - $picture_path = $file_dir . $picture_dir; - - $pic_check = file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY); - $this->_directory_test = is_writable($picture_path); - $this->assertTrue($this->_directory_test, "The directory $picture_path doesn't exist or is not writable. Further tests won't be made."); - } - - function testNoPicture() { - $this->drupalLogin($this->user); - - // Try to upload a file that is not an image for the user picture. - $not_an_image = current($this->drupalGetTestFiles('html')); - $this->saveUserPicture($not_an_image); - $this->assertRaw(t('Only JPEG, PNG and GIF images are allowed.'), t('Non-image files are not accepted.')); - } - - /** - * Do the test: - * GD Toolkit is installed - * Picture has invalid dimension - * - * results: The image should be uploaded because ImageGDToolkit resizes the picture - */ - function testWithGDinvalidDimension() { - if ($this->_directory_test && image_get_toolkit()) { - $this->drupalLogin($this->user); - - $image = current($this->drupalGetTestFiles('image')); - $info = image_get_info($image->uri); - - // Set new variables: invalid dimensions, valid filesize (0 = no limit). - $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10); - variable_set('user_picture_dimensions', $test_dim); - variable_set('user_picture_file_size', 0); - - $pic_path = $this->saveUserPicture($image); - // Check that the image was resized and is being displayed on the - // user's profile page. - $text = t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $test_dim)); - $this->assertRaw($text, t('Image was resized.')); - $alt = t("@user's picture", array('@user' => format_username($this->user))); - $style = variable_get('user_picture_style', ''); - $this->assertRaw(image_style_url($style, $pic_path), t("Image is displayed in user's edit page")); - - // Check if file is located in proper directory. - $this->assertTrue(is_file($pic_path), t("File is located in proper directory")); - } - } - - /** - * Do the test: - * GD Toolkit is installed - * Picture has invalid size - * - * results: The image should be uploaded because ImageGDToolkit resizes the picture - */ - function testWithGDinvalidSize() { - if ($this->_directory_test && image_get_toolkit()) { - $this->drupalLogin($this->user); - - // Images are sorted first by size then by name. We need an image - // bigger than 1 KB so we'll grab the last one. - $files = $this->drupalGetTestFiles('image'); - $image = end($files); - $info = image_get_info($image->uri); - - // Set new variables: valid dimensions, invalid filesize. - $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); - $test_size = 1; - variable_set('user_picture_dimensions', $test_dim); - variable_set('user_picture_file_size', $test_size); - - $pic_path = $this->saveUserPicture($image); - - // Test that the upload failed and that the correct reason was cited. - $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); - $this->assertRaw($text, t('Upload failed.')); - $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024))); - $this->assertRaw($text, t('File size cited as reason for failure.')); - - // Check if file is not uploaded. - $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); - } - } - - /** - * Do the test: - * GD Toolkit is not installed - * Picture has invalid size - * - * results: The image shouldn't be uploaded - */ - function testWithoutGDinvalidDimension() { - if ($this->_directory_test && !image_get_toolkit()) { - $this->drupalLogin($this->user); - - $image = current($this->drupalGetTestFiles('image')); - $info = image_get_info($image->uri); - - // Set new variables: invalid dimensions, valid filesize (0 = no limit). - $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10); - variable_set('user_picture_dimensions', $test_dim); - variable_set('user_picture_file_size', 0); - - $pic_path = $this->saveUserPicture($image); - - // Test that the upload failed and that the correct reason was cited. - $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); - $this->assertRaw($text, t('Upload failed.')); - $text = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $test_dim)); - $this->assertRaw($text, t('Checking response on invalid image (dimensions).')); - - // Check if file is not uploaded. - $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); - } - } - - /** - * Do the test: - * GD Toolkit is not installed - * Picture has invalid size - * - * results: The image shouldn't be uploaded - */ - function testWithoutGDinvalidSize() { - if ($this->_directory_test && !image_get_toolkit()) { - $this->drupalLogin($this->user); - - $image = current($this->drupalGetTestFiles('image')); - $info = image_get_info($image->uri); - - // Set new variables: valid dimensions, invalid filesize. - $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); - $test_size = 1; - variable_set('user_picture_dimensions', $test_dim); - variable_set('user_picture_file_size', $test_size); - - $pic_path = $this->saveUserPicture($image); - - // Test that the upload failed and that the correct reason was cited. - $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename)); - $this->assertRaw($text, t('Upload failed.')); - $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024))); - $this->assertRaw($text, t('File size cited as reason for failure.')); - - // Check if file is not uploaded. - $this->assertFalse(is_file($pic_path), t('File was not uploaded.')); - } - } - - /** - * Do the test: - * Picture is valid (proper size and dimension) - * - * results: The image should be uploaded - */ - function testPictureIsValid() { - if ($this->_directory_test) { - $this->drupalLogin($this->user); - - $image = current($this->drupalGetTestFiles('image')); - $info = image_get_info($image->uri); - - // Set new variables: valid dimensions, valid filesize (0 = no limit). - $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10); - variable_set('user_picture_dimensions', $test_dim); - variable_set('user_picture_file_size', 0); - - $pic_path = $this->saveUserPicture($image); - - // Check if image is displayed in user's profile page. - $this->drupalGet('user'); - $this->assertRaw(file_uri_target($pic_path), t("Image is displayed in user's profile page")); - - // Check if file is located in proper directory. - $this->assertTrue(is_file($pic_path), t('File is located in proper directory')); - - // Set new picture dimensions. - $test_dim = ($info['width'] + 5) . 'x' . ($info['height'] + 5); - variable_set('user_picture_dimensions', $test_dim); - - $pic_path2 = $this->saveUserPicture($image); - $this->assertNotEqual($pic_path, $pic_path2, t('Filename of second picture is different.')); - } - } - - /** - * Test HTTP schema working with user pictures. - */ - function testExternalPicture() { - $this->drupalLogin($this->user); - // Set the default picture to an URI with a HTTP schema. - $images = $this->drupalGetTestFiles('image'); - $image = $images[0]; - $pic_path = file_create_url($image->uri); - variable_set('user_picture_default', $pic_path); - - // Check if image is displayed in user's profile page. - $this->drupalGet('user'); - - // Get the user picture image via xpath. - $elements = $this->xpath('//div[@class="user-picture"]/img'); - $this->assertEqual(count($elements), 1, t("There is exactly one user picture on the user's profile page")); - $this->assertEqual($pic_path, (string) $elements[0]['src'], t("User picture source is correct.")); - } - - function saveUserPicture($image) { - $edit = array('files[picture_upload]' => drupal_realpath($image->uri)); - $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save')); - - // Load actual user data from database. - $account = user_load($this->user->uid, TRUE); - return isset($account->picture) ? $account->picture->uri : NULL; - } -} - - class UserPermissionsTestCase extends DrupalWebTestCase { protected $admin_user; protected $rid; diff --git a/profiles/standard/standard.install b/profiles/standard/standard.install index 5d44717..9c6ba17 100644 --- a/profiles/standard/standard.install +++ b/profiles/standard/standard.install @@ -258,12 +258,6 @@ function standard_install() { // Don't display date and author information for "Basic page" nodes by default. variable_set('node_submitted_page', FALSE); - // Enable user picture support and set the default to a square thumbnail option. - variable_set('user_pictures', '1'); - variable_set('user_picture_dimensions', '1024x1024'); - variable_set('user_picture_file_size', '800'); - variable_set('user_picture_style', 'thumbnail'); - // Allow visitor account creation with administrative approval. variable_set('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); @@ -387,6 +381,82 @@ function standard_install() { ); field_create_instance($instance); + + + // Create an image field named "User picture", enabled for the 'user' entity. + // Many of the following values will be defaulted, they're included here as an illustrative examples. + // See http://api.drupal.org/api/function/field_create_field/7 + + $field = array( + 'field_name' => 'field_user_picture', + 'type' => 'image', + 'cardinality' => 1, + 'locked' => FALSE, + 'indexes' => array('fid' => array('fid')), + 'settings' => array( + 'uri_scheme' => 'public', + 'default_image' => FALSE, + ), + 'storage' => array( + 'type' => 'field_sql_storage', + 'settings' => array(), + ), + ); + field_create_field($field); + + + // Many of the following values will be defaulted, they're included here as an illustrative examples. + // See http://api.drupal.org/api/function/field_create_instance/7 + $instance = array( + 'field_name' => 'field_user_picture', + 'entity_type' => 'user', + 'label' => 'User Picture', + 'bundle' => 'user', + 'description' => st('Upload an image to go with this user account.'), + 'required' => FALSE, + + 'settings' => array( + 'file_directory' => 'field/user_picture', + 'file_extensions' => 'png gif jpg jpeg', + 'max_filesize' => '', + 'max_resolution' => '', + 'min_resolution' => '', + 'alt_field' => 'User picture', + 'title_field' => '', + ), + + 'widget' => array( + 'type' => 'image_image', + 'settings' => array( + 'progress_indicator' => 'throbber', + 'preview_image_style' => 'medium', + ), + 'weight' => -1, + ), + + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array('image_style' => 'medium', 'image_link' => 'content'), + ), + 'compact' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array('image_style' => 'thumbnail', 'image_link' => 'content'), + ), + ), + ); + field_create_instance($instance); + + // Remove 'summary' pseudo-field from compact view mode on the User entity. + $bundle_settings = field_bundle_settings('user', 'user'); + $bundle_settings['extra_fields']['display']['summary']['compact'] = array( + 'visible' => FALSE, + 'weight' => 10, + ); + field_bundle_settings('user', 'user', $bundle_settings); + // Enable default permissions for system roles. $filtered_html_permission = filter_permission_name($filtered_html_format); user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'access comments', $filtered_html_permission)); diff --git a/themes/bartik/css/style-rtl.css b/themes/bartik/css/style-rtl.css index d25006f..cd7a5c4 100644 --- a/themes/bartik/css/style-rtl.css +++ b/themes/bartik/css/style-rtl.css @@ -82,7 +82,7 @@ ul.tips { /* ----------------- Content ------------------ */ -.submitted .user-picture img { +.submitted .field-name-field-user-picture img { float: right; margin-left: 5px; margin-right: 0; @@ -102,7 +102,7 @@ ul.tips { /* ----------------- Comments ----------------- */ -.comment .user-picture img { +.comment .field-name-field-user-picture img { margin-right: 0; } .comment .attribution { diff --git a/themes/bartik/css/style.css b/themes/bartik/css/style.css index 4fb8210..b89d6f9 100644 --- a/themes/bartik/css/style.css +++ b/themes/bartik/css/style.css @@ -616,7 +616,7 @@ h1#page-title { color: #68696b; margin-bottom: -5px; } -.submitted .user-picture img { +.submitted .field-name-field-user-picture img { float: left; /* LTR */ height: 20px; margin: 1px 5px 0 0; /* LTR */ @@ -651,7 +651,7 @@ h1#page-title { text-align: right; } .field-type-image img, -.user-picture img { +.field-name-field-user-picture img { margin: 0 0 1em; } ul.links { @@ -672,7 +672,7 @@ ul.links { .comment h2.title { margin-bottom: 1em; } -.comment div.user-picture img { +.comment .field-name-field-user-picture img { margin-left: 0; /* LTR */ } .comment { @@ -1056,7 +1056,7 @@ div.messages { /* -------------- User Profile -------------- */ -.profile .user-picture { +.profile .field-name-field-user-picture { float: none; } diff --git a/themes/bartik/templates/comment.tpl.php b/themes/bartik/templates/comment.tpl.php index d64487d..ae5b8ac 100644 --- a/themes/bartik/templates/comment.tpl.php +++ b/themes/bartik/templates/comment.tpl.php @@ -20,7 +20,7 @@ * - $permalink: Comment permalink. * - $submitted: Submission information created from $author and $created during * template_preprocess_comment(). - * - $picture: Authors picture. + * - $picture: Authors picture. Use render() when printing it. * - $signature: Authors signature. * - $status: Comment status. Possible values are: * comment-unpublished, comment-published or comment-preview. @@ -61,7 +61,7 @@
- +