3 namespace Drupal\content_moderation\Entity;
5 use Drupal\Core\Entity\ContentEntityBase;
6 use Drupal\Core\Entity\EntityInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Field\BaseFieldDefinition;
9 use Drupal\Core\TypedData\TranslatableInterface;
10 use Drupal\user\UserInterface;
13 * Defines the Content moderation state entity.
16 * id = "content_moderation_state",
17 * label = @Translation("Content moderation state"),
18 * label_singular = @Translation("content moderation state"),
19 * label_plural = @Translation("content moderation states"),
20 * label_count = @PluralTranslation(
21 * singular = "@count content moderation state",
22 * plural = "@count content moderation states"
25 * "storage_schema" = "Drupal\content_moderation\ContentModerationStateStorageSchema",
26 * "views_data" = "\Drupal\views\EntityViewsData",
27 * "access" = "Drupal\content_moderation\ContentModerationStateAccessControlHandler",
29 * base_table = "content_moderation_state",
30 * revision_table = "content_moderation_state_revision",
31 * data_table = "content_moderation_state_field_data",
32 * revision_data_table = "content_moderation_state_field_revision",
33 * translatable = TRUE,
37 * "revision" = "revision_id",
40 * "langcode" = "langcode",
45 * This entity is marked internal because it should not be used directly to
46 * alter the moderation state of an entity. Instead, the computed
47 * moderation_state field should be set on the entity directly.
49 class ContentModerationState extends ContentEntityBase implements ContentModerationStateInterface {
54 public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
55 $fields = parent::baseFieldDefinitions($entity_type);
57 $fields['uid'] = BaseFieldDefinition::create('entity_reference')
59 ->setDescription(t('The username of the entity creator.'))
60 ->setSetting('target_type', 'user')
61 ->setDefaultValueCallback('Drupal\content_moderation\Entity\ContentModerationState::getCurrentUserId')
62 ->setTranslatable(TRUE)
63 ->setRevisionable(TRUE);
65 $fields['workflow'] = BaseFieldDefinition::create('entity_reference')
66 ->setLabel(t('Workflow'))
67 ->setDescription(t('The workflow the moderation state is in.'))
68 ->setSetting('target_type', 'workflow')
70 ->setRevisionable(TRUE);
72 $fields['moderation_state'] = BaseFieldDefinition::create('string')
73 ->setLabel(t('Moderation state'))
74 ->setDescription(t('The moderation state of the referenced content.'))
76 ->setTranslatable(TRUE)
77 ->setRevisionable(TRUE);
79 $fields['content_entity_type_id'] = BaseFieldDefinition::create('string')
80 ->setLabel(t('Content entity type ID'))
81 ->setDescription(t('The ID of the content entity type this moderation state is for.'))
83 ->setSetting('max_length', EntityTypeInterface::ID_MAX_LENGTH)
84 ->setRevisionable(TRUE);
86 $fields['content_entity_id'] = BaseFieldDefinition::create('integer')
87 ->setLabel(t('Content entity ID'))
88 ->setDescription(t('The ID of the content entity this moderation state is for.'))
90 ->setRevisionable(TRUE);
92 $fields['content_entity_revision_id'] = BaseFieldDefinition::create('integer')
93 ->setLabel(t('Content entity revision ID'))
94 ->setDescription(t('The revision ID of the content entity this moderation state is for.'))
96 ->setRevisionable(TRUE);
104 public function getOwner() {
105 return $this->get('uid')->entity;
111 public function getOwnerId() {
112 return $this->getEntityKey('uid');
118 public function setOwnerId($uid) {
119 $this->set('uid', $uid);
126 public function setOwner(UserInterface $account) {
127 $this->set('uid', $account->id());
132 * Creates or updates an entity's moderation state whilst saving that entity.
134 * @param \Drupal\content_moderation\Entity\ContentModerationState $content_moderation_state
135 * The content moderation entity content entity to create or save.
138 * This method should only be called as a result of saving the related
141 public static function updateOrCreateFromEntity(ContentModerationState $content_moderation_state) {
142 $content_moderation_state->realSave();
146 * Loads a content moderation state entity.
148 * @param \Drupal\Core\Entity\EntityInterface $entity
149 * A moderated entity object.
151 * @return \Drupal\content_moderation\Entity\ContentModerationStateInterface|null
152 * The related content moderation state or NULL if none could be found.
155 * This method should only be called by code directly handling the
156 * ContentModerationState entity objects.
158 public static function loadFromModeratedEntity(EntityInterface $entity) {
159 $content_moderation_state = NULL;
160 $moderation_info = \Drupal::service('content_moderation.moderation_information');
162 if ($moderation_info->isModeratedEntity($entity)) {
163 /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
164 $storage = \Drupal::entityTypeManager()->getStorage('content_moderation_state');
166 $ids = $storage->getQuery()
167 ->condition('content_entity_type_id', $entity->getEntityTypeId())
168 ->condition('content_entity_id', $entity->id())
169 ->condition('workflow', $moderation_info->getWorkflowForEntity($entity)->id())
170 ->condition('content_entity_revision_id', $entity->getLoadedRevisionId())
175 /** @var \Drupal\content_moderation\Entity\ContentModerationStateInterface $content_moderation_state */
176 $content_moderation_state = $storage->loadRevision(key($ids));
180 return $content_moderation_state;
184 * Default value callback for the 'uid' base field definition.
186 * @see \Drupal\content_moderation\Entity\ContentModerationState::baseFieldDefinitions()
189 * An array of default values.
191 public static function getCurrentUserId() {
192 return [\Drupal::currentUser()->id()];
198 public function save() {
199 $related_entity = \Drupal::entityTypeManager()
200 ->getStorage($this->content_entity_type_id->value)
201 ->loadRevision($this->content_entity_revision_id->value);
202 if ($related_entity instanceof TranslatableInterface) {
203 $related_entity = $related_entity->getTranslation($this->activeLangcode);
205 $related_entity->moderation_state = $this->moderation_state;
206 return $related_entity->save();
210 * Saves an entity permanently.
212 * When saving existing entities, the entity is assumed to be complete,
213 * partial updates of entities are not supported.
216 * Either SAVED_NEW or SAVED_UPDATED, depending on the operation performed.
218 * @throws \Drupal\Core\Entity\EntityStorageException
219 * In case of failures an exception is thrown.
221 protected function realSave() {
222 return parent::save();
228 protected function getFieldsToSkipFromTranslationChangesCheck() {
229 $field_names = parent::getFieldsToSkipFromTranslationChangesCheck();
230 // We need to skip the parent entity revision ID, since that will always
231 // change on every save, otherwise every translation would be marked as
232 // affected regardless of actual changes.
233 $field_names[] = 'content_entity_revision_id';