Commit db1122d6 authored by catch's avatar catch

Issue #1778178 by fago, Berdir, effulgentsia, mradcliffe, das-peter: Convert...

Issue #1778178 by fago, Berdir, effulgentsia, mradcliffe, das-peter: Convert comments to the new Entity Field API.
parent 77f03842
......@@ -2500,7 +2500,15 @@ function state() {
* @return Drupal\Core\TypedData\TypedDataManager
*/
function typed_data() {
return drupal_container()->get('typed_data');
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['manager'] = &drupal_static(__FUNCTION__);
}
if (!isset($drupal_static_fast['manager'])) {
$drupal_static_fast['manager'] = drupal_container()->get('typed_data');
}
return $drupal_static_fast['manager'];
}
/**
......
......@@ -109,41 +109,40 @@ function comment_admin_overview($form, &$form_state, $arg) {
foreach ($comments as $comment) {
// Remove the first node title from the node_titles array and attach to
// the comment.
$comment->node_title = array_shift($node_titles);
$comment_body = field_get_items($comment, 'comment_body');
$options[$comment->cid] = array(
$node_title = array_shift($node_titles);
$options[$comment->id()] = array(
'subject' => array(
'data' => array(
'#type' => 'link',
'#title' => $comment->subject,
'#href' => 'comment/' . $comment->cid,
'#options' => array('attributes' => array('title' => truncate_utf8($comment_body[0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
'#title' => $comment->subject->value,
'#href' => 'comment/' . $comment->id(),
'#options' => array('attributes' => array('title' => truncate_utf8($comment->comment_body->value, 128)), 'fragment' => 'comment-' . $comment->id()),
),
),
'author' => theme('username', array('account' => $comment)),
'author' => theme('username', array('account' => comment_prepare_author($comment))),
'posted_in' => array(
'data' => array(
'#type' => 'link',
'#title' => $comment->node_title,
'#href' => 'node/' . $comment->nid,
'#title' => $node_title,
'#href' => 'node/' . $comment->nid->value,
),
),
'changed' => format_date($comment->changed, 'short'),
'changed' => format_date($comment->changed->value, 'short'),
);
$links = array();
$links['edit'] = array(
'title' => t('edit'),
'href' => 'comment/' . $comment->cid . '/edit',
'href' => 'comment/' . $comment->id() . '/edit',
'query' => $destination,
);
if (module_invoke('translation_entity', 'translate_access', $comment)) {
$links['translate'] = array(
'title' => t('translate'),
'href' => 'comment/' . $comment->cid . '/translations',
'href' => 'comment/' . $comment->id() . '/translations',
'query' => $destination,
);
}
$options[$comment->cid]['operations']['data'] = array(
$options[$comment->id()]['operations']['data'] = array(
'#type' => 'operations',
'#links' => $links,
);
......@@ -194,10 +193,10 @@ function comment_admin_overview_submit($form, &$form_state) {
$comment = comment_load($value);
if ($operation == 'unpublish') {
$comment->status = COMMENT_NOT_PUBLISHED;
$comment->status->value = COMMENT_NOT_PUBLISHED;
}
elseif ($operation == 'publish') {
$comment->status = COMMENT_PUBLISHED;
$comment->status->value = COMMENT_PUBLISHED;
}
comment_save($comment);
}
......@@ -226,7 +225,7 @@ function comment_multiple_delete_confirm($form, &$form_state) {
$comment_counter = 0;
foreach (array_filter($edit['comments']) as $cid => $value) {
$comment = comment_load($cid);
if (is_object($comment) && is_numeric($comment->cid)) {
if (is_object($comment) && is_numeric($comment->id())) {
$subject = db_query('SELECT subject FROM {comment} WHERE cid = :cid', array(':cid' => $cid))->fetchField();
$form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '<li>', '#suffix' => check_plain($subject) . '</li>');
$comment_counter++;
......@@ -290,11 +289,11 @@ function comment_confirm_delete_page($cid) {
function comment_confirm_delete($form, &$form_state, Comment $comment) {
$form_state['comment'] = $comment;
// Always provide entity id in the same form key as in the entity edit form.
$form['cid'] = array('#type' => 'value', '#value' => $comment->cid);
$form['cid'] = array('#type' => 'value', '#value' => $comment->id());
return confirm_form(
$form,
t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject)),
'node/' . $comment->nid,
t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject->value)),
'node/' . $comment->nid->value,
t('Any replies to this comment will be lost. This action cannot be undone.'),
t('Delete'),
t('Cancel'),
......@@ -307,11 +306,11 @@ function comment_confirm_delete($form, &$form_state, Comment $comment) {
function comment_confirm_delete_submit($form, &$form_state) {
$comment = $form_state['comment'];
// Delete the comment and its replies.
comment_delete($comment->cid);
$comment->delete();
drupal_set_message(t('The comment and all its replies have been deleted.'));
watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->cid));
watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->id()));
// Clear the cache so an anonymous user sees that his comment was deleted.
cache_invalidate_tags(array('content' => TRUE));
$form_state['redirect'] = "node/$comment->nid";
$form_state['redirect'] = "node/{$comment->nid->value}";
}
......@@ -23,7 +23,7 @@
*/
function hook_comment_presave(Drupal\comment\Comment $comment) {
// Remove leading & trailing spaces from the comment subject.
$comment->subject = trim($comment->subject);
$comment->subject->value = trim($comment->subject->value);
}
/**
......@@ -34,7 +34,7 @@ function hook_comment_presave(Drupal\comment\Comment $comment) {
*/
function hook_comment_insert(Drupal\comment\Comment $comment) {
// Reindex the node when comments are added.
search_touch_node($comment->nid);
search_touch_node($comment->nid->value);
}
/**
......@@ -45,7 +45,7 @@ function hook_comment_insert(Drupal\comment\Comment $comment) {
*/
function hook_comment_update(Drupal\comment\Comment $comment) {
// Reindex the node when comments are updated.
search_touch_node($comment->nid);
search_touch_node($comment->nid->value);
}
/**
......@@ -130,7 +130,7 @@ function hook_comment_view_alter(&$build, \Drupal\comment\Plugin\Core\Entity\Com
* The comment the action is being performed on.
*/
function hook_comment_publish(Drupal\comment\Comment $comment) {
drupal_set_message(t('Comment: @subject has been published', array('@subject' => $comment->subject)));
drupal_set_message(t('Comment: @subject has been published', array('@subject' => $comment->subject->value)));
}
/**
......@@ -140,7 +140,7 @@ function hook_comment_publish(Drupal\comment\Comment $comment) {
* The comment the action is being performed on.
*/
function hook_comment_unpublish(Drupal\comment\Comment $comment) {
drupal_set_message(t('Comment: @subject has been unpublished', array('@subject' => $comment->subject)));
drupal_set_message(t('Comment: @subject has been unpublished', array('@subject' => $comment->subject->value)));
}
/**
......@@ -160,7 +160,7 @@ function hook_comment_unpublish(Drupal\comment\Comment $comment) {
function hook_comment_predelete(Drupal\comment\Comment $comment) {
// Delete a record associated with the comment in a custom table.
db_delete('example_comment_table')
->condition('cid', $comment->cid)
->condition('cid', $comment->id())
->execute();
}
......@@ -179,7 +179,7 @@ function hook_comment_predelete(Drupal\comment\Comment $comment) {
* @see entity_delete_multiple()
*/
function hook_comment_delete(Drupal\comment\Comment $comment) {
drupal_set_message(t('Comment: @subject has been deleted', array('@subject' => $comment->subject)));
drupal_set_message(t('Comment: @subject has been deleted', array('@subject' => $comment->subject->value)));
}
/**
......
This diff is collapsed.
......@@ -56,18 +56,15 @@ function comment_reply(Node $node, $pid = NULL) {
if (user_access('access comments')) {
// Load the parent comment.
$comment = comment_load($pid);
if ($comment->status == COMMENT_PUBLISHED) {
if ($comment->status->value == COMMENT_PUBLISHED) {
// If that comment exists, make sure that the current comment and the
// parent comment both belong to the same parent node.
if ($comment->nid != $node->nid) {
if ($comment->nid->value != $node->nid) {
// Attempting to reply to a comment not belonging to the current nid.
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
drupal_goto("node/$node->nid");
}
// Display the parent comment
$comment->node_type = 'comment_node_' . $node->type;
field_attach_load('comment', array($comment->cid => $comment));
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
$build['comment_parent'] = comment_view($comment);
}
else {
......@@ -120,11 +117,11 @@ function comment_approve($cid) {
}
if ($comment = comment_load($cid)) {
$comment->status = COMMENT_PUBLISHED;
$comment->status->value = COMMENT_PUBLISHED;
comment_save($comment);
drupal_set_message(t('Comment approved.'));
drupal_goto('node/' . $comment->nid);
drupal_goto('node/' . $comment->nid->value);
}
throw new NotFoundHttpException();
}
......@@ -122,79 +122,75 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
switch ($name) {
// Simple key values on the comment.
case 'cid':
$replacements[$original] = $comment->cid;
$replacements[$original] = $comment->id();
break;
// Poster identity information for comments
case 'hostname':
$replacements[$original] = $sanitize ? check_plain($comment->hostname) : $comment->hostname;
$replacements[$original] = $sanitize ? check_plain($comment->hostname->value) : $comment->hostname->value;
break;
case 'name':
$name = ($comment->uid == 0) ? config('user.settings')->get('anonymous') : $comment->name;
$name = ($comment->uid->value == 0) ? config('user.settings')->get('anonymous') : $comment->name->value;
$replacements[$original] = $sanitize ? filter_xss($name) : $name;
break;
case 'mail':
if ($comment->uid != 0) {
$account = user_load($comment->uid);
if ($comment->uid->value != 0) {
$account = user_load($comment->uid->value);
$mail = $account->mail;
}
else {
$mail = $comment->mail;
$mail = $comment->mail->value;
}
$replacements[$original] = $sanitize ? check_plain($mail) : $mail;
break;
case 'homepage':
$replacements[$original] = $sanitize ? check_url($comment->homepage) : $comment->homepage;
$replacements[$original] = $sanitize ? check_url($comment->homepage->value) : $comment->homepage->value;
break;
case 'title':
$replacements[$original] = $sanitize ? filter_xss($comment->subject) : $comment->subject;
$replacements[$original] = $sanitize ? filter_xss($comment->subject->value) : $comment->subject->value;
break;
case 'body':
if ($items = field_get_items($comment, 'comment_body', $langcode)) {
$instance = field_info_instance('comment', 'body', 'comment_body');
$field_langcode = field_language($comment, 'comment_body', $langcode);
$replacements[$original] = $sanitize ? _text_sanitize($instance, $field_langcode, $items[0], 'value') : $items[0]['value'];
}
$replacements[$original] = $sanitize ? $comment->comment_body->processed : $comment->comment_body->value;
break;
// Comment related URLs.
case 'url':
$url_options['fragment'] = 'comment-' . $comment->cid;
$replacements[$original] = url('comment/' . $comment->cid, $url_options);
$url_options['fragment'] = 'comment-' . $comment->id();
$replacements[$original] = url('comment/' . $comment->id(), $url_options);
break;
case 'edit-url':
$url_options['fragment'] = NULL;
$replacements[$original] = url('comment/' . $comment->cid . '/edit', $url_options);
$replacements[$original] = url('comment/' . $comment->id() . '/edit', $url_options);
break;
// Default values for the chained tokens handled below.
case 'author':
$replacements[$original] = $sanitize ? filter_xss($comment->name) : $comment->name;
$replacements[$original] = $sanitize ? filter_xss($comment->name->value) : $comment->name->value;
break;
case 'parent':
if (!empty($comment->pid)) {
$parent = comment_load($comment->pid);
if (!empty($comment->pid->value)) {
$parent = comment_load($comment->pid->value);
$replacements[$original] = $sanitize ? filter_xss($parent->subject) : $parent->subject;
}
break;
case 'created':
$replacements[$original] = format_date($comment->created, 'medium', '', NULL, $langcode);
$replacements[$original] = format_date($comment->created->value, 'medium', '', NULL, $langcode);
break;
case 'changed':
$replacements[$original] = format_date($comment->changed, 'medium', '', NULL, $langcode);
$replacements[$original] = format_date($comment->changed->value, 'medium', '', NULL, $langcode);
break;
case 'node':
$node = node_load($comment->nid);
$node = $comment->nid->entity;
$title = $node->label();
$replacements[$original] = $sanitize ? filter_xss($title) : $title;
break;
......@@ -203,23 +199,23 @@ function comment_tokens($type, $tokens, array $data = array(), array $options =
// Chained token relationships.
if ($node_tokens = token_find_with_prefix($tokens, 'node')) {
$node = node_load($comment->nid);
$node = $comment->nid->entity;
$replacements += token_generate('node', $node_tokens, array('node' => $node), $options);
}
if ($date_tokens = token_find_with_prefix($tokens, 'created')) {
$replacements += token_generate('date', $date_tokens, array('date' => $comment->created), $options);
$replacements += token_generate('date', $date_tokens, array('date' => $comment->created->value), $options);
}
if ($date_tokens = token_find_with_prefix($tokens, 'changed')) {
$replacements += token_generate('date', $date_tokens, array('date' => $comment->changed), $options);
$replacements += token_generate('date', $date_tokens, array('date' => $comment->changed->value), $options);
}
if (($parent_tokens = token_find_with_prefix($tokens, 'parent')) && $parent = comment_load($comment->pid)) {
if (($parent_tokens = token_find_with_prefix($tokens, 'parent')) && $parent = $comment->pid->entity) {
$replacements += token_generate('comment', $parent_tokens, array('comment' => $parent), $options);
}
if (($author_tokens = token_find_with_prefix($tokens, 'author')) && $account = user_load($comment->uid)) {
if (($author_tokens = token_find_with_prefix($tokens, 'author')) && $account = $comment->uid->entity) {
$replacements += token_generate('user', $author_tokens, array('user' => $account), $options);
}
}
......
......@@ -28,21 +28,25 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
return $return;
}
// Attach user account.
user_attach_accounts($entities);
// Pre-load associated users into cache to leverage multiple loading.
$uids = array();
foreach ($entities as $entity) {
$uids[] = $entity->uid->value;
}
user_load_multiple(array_unique($uids));
parent::buildContent($entities, $displays, $view_mode, $langcode);
// Load all nodes of all comments at once.
$nids = array();
foreach ($entities as $entity) {
$nids[$entity->nid] = $entity->nid;
$nids[$entity->nid->value] = $entity->nid->value;
}
$nodes = node_load_multiple($nids);
foreach ($entities as $entity) {
if (isset($nodes[$entity->nid])) {
$node = $nodes[$entity->nid];
if (isset($nodes[$entity->nid->value])) {
$node = $nodes[$entity->nid->value];
}
else {
throw new \InvalidArgumentException(t('Invalid node for comment.'));
......@@ -87,7 +91,7 @@ protected function alterBuild(array &$build, EntityInterface $comment, EntityDis
}
// Add anchor for each comment.
$prefix .= "<a id=\"comment-$comment->cid\"></a>\n";
$prefix .= "<a id=\"comment-{$comment->id()}\"></a>\n";
$build['#prefix'] = $prefix;
// Close all open divs.
......
<?php
/**
* @file
* Contains \Drupal\comment\FieldNewItem.
*/
namespace Drupal\comment;
use Drupal\Core\Entity\Field\Type\IntegerItem;
/**
* The field item for the 'new' field.
*/
class FieldNewItem extends IntegerItem {
/**
* Definitions of the contained properties.
*
* @see self::getPropertyDefinitions()
*
* @var array
*/
static $propertyDefinitions;
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
*/
public function getPropertyDefinitions() {
if (!isset(static::$propertyDefinitions)) {
static::$propertyDefinitions['value'] = array(
'type' => 'integer',
'label' => t('Integer value'),
'class' => '\Drupal\comment\FieldNewValue',
);
}
return static::$propertyDefinitions;
}
}
<?php
/**
* @file
* Contains \Drupal\comment\FieldNewValue.
*/
namespace Drupal\comment;
use Drupal\Core\TypedData\ContextAwareTypedData;
use Drupal\Core\TypedData\ReadOnlyException;
use InvalidArgumentException;
/**
* A computed property for the integer value of the 'new' field.
*
* @todo: Declare the list of allowed values once supported.
*/
class FieldNewValue extends ContextAwareTypedData {
/**
* Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
*/
public function getValue($langcode = NULL) {
if (!isset($this->value)) {
if (!isset($this->parent)) {
throw new InvalidArgumentException('Computed properties require context for computation.');
}
$field = $this->parent->getParent();
$entity = $field->getParent();
$this->value = node_mark($entity->nid->value, $entity->changed->value);
}
return $this->value;
}
/**
* Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
*/
public function setValue($value) {
if (isset($value)) {
throw new ReadOnlyException('Unable to set a computed property.');
}
}
}
......@@ -8,7 +8,7 @@
namespace Drupal\comment\Plugin\Core\Entity;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\EntityNG;
use Drupal\Core\Annotation\Plugin;
use Drupal\Core\Annotation\Translation;
......@@ -25,7 +25,7 @@
* form_controller_class = {
* "default" = "Drupal\comment\CommentFormController"
* },
* translation_controller_class = "Drupal\comment\CommentTranslationController",
* translation_controller_class = "Drupal\translation_entity\EntityTranslationControllerNG",
* base_table = "comment",
* uri_callback = "comment_uri",
* fieldable = TRUE,
......@@ -44,45 +44,51 @@
* }
* )
*/
class Comment extends Entity implements ContentEntityInterface {
class Comment extends EntityNG implements ContentEntityInterface {
/**
* The comment ID.
*
* @var integer
* @todo Rename to 'id'.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $cid;
/**
* The comment UUID.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $uuid;
/**
* The parent comment ID if this is a reply to a comment.
*
* @var integer
* @todo: Rename to 'parent_id'.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $pid;
/**
* The ID of the node to which the comment is attached.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $nid;
/**
* The comment language code.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $langcode = LANGUAGE_NOT_SPECIFIED;
public $langcode;
/**
* The comment title.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $subject;
......@@ -90,25 +96,25 @@ class Comment extends Entity implements ContentEntityInterface {
/**
* The comment author ID.
*
* @var integer
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $uid = 0;
public $uid;
/**
* The comment author's name.
*
* For anonymous authors, this is the value as typed in the comment form.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $name = '';
public $name;
/**
* The comment author's e-mail address.
*
* For anonymous authors, this is the value as typed in the comment form.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $mail;
......@@ -117,21 +123,100 @@ class Comment extends Entity implements ContentEntityInterface {
*
* For anonymous authors, this is the value as typed in the comment form.
*
* @var string
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $homepage;
/**
* Implements Drupal\Core\Entity\EntityInterface::id().
* The comment author's hostname.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public function id() {
return $this->cid;
public $hostname;
/**
* The time that the comment was created.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $created;
/**
* The time that the comment was last edited.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $changed;
/**
* A boolean field indicating whether the comment is published.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $status;
/**
* The alphadecimal representation of the comment's place in a thread.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $thread;
/**
* The comment node type.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $node_type;
/**
* The comment 'new' marker for the current user.
*
* @var \Drupal\Core\Entity\Field\FieldInterface
*/
public $new;
/**
* The plain data values of the contained properties.
*
* Define default values.
*
* @var array
*/
protected $values = array(
'langcode' => array(LANGUAGE_DEFAULT => array(0 => array('value' => LANGUAGE_NOT_SPECIFIED))),
'name' => array(LANGUAGE_DEFAULT => array(0 => array('value' => ''))),
'uid' => array(LANGUAGE_DEFAULT => array(0 => array('value' => 0))),
);
/**
* Initialize the object. Invoked upon construction and wake up.
*/
protected function init() {
parent::init();
// We unset all defined properties, so magic getters apply.
unset($this->cid);
unset($this->uuid);
unset($this->pid);
unset($this->nid);
unset($this->subject);
unset($this->uid);
unset($this->name);
unset($this->mail);
unset($this->homepage);
unset($this->hostname);
unset($this->created);
unset($this->changed);
unset($this->status);
unset($this->thread);
unset($this->node_type);
unset($this->new);
}
/**
* Implements Drupal\Core\Entity\EntityInterface::bundle().
* Implements Drupal\Core\Entity\EntityInterface::id().