Newer
Older
<?php
namespace Drupal\node\Entity;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityPublishedTrait;
catch
committed
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
Alex Pott
committed
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Drupal\user\UserInterface;
/**
* Defines the node entity class.
Angie Byron
committed
*
Alex Pott
committed
* @ContentEntityType(
Angie Byron
committed
* id = "node",
Angie Byron
committed
* label = @Translation("Content"),
* label_singular = @Translation("content item"),
* label_plural = @Translation("content items"),
* label_count = @PluralTranslation(
* singular = "@count content item",
* plural = "@count content items"
* ),
Angie Byron
committed
* bundle_label = @Translation("Content type"),
Alex Pott
committed
* handlers = {
* "storage" = "Drupal\node\NodeStorage",
* "storage_schema" = "Drupal\node\NodeStorageSchema",
Alex Pott
committed
* "view_builder" = "Drupal\node\NodeViewBuilder",
* "access" = "Drupal\node\NodeAccessControlHandler",
* "views_data" = "Drupal\node\NodeViewsData",
Alex Pott
committed
* "default" = "Drupal\node\NodeForm",
* "delete" = "Drupal\node\Form\NodeDeleteForm",
Alex Pott
committed
* "edit" = "Drupal\node\NodeForm"
* "route_provider" = {
* "html" = "Drupal\node\Entity\NodeRouteProvider",
* },
* "list_builder" = "Drupal\node\NodeListBuilder",
* "translation" = "Drupal\node\NodeTranslationHandler"
Angie Byron
committed
* },
* base_table = "node",
* data_table = "node_field_data",
* revision_table = "node_revision",
* revision_data_table = "node_field_revision",
* show_revision_ui = TRUE,
Angie Byron
committed
* translatable = TRUE,
* list_cache_contexts = { "user.node_grants:view" },
Angie Byron
committed
* entity_keys = {
* "id" = "nid",
* "revision" = "vid",
* "bundle" = "type",
* "label" = "title",
* "langcode" = "langcode",
catch
committed
* "uuid" = "uuid",
* "status" = "status",
* "published" = "status",
catch
committed
* "uid" = "uid",
Angie Byron
committed
* },
catch
committed
* bundle_entity_type = "node_type",
Alex Pott
committed
* field_ui_base_route = "entity.node_type.edit_form",
Angie Byron
committed
* common_reference_target = TRUE,
Alex Pott
committed
* permission_granularity = "bundle",
* links = {
* "canonical" = "/node/{node}",
* "delete-form" = "/node/{node}/delete",
* "edit-form" = "/node/{node}/edit",
* "version-history" = "/node/{node}/revisions",
* "revision" = "/node/{node}/revisions/{node_revision}/view",
Alex Pott
committed
* }
Angie Byron
committed
* )
class Node extends ContentEntityBase implements NodeInterface {
use EntityChangedTrait;
use EntityPublishedTrait;
catch
committed
/**
* Whether the node is being previewed or not.
*
* The variable is set to public as it will give a considerable performance
* improvement. See https://www.drupal.org/node/2498919.
*
catch
committed
* @var true|null
* TRUE if the node is being previewed and NULL if it is not.
catch
committed
*/
public $in_preview = NULL;
/**
* {@inheritdoc}
*/
public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
Alex Pott
committed
foreach (array_keys($this->getTranslationLanguages()) as $langcode) {
$translation = $this->getTranslation($langcode);
// If no owner has been set explicitly, make the anonymous user the owner.
if (!$translation->getOwner()) {
$translation->setOwnerId(0);
}
}
Alex Pott
committed
// If no revision author has been set explicitly, make the node owner the
// revision author.
if (!$this->getRevisionUser()) {
$this->setRevisionUserId($this->getOwnerId());
}
}
Alex Pott
committed
* {@inheritdoc}
catch
committed
public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
parent::preSaveRevision($storage, $record);
Angie Byron
committed
if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) {
Alex Pott
committed
// If we are updating an existing node without adding a new revision, we
// need to make sure $entity->revision_log is reset whenever it is empty.
Alex Pott
committed
// Therefore, this code allows us to avoid clobbering an existing log
// entry with an empty one.
$record->revision_log = $this->original->revision_log->value;
Alex Pott
committed
}
}
/**
Alex Pott
committed
* {@inheritdoc}
catch
committed
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
Angie Byron
committed
Alex Pott
committed
// Update the node access table for this node, but only if it is the
// default revision. There's no need to delete existing records if the node
// is new.
if ($this->isDefaultRevision()) {
/** @var \Drupal\node\NodeAccessControlHandlerInterface $access_control_handler */
$access_control_handler = \Drupal::entityManager()->getAccessControlHandler('node');
$grants = $access_control_handler->acquireGrants($this);
\Drupal::service('node.grant_storage')->write($this, $grants, NULL, $update);
Alex Pott
committed
}
// Reindex the node when it is updated. The node is automatically indexed
// when it is added, simply by being added to the node table.
if ($update) {
node_reindex_node_search($this->id());
}
Alex Pott
committed
}
/**
Alex Pott
committed
* {@inheritdoc}
catch
committed
public static function preDelete(EntityStorageInterface $storage, array $entities) {
parent::preDelete($storage, $entities);
Angie Byron
committed
Alex Pott
committed
// Ensure that all nodes deleted are removed from the search index.
if (\Drupal::moduleHandler()->moduleExists('search')) {
foreach ($entities as $entity) {
Alex Pott
committed
search_index_clear('node_search', $entity->nid->value);
Alex Pott
committed
}
}
}
Alex Pott
committed
/**
* {@inheritdoc}
*/
catch
committed
public static function postDelete(EntityStorageInterface $storage, array $nodes) {
parent::postDelete($storage, $nodes);
Alex Pott
committed
\Drupal::service('node.grant_storage')->deleteNodeRecords(array_keys($nodes));
}
/**
* {@inheritdoc}
*/
public function getType() {
return $this->bundle();
}
/**
* {@inheritdoc}
*/
catch
committed
public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
// This override exists to set the operation to the default value "view".
return parent::access($operation, $account, $return_as_object);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return $this->get('title')->value;
}
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function setTitle($title) {
$this->set('title', $title);
return $this;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function getCreatedTime() {
return $this->get('created')->value;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function setCreatedTime($timestamp) {
$this->set('created', $timestamp);
return $this;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function isPromoted() {
return (bool) $this->get('promote')->value;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function setPromoted($promoted) {
$this->set('promote', $promoted ? NODE_PROMOTED : NODE_NOT_PROMOTED);
Alex Pott
committed
return $this;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function isSticky() {
return (bool) $this->get('sticky')->value;
}
/**
Alex Pott
committed
* {@inheritdoc}
Alex Pott
committed
public function setSticky($sticky) {
$this->set('sticky', $sticky ? NODE_STICKY : NODE_NOT_STICKY);
return $this;
}
/**
Alex Pott
committed
* {@inheritdoc}
public function getOwner() {
return $this->get('uid')->entity;
Dries Buytaert
committed
/**
Alex Pott
committed
* {@inheritdoc}
Dries Buytaert
committed
*/
public function getOwnerId() {
catch
committed
return $this->getEntityKey('uid');
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* {@inheritdoc}
*/
public function setOwnerId($uid) {
Alex Pott
committed
$this->set('uid', $uid);
return $this;
}
/**
* {@inheritdoc}
*/
public function setOwner(UserInterface $account) {
$this->set('uid', $account->id());
return $this;
}
/**
* {@inheritdoc}
*/
Alex Pott
committed
public function getRevisionCreationTime() {
return $this->get('revision_timestamp')->value;
}
/**
* {@inheritdoc}
*/
Alex Pott
committed
public function setRevisionCreationTime($timestamp) {
$this->set('revision_timestamp', $timestamp);
return $this;
}
/**
* {@inheritdoc}
*/
Alex Pott
committed
public function getRevisionAuthor() {
return $this->getRevisionUser();
}
/**
* {@inheritdoc}
*/
public function getRevisionUser() {
Alex Pott
committed
return $this->get('revision_uid')->entity;
}
/**
* {@inheritdoc}
*/
Alex Pott
committed
public function setRevisionAuthorId($uid) {
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
$this->setRevisionUserId($uid);
return $this;
}
/**
* {@inheritdoc}
*/
public function setRevisionUser(UserInterface $user) {
$this->set('revision_uid', $user);
return $this;
}
/**
* {@inheritdoc}
*/
public function getRevisionUserId() {
return $this->get('revision_uid')->entity->id();
}
/**
* {@inheritdoc}
*/
public function setRevisionUserId($user_id) {
$this->set('revision_uid', $user_id);
return $this;
}
/**
* {@inheritdoc}
*/
public function getRevisionLogMessage() {
return $this->get('revision_log')->value;
}
/**
* {@inheritdoc}
*/
public function setRevisionLogMessage($revision_log_message) {
$this->set('revision_log', $revision_log_message);
Alex Pott
committed
return $this;
}
Alex Pott
committed
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields += static::publishedBaseFieldDefinitions($entity_type);
Alex Pott
committed
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
->setRequired(TRUE)
->setTranslatable(TRUE)
->setRevisionable(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', array(
'label' => 'hidden',
Alex Pott
committed
'type' => 'string',
'weight' => -5,
))
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => -5,
))
->setDisplayConfigurable('form', TRUE);
Alex Pott
committed
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Authored by'))
Alex Pott
committed
->setDescription(t('The username of the content author.'))
->setRevisionable(TRUE)
->setSetting('target_type', 'user')
->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId')
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
'label' => 'hidden',
'type' => 'author',
'weight' => 0,
))
->setDisplayOptions('form', array(
'type' => 'entity_reference_autocomplete',
'weight' => 5,
'settings' => array(
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
),
))
->setDisplayConfigurable('form', TRUE);
Alex Pott
committed
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Authored on'))
->setDescription(t('The time that the node was created.'))
->setRevisionable(TRUE)
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
'label' => 'hidden',
'type' => 'timestamp',
'weight' => 0,
))
->setDisplayOptions('form', array(
'type' => 'datetime_timestamp',
'weight' => 10,
))
->setDisplayConfigurable('form', TRUE);
Alex Pott
committed
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the node was last edited.'))
->setRevisionable(TRUE)
->setTranslatable(TRUE);
Alex Pott
committed
$fields['promote'] = BaseFieldDefinition::create('boolean')
Alex Pott
committed
->setLabel(t('Promoted to front page'))
->setRevisionable(TRUE)
->setTranslatable(TRUE)
->setDefaultValue(TRUE)
->setDisplayOptions('form', array(
'type' => 'boolean_checkbox',
'settings' => array(
'display_label' => TRUE,
),
'weight' => 15,
))
->setDisplayConfigurable('form', TRUE);
Alex Pott
committed
$fields['sticky'] = BaseFieldDefinition::create('boolean')
Alex Pott
committed
->setLabel(t('Sticky at top of lists'))
->setRevisionable(TRUE)
->setTranslatable(TRUE)
->setDefaultValue(FALSE)
->setDisplayOptions('form', array(
'type' => 'boolean_checkbox',
'settings' => array(
'display_label' => TRUE,
),
'weight' => 16,
))
->setDisplayConfigurable('form', TRUE);
Alex Pott
committed
$fields['revision_timestamp'] = BaseFieldDefinition::create('created')
->setLabel(t('Revision timestamp'))
->setDescription(t('The time that the current revision was created.'))
->setQueryable(FALSE)
->setRevisionable(TRUE);
Alex Pott
committed
$fields['revision_uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Revision user ID'))
->setDescription(t('The user ID of the author of the current revision.'))
->setSetting('target_type', 'user')
->setQueryable(FALSE)
->setRevisionable(TRUE);
Alex Pott
committed
$fields['revision_log'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Revision log message'))
->setDescription(t('Briefly describe the changes you have made.'))
->setRevisionable(TRUE)
catch
committed
->setDefaultValue('')
->setDisplayOptions('form', array(
'type' => 'string_textarea',
'weight' => 25,
'settings' => array(
'rows' => 4,
),
));
catch
committed
$fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Revision translation affected'))
->setDescription(t('Indicates if the last edit of a translation belongs to current revision.'))
->setReadOnly(TRUE)
->setRevisionable(TRUE)
->setTranslatable(TRUE);
return $fields;
Alex Pott
committed
}
/**
* Default value callback for 'uid' base field definition.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getCurrentUserId() {
return array(\Drupal::currentUser()->id());
}