Pull merge.
[yaffs-website] / web / core / modules / block_content / src / Entity / BlockContent.php
1 <?php
2
3 namespace Drupal\block_content\Entity;
4
5 use Drupal\block_content\Access\RefinableDependentAccessTrait;
6 use Drupal\Core\Entity\EditorialContentEntityBase;
7 use Drupal\Core\Entity\EntityStorageInterface;
8 use Drupal\Core\Entity\EntityTypeInterface;
9 use Drupal\Core\Field\BaseFieldDefinition;
10 use Drupal\block_content\BlockContentInterface;
11 use Drupal\user\UserInterface;
12
13 /**
14  * Defines the custom block entity class.
15  *
16  * @ContentEntityType(
17  *   id = "block_content",
18  *   label = @Translation("Custom block"),
19  *   label_collection = @Translation("Custom blocks"),
20  *   label_singular = @Translation("custom block"),
21  *   label_plural = @Translation("custom blocks"),
22  *   label_count = @PluralTranslation(
23  *     singular = "@count custom block",
24  *     plural = "@count custom blocks",
25  *   ),
26  *   bundle_label = @Translation("Custom block type"),
27  *   handlers = {
28  *     "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
29  *     "access" = "Drupal\block_content\BlockContentAccessControlHandler",
30  *     "list_builder" = "Drupal\block_content\BlockContentListBuilder",
31  *     "view_builder" = "Drupal\block_content\BlockContentViewBuilder",
32  *     "views_data" = "Drupal\block_content\BlockContentViewsData",
33  *     "form" = {
34  *       "add" = "Drupal\block_content\BlockContentForm",
35  *       "edit" = "Drupal\block_content\BlockContentForm",
36  *       "delete" = "Drupal\block_content\Form\BlockContentDeleteForm",
37  *       "default" = "Drupal\block_content\BlockContentForm"
38  *     },
39  *     "translation" = "Drupal\block_content\BlockContentTranslationHandler"
40  *   },
41  *   admin_permission = "administer blocks",
42  *   base_table = "block_content",
43  *   revision_table = "block_content_revision",
44  *   data_table = "block_content_field_data",
45  *   revision_data_table = "block_content_field_revision",
46  *   show_revision_ui = TRUE,
47  *   links = {
48  *     "canonical" = "/block/{block_content}",
49  *     "delete-form" = "/block/{block_content}/delete",
50  *     "edit-form" = "/block/{block_content}",
51  *     "collection" = "/admin/structure/block/block-content",
52  *     "create" = "/block",
53  *   },
54  *   translatable = TRUE,
55  *   entity_keys = {
56  *     "id" = "id",
57  *     "revision" = "revision_id",
58  *     "bundle" = "type",
59  *     "label" = "info",
60  *     "langcode" = "langcode",
61  *     "uuid" = "uuid",
62  *     "published" = "status",
63  *   },
64  *   revision_metadata_keys = {
65  *     "revision_user" = "revision_user",
66  *     "revision_created" = "revision_created",
67  *     "revision_log_message" = "revision_log"
68  *   },
69  *   bundle_entity_type = "block_content_type",
70  *   field_ui_base_route = "entity.block_content_type.edit_form",
71  *   render_cache = FALSE,
72  * )
73  *
74  * Note that render caching of block_content entities is disabled because they
75  * are always rendered as blocks, and blocks already have their own render
76  * caching.
77  * See https://www.drupal.org/node/2284917#comment-9132521 for more information.
78  */
79 class BlockContent extends EditorialContentEntityBase implements BlockContentInterface {
80
81   use RefinableDependentAccessTrait;
82
83   /**
84    * The theme the block is being created in.
85    *
86    * When creating a new custom block from the block library, the user is
87    * redirected to the configure form for that block in the given theme. The
88    * theme is stored against the block when the custom block add form is shown.
89    *
90    * @var string
91    */
92   protected $theme;
93
94   /**
95    * {@inheritdoc}
96    */
97   public function createDuplicate() {
98     $duplicate = parent::createDuplicate();
99     $duplicate->revision_id->value = NULL;
100     $duplicate->id->value = NULL;
101     return $duplicate;
102   }
103
104   /**
105    * {@inheritdoc}
106    */
107   public function setTheme($theme) {
108     $this->theme = $theme;
109     return $this;
110   }
111
112   /**
113    * {@inheritdoc}
114    */
115   public function getTheme() {
116     return $this->theme;
117   }
118
119   /**
120    * {@inheritdoc}
121    */
122   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
123     parent::postSave($storage, $update);
124     if ($this->isReusable() || (isset($this->original) && $this->original->isReusable())) {
125       static::invalidateBlockPluginCache();
126     }
127   }
128
129   /**
130    * {@inheritdoc}
131    */
132   public static function postDelete(EntityStorageInterface $storage, array $entities) {
133     parent::postDelete($storage, $entities);
134     /** @var \Drupal\block_content\BlockContentInterface $block */
135     foreach ($entities as $block) {
136       if ($block->isReusable()) {
137         // If any deleted blocks are reusable clear the block cache.
138         static::invalidateBlockPluginCache();
139         return;
140       }
141     }
142   }
143
144   /**
145    * {@inheritdoc}
146    */
147   public function getInstances() {
148     return \Drupal::entityTypeManager()->getStorage('block')->loadByProperties(['plugin' => 'block_content:' . $this->uuid()]);
149   }
150
151   /**
152    * {@inheritdoc}
153    */
154   public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
155     parent::preSaveRevision($storage, $record);
156
157     if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) {
158       // If we are updating an existing block_content without adding a new
159       // revision and the user did not supply a revision log, keep the existing
160       // one.
161       $record->revision_log = $this->original->getRevisionLogMessage();
162     }
163   }
164
165   /**
166    * {@inheritdoc}
167    */
168   public function delete() {
169     foreach ($this->getInstances() as $instance) {
170       $instance->delete();
171     }
172     parent::delete();
173   }
174
175   /**
176    * {@inheritdoc}
177    */
178   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
179     /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
180     $fields = parent::baseFieldDefinitions($entity_type);
181
182     $fields['id']->setLabel(t('Custom block ID'))
183       ->setDescription(t('The custom block ID.'));
184
185     $fields['uuid']->setDescription(t('The custom block UUID.'));
186
187     $fields['revision_id']->setDescription(t('The revision ID.'));
188
189     $fields['langcode']->setDescription(t('The custom block language code.'));
190
191     $fields['type']->setLabel(t('Block type'))
192       ->setDescription(t('The block type.'));
193
194     $fields['revision_log']->setDescription(t('The log entry explaining the changes in this revision.'));
195
196     $fields['info'] = BaseFieldDefinition::create('string')
197       ->setLabel(t('Block description'))
198       ->setDescription(t('A brief description of your block.'))
199       ->setRevisionable(TRUE)
200       ->setTranslatable(TRUE)
201       ->setRequired(TRUE)
202       ->setDisplayOptions('form', [
203         'type' => 'string_textfield',
204         'weight' => -5,
205       ])
206       ->setDisplayConfigurable('form', TRUE)
207       ->addConstraint('UniqueField', []);
208
209     $fields['changed'] = BaseFieldDefinition::create('changed')
210       ->setLabel(t('Changed'))
211       ->setDescription(t('The time that the custom block was last edited.'))
212       ->setTranslatable(TRUE)
213       ->setRevisionable(TRUE);
214
215     $fields['reusable'] = BaseFieldDefinition::create('boolean')
216       ->setLabel(t('Reusable'))
217       ->setDescription(t('A boolean indicating whether this block is reusable.'))
218       ->setTranslatable(FALSE)
219       ->setRevisionable(FALSE)
220       ->setDefaultValue(TRUE);
221
222     return $fields;
223   }
224
225   /**
226    * {@inheritdoc}
227    */
228   public function getRevisionLog() {
229     return $this->getRevisionLogMessage();
230   }
231
232   /**
233    * {@inheritdoc}
234    */
235   public function setInfo($info) {
236     $this->set('info', $info);
237     return $this;
238   }
239
240   /**
241    * {@inheritdoc}
242    */
243   public function setRevisionLog($revision_log) {
244     return $this->setRevisionLogMessage($revision_log);
245   }
246
247   /**
248    * {@inheritdoc}
249    */
250   public function getRevisionCreationTime() {
251     return $this->get('revision_created')->value;
252   }
253
254   /**
255    * {@inheritdoc}
256    */
257   public function setRevisionCreationTime($timestamp) {
258     $this->set('revision_created', $timestamp);
259     return $this;
260   }
261
262   /**
263    * {@inheritdoc}
264    */
265   public function getRevisionUser() {
266     return $this->get('revision_user')->entity;
267   }
268
269   public function setRevisionUser(UserInterface $account) {
270     $this->set('revision_user', $account);
271     return $this;
272   }
273
274   /**
275    * {@inheritdoc}
276    */
277   public function getRevisionUserId() {
278     return $this->get('revision_user')->entity->id();
279   }
280
281   /**
282    * {@inheritdoc}
283    */
284   public function setRevisionUserId($user_id) {
285     $this->set('revision_user', $user_id);
286     return $this;
287   }
288
289   /**
290    * {@inheritdoc}
291    */
292   public function getRevisionLogMessage() {
293     return $this->get('revision_log')->value;
294   }
295
296   /**
297    * {@inheritdoc}
298    */
299   public function setRevisionLogMessage($revision_log_message) {
300     $this->set('revision_log', $revision_log_message);
301     return $this;
302   }
303
304   /**
305    * {@inheritdoc}
306    */
307   public function isReusable() {
308     return (bool) $this->get('reusable')->value;
309   }
310
311   /**
312    * {@inheritdoc}
313    */
314   public function setReusable() {
315     return $this->set('reusable', TRUE);
316   }
317
318   /**
319    * {@inheritdoc}
320    */
321   public function setNonReusable() {
322     return $this->set('reusable', FALSE);
323   }
324
325   /**
326    * Invalidates the block plugin cache after changes and deletions.
327    */
328   protected static function invalidateBlockPluginCache() {
329     // Invalidate the block cache to update custom block-based derivatives.
330     \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
331   }
332
333 }