Issue #2458817 by Berdir, dawehner: Creating new user entities for anonymous users is very slow

8.0.x
Alex Pott 2015-04-07 12:39:10 +01:00
parent 804b2c9ffc
commit 3ab0ef9bb8
7 changed files with 41 additions and 64 deletions

View File

@ -631,31 +631,6 @@ function comment_preprocess_block(&$variables) {
} }
} }
/**
* Prepares a user account object for rendering comment authors.
*
* This helper handles anonymous authors in addition to registered comment
* authors.
*
* @param \Drupal\comment\CommentInterface $comment
* The comment to which the author replied.
*
* @return \Drupal\user\UserInterface
* A user account, for use with theme_username() or the user_picture template.
*/
function comment_prepare_author(CommentInterface $comment) {
// The account has been pre-loaded by CommentViewBuilder::buildComponents().
$account = $comment->getOwner();
if (empty($account->uid->value)) {
// @todo Avoid creating a new entity by just creating a new instance
// directly, see https://drupal.org/node/1867228.
$account = entity_create('user', array('uid' => 0, 'name' => $comment->getAuthorName(), 'homepage' => $comment->getHomepage()));
// The anonymous user is not a new account, do not treat it as one.
$account->enforceIsNew(FALSE);
}
return $account;
}
/** /**
* Prepares variables for comment templates. * Prepares variables for comment templates.
* *
@ -673,7 +648,7 @@ function template_preprocess_comment(&$variables) {
$variables['comment'] = $comment; $variables['comment'] = $comment;
$variables['commented_entity'] = $commented_entity; $variables['commented_entity'] = $commented_entity;
$account = comment_prepare_author($comment); $account = $comment->getOwner();
$username = array( $username = array(
'#theme' => 'username', '#theme' => 'username',
'#account' => $account, '#account' => $account,
@ -718,7 +693,7 @@ function template_preprocess_comment(&$variables) {
if ($comment->hasParentComment()) { if ($comment->hasParentComment()) {
// Fetch and store the parent comment information for use in templates. // Fetch and store the parent comment information for use in templates.
$comment_parent = $comment->getParentComment(); $comment_parent = $comment->getParentComment();
$account_parent = comment_prepare_author($comment_parent); $account_parent = $comment_parent->getOwner();
$variables['parent_comment'] = $comment_parent; $variables['parent_comment'] = $comment_parent;
$username = array( $username = array(
'#theme' => 'username', '#theme' => 'username',

View File

@ -14,6 +14,7 @@ use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Entity\FieldStorageConfig;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface; use Drupal\user\UserInterface;
/** /**
@ -534,7 +535,13 @@ class Comment extends ContentEntityBase implements CommentInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getOwner() { public function getOwner() {
return $this->get('uid')->entity; $user = $this->get('uid')->entity;
if (!$user || $user->isAnonymous()) {
$user = User::getAnonymousUser();
$user->name = $this->getAuthorName();
$user->homepage = $this->getHomepage();
}
return $user;
} }
/** /**

View File

@ -185,7 +185,7 @@ class CommentAdminOverview extends FormBase {
$commented_entity = $commented_entities[$comment->getCommentedEntityTypeId()][$comment->getCommentedEntityId()]; $commented_entity = $commented_entities[$comment->getCommentedEntityTypeId()][$comment->getCommentedEntityId()];
$username = array( $username = array(
'#theme' => 'username', '#theme' => 'username',
'#account' => comment_prepare_author($comment), '#account' => $comment->getOwner(),
); );
$body = ''; $body = '';
if (!empty($comment->comment_body->value)) { if (!empty($comment->comment_body->value)) {

View File

@ -11,6 +11,7 @@ use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityViewBuilder; use Drupal\Core\Entity\EntityViewBuilder;
use Drupal\node\Entity\Node; use Drupal\node\Entity\Node;
use Drupal\user\Entity\User;
/** /**
* Render controller for nodes. * Render controller for nodes.
@ -26,9 +27,6 @@ class NodeViewBuilder extends EntityViewBuilder {
return; return;
} }
// Attach user account.
user_attach_accounts($build, $entities);
parent::buildComponents($build, $entities, $displays, $view_mode, $langcode); parent::buildComponents($build, $entities, $displays, $view_mode, $langcode);
foreach ($entities as $id => $entity) { foreach ($entities as $id => $entity) {

View File

@ -62,6 +62,13 @@ use Drupal\user\UserInterface;
*/ */
class User extends ContentEntityBase implements UserInterface { class User extends ContentEntityBase implements UserInterface {
/**
* Stores a reference for a reusable anonymous user entity.
*
* @var \Drupal\user\UserInterface
*/
protected static $anonymousUser;
/** /**
* The hostname for this user. * The hostname for this user.
* *
@ -424,6 +431,26 @@ class User extends ContentEntityBase implements UserInterface {
return !empty($this->get('pass')->existing) && \Drupal::service('password')->check(trim($this->get('pass')->existing), $account_unchanged); return !empty($this->get('pass')->existing) && \Drupal::service('password')->check(trim($this->get('pass')->existing), $account_unchanged);
} }
/**
* Returns an anonymous user entity.
*
* @return \Drupal\user\UserInterface
* An anonymous user entity.
*/
public static function getAnonymousUser() {
if (!isset(static::$anonymousUser)) {
// @todo Use the entity factory once available, see
// https://www.drupal.org/node/1867228.
$entity_manager = \Drupal::entityManager();
$entity_type = $entity_manager->getDefinition('user');
$class = $entity_type->getClass();
static::$anonymousUser = new $class(['uid' => [LanguageInterface::LANGCODE_DEFAULT => 0]], $entity_type->id());
}
return clone static::$anonymousUser;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -9,7 +9,7 @@ namespace Drupal\user\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
/** /**
* Plugin implementation of the 'author' formatter. * Plugin implementation of the 'author' formatter.
@ -23,7 +23,7 @@ use Drupal\Core\Field\FormatterBase;
* } * }
* ) * )
*/ */
class AuthorFormatter extends FormatterBase { class AuthorFormatter extends EntityReferenceFormatterBase {
/** /**
* {@inheritdoc} * {@inheritdoc}

View File

@ -116,36 +116,6 @@ function user_js_settings_alter(&$settings, AttachedAssetsInterface $assets) {
$settings['user']['permissionsHash'] = \Drupal::service('user_permissions_hash_generator')->generate($user); $settings['user']['permissionsHash'] = \Drupal::service('user_permissions_hash_generator')->generate($user);
} }
/**
* Populates $entity->account for each prepared entity.
*
* Called by Drupal\Core\Entity\EntityViewBuilderInterface::buildComponents()
* implementations.
*
* @param array &$build
* A renderable array representing the entity content.
* @param \Drupal\user\EntityOwnerInterface[] $entities
* The entities keyed by entity ID.
*/
function user_attach_accounts(array &$build, array $entities) {
$uids = array();
foreach ($entities as $entity) {
$uids[] = $entity->getOwnerId();
}
$uids = array_unique($uids);
$accounts = user_load_multiple($uids);
$anonymous = entity_create('user', array('uid' => 0));
foreach ($entities as $id => $entity) {
if (isset($accounts[$entity->getOwnerId()])) {
$entities[$id]->setOwner($accounts[$entity->getOwnerId()]);
}
else {
$entities[$id]->setOwner($anonymous);
}
}
}
/** /**
* Returns whether this site supports the default user picture feature. * Returns whether this site supports the default user picture feature.
* *