Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / crop / src / Entity / Crop.php
1 <?php
2
3 namespace Drupal\crop\Entity;
4
5 use Drupal\Core\Entity\ContentEntityBase;
6 use Drupal\Core\Entity\EntityStorageInterface;
7 use Drupal\Core\Entity\EntityTypeInterface;
8 use Drupal\Core\Field\BaseFieldDefinition;
9 use Drupal\crop\CropInterface;
10 use Drupal\crop\EntityProviderNotFoundException;
11 use Drupal\image\ImageStyleInterface;
12
13 /**
14  * Defines the crop entity class.
15  *
16  * @ContentEntityType(
17  *   id = "crop",
18  *   label = @Translation("Crop"),
19  *   bundle_label = @Translation("Crop type"),
20  *   handlers = {
21  *     "storage" = "Drupal\crop\CropStorage",
22  *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
23  *     "access" = "Drupal\Core\Entity\EntityAccessControlHandler",
24  *     "form" = {
25  *       "default" = "Drupal\Core\Entity\ContentEntityForm",
26  *       "delete" = "Drupal\Core\Entity\ContentEntityConfirmFormBase",
27  *       "edit" = "Drupal\Core\Entity\ContentEntityForm"
28  *     },
29  *     "translation" = "Drupal\content_translation\ContentTranslationHandler"
30  *   },
31  *   base_table = "crop",
32  *   data_table = "crop_field_data",
33  *   revision_table = "crop_revision",
34  *   revision_data_table = "crop_field_revision",
35  *   fieldable = TRUE,
36  *   translatable = TRUE,
37  *   render_cache = FALSE,
38  *   entity_keys = {
39  *     "id" = "cid",
40  *     "bundle" = "type",
41  *     "revision" = "vid",
42  *     "langcode" = "langcode",
43  *     "uuid" = "uuid"
44  *   },
45  *   revision_metadata_keys = {
46  *     "revision_timestamp" = "revision_timestamp",
47  *     "revision_uid" = "revision_uid",
48  *     "revision_log" = "revision_log"
49  *   },
50  *   bundle_entity_type = "crop_type",
51  *   permission_granularity = "entity_type",
52  *   admin_permission = "administer crop",
53  *   links = {
54  *   }
55  * )
56  */
57 class Crop extends ContentEntityBase implements CropInterface {
58
59   /**
60    * {@inheritdoc}
61    */
62   public function position() {
63     return [
64       'x' => (int) $this->x->value,
65       'y' => (int) $this->y->value,
66     ];
67   }
68
69   /**
70    * {@inheritdoc}
71    */
72   public function setPosition($x, $y) {
73     $this->x = $x;
74     $this->y = $y;
75
76     return $this;
77   }
78
79   /**
80    * {@inheritdoc}
81    */
82   public function anchor() {
83     return [
84       'x' => (int) ($this->x->value - ($this->width->value / 2)),
85       'y' => (int) ($this->y->value - ($this->height->value / 2)),
86     ];
87   }
88
89   /**
90    * {@inheritdoc}
91    */
92   public function size() {
93     return [
94       'width' => (int) $this->width->value,
95       'height' => (int) $this->height->value,
96     ];
97   }
98
99   /**
100    * {@inheritdoc}
101    */
102   public function setSize($width, $height) {
103     $this->width = $width;
104     $this->height = $height;
105     return $this;
106   }
107
108   /**
109    * {@inheritdoc}
110    */
111   public function provider() {
112     /** @var \Drupal\crop\EntityProviderManager $plugin_manager */
113     $plugin_manager = \Drupal::service('plugin.manager.crop.entity_provider');
114
115     if (!$plugin_manager->hasDefinition($this->entity_type->value)) {
116       throw new EntityProviderNotFoundException(t('Entity provider @id not found.', ['@id' => $this->entity_type->value]));
117     }
118
119     return $plugin_manager->createInstance($this->entity_type->value);
120   }
121
122   /**
123    * {@inheritdoc}
124    */
125   public static function cropExists($uri, $type = NULL) {
126     $query = \Drupal::entityQuery('crop')
127       ->condition('uri', $uri);
128     if ($type) {
129       $query->condition('type', $type);
130     }
131     return (bool) $query->execute();
132   }
133
134   /**
135    * {@inheritdoc}
136    */
137   public static function findCrop($uri, $type) {
138     return \Drupal::entityTypeManager()->getStorage('crop')->getCrop($uri, $type);
139   }
140
141   /**
142    * {@inheritdoc}
143    */
144   public static function getCropFromImageStyle($uri, ImageStyleInterface $image_style) {
145     $effects = [];
146     $crop = FALSE;
147
148     foreach ($image_style->getEffects() as $uuid => $effect) {
149       // Store the effects parameters for later use.
150       $effects[$effect->getPluginId()] = [
151         'uuid' => $uuid,
152         'provider' => $effect->getPluginDefinition()['provider'],
153       ];
154     }
155
156     if (isset($effects['crop_crop']) && $image_style->getEffects()
157         ->has($effects['crop_crop']['uuid'])) {
158       $type = $image_style->getEffect($effects['crop_crop']['uuid'])
159         ->getConfiguration()['data']['crop_type'];
160       $crop = self::findCrop($uri, $type);
161     }
162
163     // Fallback to use the provider as a fallback to check if provider name,
164     // match with crop types for modules non-based on "manual crop" effects.
165     if (!$crop) {
166       foreach ($effects as $effect) {
167         $provider = $effect['provider'];
168         $crop = self::findCrop($uri, $provider);
169       }
170     }
171
172     return $crop;
173   }
174
175   /**
176    * {@inheritdoc}
177    */
178   public function preSave(EntityStorageInterface $storage) {
179     parent::preSave($storage);
180
181     // If no revision author has been set explicitly, make the current user
182     // revision author.
183     if (!$this->get('revision_uid')->entity) {
184       $this->set('revision_uid', \Drupal::currentUser()->id());
185     }
186
187     // Try to set URI if not yet defined.
188     if (empty($this->uri->value) && !empty($this->entity_type->value) && !empty($this->entity_id->value)) {
189       $entity = \Drupal::entityTypeManager()->getStorage($this->entity_type->value)->load($this->entity_id->value);
190       if ($uri = $this->provider()->uri($entity)) {
191         $this->set('uri', $uri);
192       }
193     }
194   }
195
196   /**
197    * {@inheritdoc}
198    */
199   public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) {
200     parent::preSaveRevision($storage, $record);
201
202     if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) {
203       // If we are updating an existing crop without adding a new revision, we
204       // need to make sure $entity->revision_log is reset whenever it is empty.
205       // Therefore, this code allows us to avoid clobbering an existing log
206       // entry with an empty one.
207       $record->revision_log = $this->original->revision_log->value;
208     }
209   }
210
211   /**
212    * {@inheritdoc}
213    */
214   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
215     parent::postSave($storage, $update);
216
217     // If you are manually generating your image derivatives instead of waiting
218     // for them to be generated on the fly, because you are using a cloud
219     // storage service (like S3), then you may not want your image derivatives
220     // to be flushed. If they are you could end up serving 404s during the time
221     // between the crop entity being saved and the image derivative being
222     // manually generated and pushed to your cloud storage service. In that
223     // case, set this configuration variable to false.
224     $flush_derivative_images = \Drupal::config('crop.settings')->get('flush_derivative_images');
225     if ($flush_derivative_images) {
226       image_path_flush($this->uri->value);
227     }
228   }
229
230   /**
231    * {@inheritdoc}
232    */
233   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
234     $fields = [];
235
236     $fields['cid'] = BaseFieldDefinition::create('integer')
237       ->setLabel(t('Crop ID'))
238       ->setDescription(t('The crop ID.'))
239       ->setReadOnly(TRUE)
240       ->setSetting('unsigned', TRUE);
241
242     $fields['uuid'] = BaseFieldDefinition::create('uuid')
243       ->setLabel(t('UUID'))
244       ->setDescription(t('The crop UUID.'))
245       ->setReadOnly(TRUE);
246
247     $fields['vid'] = BaseFieldDefinition::create('integer')
248       ->setLabel(t('Revision ID'))
249       ->setDescription(t('The crop revision ID.'))
250       ->setReadOnly(TRUE)
251       ->setSetting('unsigned', TRUE);
252
253     $fields['type'] = BaseFieldDefinition::create('entity_reference')
254       ->setLabel(t('Type'))
255       ->setDescription(t('The crop type.'))
256       ->setSetting('target_type', 'crop_type')
257       ->setReadOnly(TRUE);
258
259     $fields['langcode'] = BaseFieldDefinition::create('language')
260       ->setLabel(t('Language code'))
261       ->setDescription(t('The node language code.'))
262       ->setRevisionable(TRUE);
263
264     $fields['entity_id'] = BaseFieldDefinition::create('integer')
265       ->setLabel(t('Entity ID'))
266       ->setDescription(t('ID of entity crop belongs to.'))
267       ->setSetting('unsigned', TRUE)
268       ->setRevisionable(TRUE)
269       ->setReadOnly(TRUE);
270
271     $fields['entity_type'] = BaseFieldDefinition::create('string')
272       ->setLabel(t('Entity type'))
273       ->setDescription(t('The type of entity crop belongs to.'))
274       ->setRevisionable(TRUE)
275       ->setReadOnly(TRUE);
276
277     // Denormalized information, which is calculated in storage plugin for a
278     // given entity type. Saved here for performance reasons in image effects.
279     // ---
280     // TODO - we are not enforcing uniqueness on this as we want to support more
281     // crops per same image/image_style combination. However, image effect
282     // operates with image URI only, which means we have no mechanism to
283     // distinguish between multiple crops in there. If we really want to
284     // support multiple crops we'll need to override core at least,
285     // in \Drupal\Core\Image\ImageFactory and \Drupal\Core\Image\Image.
286     // Let's leave this for now and simply load based on URI only.
287     // We can use some semi-smart approach in case there are multiple crops
288     // with same URI for now (first created, last created, ...).
289     $fields['uri'] = BaseFieldDefinition::create('uri')
290       ->setLabel(t('URI'))
291       ->setDescription(t('The URI of the image crop belongs to.'))
292       ->setRevisionable(TRUE)
293       ->setTranslatable(TRUE)
294       ->setSetting('max_length', 255);
295
296     $fields['height'] = BaseFieldDefinition::create('integer')
297       ->setLabel(t('Height'))
298       ->setDescription(t('The crop height.'))
299       ->setRevisionable(TRUE)
300       ->setTranslatable(TRUE)
301       ->setReadOnly(TRUE)
302       ->setSetting('unsigned', TRUE);
303
304     $fields['width'] = BaseFieldDefinition::create('integer')
305       ->setLabel(t('Width'))
306       ->setDescription(t('The crop width.'))
307       ->setRevisionable(TRUE)
308       ->setTranslatable(TRUE)
309       ->setReadOnly(TRUE)
310       ->setSetting('unsigned', TRUE);
311
312     $fields['x'] = BaseFieldDefinition::create('integer')
313       ->setLabel(t('X coordinate'))
314       ->setDescription(t("The crop's X coordinate."))
315       ->setRevisionable(TRUE)
316       ->setTranslatable(TRUE)
317       ->setReadOnly(TRUE)
318       ->setSetting('unsigned', TRUE);
319
320     $fields['y'] = BaseFieldDefinition::create('integer')
321       ->setLabel(t('Y coordinate'))
322       ->setDescription(t("The crop's Y coordinate."))
323       ->setRevisionable(TRUE)
324       ->setTranslatable(TRUE)
325       ->setReadOnly(TRUE)
326       ->setSetting('unsigned', TRUE);
327
328     $fields['revision_timestamp'] = BaseFieldDefinition::create('created')
329       ->setLabel(t('Revision timestamp'))
330       ->setDescription(t('The time that the current revision was created.'))
331       ->setRevisionable(TRUE);
332
333     $fields['revision_uid'] = BaseFieldDefinition::create('entity_reference')
334       ->setLabel(t('Revision author ID'))
335       ->setDescription(t('The user ID of the author of the current revision.'))
336       ->setSetting('target_type', 'user')
337       ->setRevisionable(TRUE);
338
339     $fields['revision_log'] = BaseFieldDefinition::create('string_long')
340       ->setLabel(t('Revision Log'))
341       ->setDescription(t('The log entry explaining the changes in this revision.'))
342       ->setRevisionable(TRUE)
343       ->setTranslatable(TRUE);
344
345     return $fields;
346   }
347
348 }