827c459f724e8a3a5bf6c9af603ef2e608efff0a
[yaffs-website] / web / core / modules / node / src / Entity / Node.php
1 <?php
2
3 namespace Drupal\node\Entity;
4
5 use Drupal\Core\Entity\EditorialContentEntityBase;
6 use Drupal\Core\Entity\EntityStorageInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Field\BaseFieldDefinition;
9 use Drupal\Core\Session\AccountInterface;
10 use Drupal\node\NodeInterface;
11 use Drupal\user\UserInterface;
12
13 /**
14  * Defines the node entity class.
15  *
16  * @ContentEntityType(
17  *   id = "node",
18  *   label = @Translation("Content"),
19  *   label_collection = @Translation("Content"),
20  *   label_singular = @Translation("content item"),
21  *   label_plural = @Translation("content items"),
22  *   label_count = @PluralTranslation(
23  *     singular = "@count content item",
24  *     plural = "@count content items"
25  *   ),
26  *   bundle_label = @Translation("Content type"),
27  *   handlers = {
28  *     "storage" = "Drupal\node\NodeStorage",
29  *     "storage_schema" = "Drupal\node\NodeStorageSchema",
30  *     "view_builder" = "Drupal\node\NodeViewBuilder",
31  *     "access" = "Drupal\node\NodeAccessControlHandler",
32  *     "views_data" = "Drupal\node\NodeViewsData",
33  *     "form" = {
34  *       "default" = "Drupal\node\NodeForm",
35  *       "delete" = "Drupal\node\Form\NodeDeleteForm",
36  *       "edit" = "Drupal\node\NodeForm",
37  *       "delete-multiple-confirm" = "Drupal\node\Form\DeleteMultiple"
38  *     },
39  *     "route_provider" = {
40  *       "html" = "Drupal\node\Entity\NodeRouteProvider",
41  *     },
42  *     "list_builder" = "Drupal\node\NodeListBuilder",
43  *     "translation" = "Drupal\node\NodeTranslationHandler"
44  *   },
45  *   base_table = "node",
46  *   data_table = "node_field_data",
47  *   revision_table = "node_revision",
48  *   revision_data_table = "node_field_revision",
49  *   show_revision_ui = TRUE,
50  *   translatable = TRUE,
51  *   list_cache_contexts = { "user.node_grants:view" },
52  *   entity_keys = {
53  *     "id" = "nid",
54  *     "revision" = "vid",
55  *     "bundle" = "type",
56  *     "label" = "title",
57  *     "langcode" = "langcode",
58  *     "uuid" = "uuid",
59  *     "status" = "status",
60  *     "published" = "status",
61  *     "uid" = "uid",
62  *   },
63  *   revision_metadata_keys = {
64  *     "revision_user" = "revision_uid",
65  *     "revision_created" = "revision_timestamp",
66  *     "revision_log_message" = "revision_log"
67  *   },
68  *   bundle_entity_type = "node_type",
69  *   field_ui_base_route = "entity.node_type.edit_form",
70  *   common_reference_target = TRUE,
71  *   permission_granularity = "bundle",
72  *   links = {
73  *     "canonical" = "/node/{node}",
74  *     "delete-form" = "/node/{node}/delete",
75  *     "delete-multiple-form" = "/admin/content/node/delete",
76  *     "edit-form" = "/node/{node}/edit",
77  *     "version-history" = "/node/{node}/revisions",
78  *     "revision" = "/node/{node}/revisions/{node_revision}/view",
79  *     "create" = "/node",
80  *   }
81  * )
82  */
83 class Node extends EditorialContentEntityBase implements NodeInterface {
84
85   /**
86    * Whether the node is being previewed or not.
87    *
88    * The variable is set to public as it will give a considerable performance
89    * improvement. See https://www.drupal.org/node/2498919.
90    *
91    * @var true|null
92    *   TRUE if the node is being previewed and NULL if it is not.
93    */
94   public $in_preview = NULL;
95
96   /**
97    * {@inheritdoc}
98    */
99   public function preSave(EntityStorageInterface $storage) {
100     parent::preSave($storage);
101
102     foreach (array_keys($this->getTranslationLanguages()) as $langcode) {
103       $translation = $this->getTranslation($langcode);
104
105       // If no owner has been set explicitly, make the anonymous user the owner.
106       if (!$translation->getOwner()) {
107         $translation->setOwnerId(0);
108       }
109     }
110
111     // If no revision author has been set explicitly, make the node owner the
112     // revision author.
113     if (!$this->getRevisionUser()) {
114       $this->setRevisionUserId($this->getOwnerId());
115     }
116   }
117
118   /**
119    * {@inheritdoc}
120    */
121   public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
122     parent::preSaveRevision($storage, $record);
123
124     if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) {
125       // If we are updating an existing node without adding a new revision, we
126       // need to make sure $entity->revision_log is reset whenever it is empty.
127       // Therefore, this code allows us to avoid clobbering an existing log
128       // entry with an empty one.
129       $record->revision_log = $this->original->revision_log->value;
130     }
131   }
132
133   /**
134    * {@inheritdoc}
135    */
136   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
137     parent::postSave($storage, $update);
138
139     // Update the node access table for this node, but only if it is the
140     // default revision. There's no need to delete existing records if the node
141     // is new.
142     if ($this->isDefaultRevision()) {
143       /** @var \Drupal\node\NodeAccessControlHandlerInterface $access_control_handler */
144       $access_control_handler = \Drupal::entityManager()->getAccessControlHandler('node');
145       $grants = $access_control_handler->acquireGrants($this);
146       \Drupal::service('node.grant_storage')->write($this, $grants, NULL, $update);
147     }
148
149     // Reindex the node when it is updated. The node is automatically indexed
150     // when it is added, simply by being added to the node table.
151     if ($update) {
152       node_reindex_node_search($this->id());
153     }
154   }
155
156   /**
157    * {@inheritdoc}
158    */
159   public static function preDelete(EntityStorageInterface $storage, array $entities) {
160     parent::preDelete($storage, $entities);
161
162     // Ensure that all nodes deleted are removed from the search index.
163     if (\Drupal::moduleHandler()->moduleExists('search')) {
164       foreach ($entities as $entity) {
165         search_index_clear('node_search', $entity->nid->value);
166       }
167     }
168   }
169
170   /**
171    * {@inheritdoc}
172    */
173   public static function postDelete(EntityStorageInterface $storage, array $nodes) {
174     parent::postDelete($storage, $nodes);
175     \Drupal::service('node.grant_storage')->deleteNodeRecords(array_keys($nodes));
176   }
177
178   /**
179    * {@inheritdoc}
180    */
181   public function getType() {
182     return $this->bundle();
183   }
184
185   /**
186    * {@inheritdoc}
187    */
188   public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) {
189     // This override exists to set the operation to the default value "view".
190     return parent::access($operation, $account, $return_as_object);
191   }
192
193   /**
194    * {@inheritdoc}
195    */
196   public function getTitle() {
197     return $this->get('title')->value;
198   }
199
200   /**
201    * {@inheritdoc}
202    */
203   public function setTitle($title) {
204     $this->set('title', $title);
205     return $this;
206   }
207
208   /**
209    * {@inheritdoc}
210    */
211   public function getCreatedTime() {
212     return $this->get('created')->value;
213   }
214
215   /**
216    * {@inheritdoc}
217    */
218   public function setCreatedTime($timestamp) {
219     $this->set('created', $timestamp);
220     return $this;
221   }
222
223   /**
224    * {@inheritdoc}
225    */
226   public function isPromoted() {
227     return (bool) $this->get('promote')->value;
228   }
229
230   /**
231    * {@inheritdoc}
232    */
233   public function setPromoted($promoted) {
234     $this->set('promote', $promoted ? NodeInterface::PROMOTED : NodeInterface::NOT_PROMOTED);
235     return $this;
236   }
237
238   /**
239    * {@inheritdoc}
240    */
241   public function isSticky() {
242     return (bool) $this->get('sticky')->value;
243   }
244
245   /**
246    * {@inheritdoc}
247    */
248   public function setSticky($sticky) {
249     $this->set('sticky', $sticky ? NodeInterface::STICKY : NodeInterface::NOT_STICKY);
250     return $this;
251   }
252
253   /**
254    * {@inheritdoc}
255    */
256   public function getOwner() {
257     return $this->get('uid')->entity;
258   }
259
260   /**
261    * {@inheritdoc}
262    */
263   public function getOwnerId() {
264     return $this->getEntityKey('uid');
265   }
266
267   /**
268    * {@inheritdoc}
269    */
270   public function setOwnerId($uid) {
271     $this->set('uid', $uid);
272     return $this;
273   }
274
275   /**
276    * {@inheritdoc}
277    */
278   public function setOwner(UserInterface $account) {
279     $this->set('uid', $account->id());
280     return $this;
281   }
282
283   /**
284    * {@inheritdoc}
285    */
286   public function getRevisionAuthor() {
287     return $this->getRevisionUser();
288   }
289
290   /**
291    * {@inheritdoc}
292    */
293   public function setRevisionAuthorId($uid) {
294     $this->setRevisionUserId($uid);
295     return $this;
296   }
297
298   /**
299    * {@inheritdoc}
300    */
301   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
302     $fields = parent::baseFieldDefinitions($entity_type);
303
304     $fields['title'] = BaseFieldDefinition::create('string')
305       ->setLabel(t('Title'))
306       ->setRequired(TRUE)
307       ->setTranslatable(TRUE)
308       ->setRevisionable(TRUE)
309       ->setSetting('max_length', 255)
310       ->setDisplayOptions('view', [
311         'label' => 'hidden',
312         'type' => 'string',
313         'weight' => -5,
314       ])
315       ->setDisplayOptions('form', [
316         'type' => 'string_textfield',
317         'weight' => -5,
318       ])
319       ->setDisplayConfigurable('form', TRUE);
320
321     $fields['uid'] = BaseFieldDefinition::create('entity_reference')
322       ->setLabel(t('Authored by'))
323       ->setDescription(t('The username of the content author.'))
324       ->setRevisionable(TRUE)
325       ->setSetting('target_type', 'user')
326       ->setDefaultValueCallback('Drupal\node\Entity\Node::getCurrentUserId')
327       ->setTranslatable(TRUE)
328       ->setDisplayOptions('view', [
329         'label' => 'hidden',
330         'type' => 'author',
331         'weight' => 0,
332       ])
333       ->setDisplayOptions('form', [
334         'type' => 'entity_reference_autocomplete',
335         'weight' => 5,
336         'settings' => [
337           'match_operator' => 'CONTAINS',
338           'size' => '60',
339           'placeholder' => '',
340         ],
341       ])
342       ->setDisplayConfigurable('form', TRUE);
343
344     $fields['status']
345       ->setDisplayOptions('form', [
346         'type' => 'boolean_checkbox',
347         'settings' => [
348           'display_label' => TRUE,
349         ],
350         'weight' => 120,
351       ])
352       ->setDisplayConfigurable('form', TRUE);
353
354     $fields['created'] = BaseFieldDefinition::create('created')
355       ->setLabel(t('Authored on'))
356       ->setDescription(t('The time that the node was created.'))
357       ->setRevisionable(TRUE)
358       ->setTranslatable(TRUE)
359       ->setDisplayOptions('view', [
360         'label' => 'hidden',
361         'type' => 'timestamp',
362         'weight' => 0,
363       ])
364       ->setDisplayOptions('form', [
365         'type' => 'datetime_timestamp',
366         'weight' => 10,
367       ])
368       ->setDisplayConfigurable('form', TRUE);
369
370     $fields['changed'] = BaseFieldDefinition::create('changed')
371       ->setLabel(t('Changed'))
372       ->setDescription(t('The time that the node was last edited.'))
373       ->setRevisionable(TRUE)
374       ->setTranslatable(TRUE);
375
376     $fields['promote'] = BaseFieldDefinition::create('boolean')
377       ->setLabel(t('Promoted to front page'))
378       ->setRevisionable(TRUE)
379       ->setTranslatable(TRUE)
380       ->setDefaultValue(TRUE)
381       ->setDisplayOptions('form', [
382         'type' => 'boolean_checkbox',
383         'settings' => [
384           'display_label' => TRUE,
385         ],
386         'weight' => 15,
387       ])
388       ->setDisplayConfigurable('form', TRUE);
389
390     $fields['sticky'] = BaseFieldDefinition::create('boolean')
391       ->setLabel(t('Sticky at top of lists'))
392       ->setRevisionable(TRUE)
393       ->setTranslatable(TRUE)
394       ->setDefaultValue(FALSE)
395       ->setDisplayOptions('form', [
396         'type' => 'boolean_checkbox',
397         'settings' => [
398           'display_label' => TRUE,
399         ],
400         'weight' => 16,
401       ])
402       ->setDisplayConfigurable('form', TRUE);
403
404     return $fields;
405   }
406
407   /**
408    * Default value callback for 'uid' base field definition.
409    *
410    * @see ::baseFieldDefinitions()
411    *
412    * @return array
413    *   An array of default values.
414    */
415   public static function getCurrentUserId() {
416     return [\Drupal::currentUser()->id()];
417   }
418
419 }