Updating Media dependent modules to versions compatible with core Media.
[yaffs-website] / web / modules / contrib / crop / crop.module
1 <?php
2
3 /**
4  * @file
5  * The Crop API Drupal module.
6  *
7  * Provides storage and API for image crops.
8  */
9
10 use Drupal\Component\Utility\UrlHelper;
11 use Drupal\Core\Form\FormStateInterface;
12 use Drupal\Core\StreamWrapper\PublicStream;
13 use Drupal\crop\Entity\Crop;
14 use Drupal\image\Entity\ImageStyle;
15 use Drupal\media\MediaSourceInterface;
16 use Drupal\media\MediaTypeInterface;
17 use Drupal\file\FileInterface;
18
19 /**
20  * Implements hook_theme().
21  */
22 function crop_theme() {
23   return [
24     'crop_crop_summary' => [
25       'variables' => ['data' => [], 'effect' => []],
26     ],
27   ];
28 }
29
30 /**
31  * Prepares variables for crop_crop summary template.
32  *
33  * Default template: crop-crop-summary.twig.html.
34  */
35 function template_preprocess_crop_crop_summary(&$variables) {
36   if (!empty($variables['data']['crop_type'])) {
37     $type = \Drupal::entityTypeManager()->getStorage('crop_type')->load($variables['data']['crop_type']);
38     $variables['data']['crop_type'] = $type->label();
39   }
40 }
41
42 /**
43  * Implements hook_form_FORM_ID_alter().
44  *
45  * Adds crop configuration fields to media form.
46  */
47 function crop_form_media_type_edit_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
48   /** @var \Drupal\media\Entity\MediaType $entity_type */
49   $entity_type = $form_state->getFormObject()->getEntity();
50   $options = [];
51   $allowed_field_types = ['file', 'image'];
52
53   /** @var \Drupal\Core\Field\FieldDefinitionInterface[] $fields */
54   $fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('media', $entity_type->id());
55   foreach ($fields as $field_name => $field) {
56     if (in_array($field->getType(), $allowed_field_types) && !$field->getFieldStorageDefinition()->isBaseField()) {
57       $options[$field_name] = $field->getLabel();
58     }
59   }
60
61   $form['#entity_builders'][] = 'crop_media_type_form_builder';
62   $form['crop'] = [
63     '#type' => 'fieldset',
64     '#title' => t('Crop configuration'),
65     '#group' => 'source_dependent',
66   ];
67
68   if (empty($options)) {
69     $form['crop']['image_field'] = [
70       '#type' => 'value',
71       '#value' => NULL,
72     ];
73
74     $form['crop']['message'] = [
75       '#markup' => t('There are no file or image fields on this bundle at the moment. In order to configure crop add at least one such field and come back.'),
76     ];
77
78     return;
79   }
80
81   $form['crop']['image_field'] = [
82     '#type' => 'select',
83     '#title' => t('Image field'),
84     '#default_value' => $entity_type->getThirdPartySetting('crop', 'image_field'),
85     '#options' => $options,
86     '#empty_option' => t('- Skip field -'),
87     '#empty_value' => MediaSourceInterface::METADATA_FIELD_EMPTY,
88     '#description' => t('Select field that stores image which needs to be cropped.'),
89   ];
90 }
91
92 /**
93  * Entity builder for Media type.
94  *
95  * Adds third party settings to Media type config entity.
96  *
97  * @see crop_form_media_type_edit_form_alter()
98  */
99 function crop_media_type_form_builder($entity_type, MediaTypeInterface $bundle, array &$form, FormStateInterface $form_state) {
100   $bundle->setThirdPartySetting('crop', 'image_field', $form_state->getValue('image_field'));
101 }
102
103 /**
104  * Implements hook_ENTITY_TYPE_delete().
105  *
106  * Deletes orphaned crops when a file is deleted.
107  */
108 function crop_file_delete(FileInterface $file) {
109   // Get all crops for the file being deleted.
110   $crops = \Drupal::entityTypeManager()
111     ->getStorage('crop')
112     ->loadByProperties(['uri' => $file->getFileUri()]);
113
114   foreach ($crops as $crop) {
115     $crop->delete();
116   }
117 }
118
119 /**
120  * Implements hook_file_url_alter().
121  */
122 function crop_file_url_alter(&$uri) {
123   // Process only files that are stored in "styles" directory.
124   if (strpos($uri, '/styles/') !== FALSE && preg_match('/\/styles\/(.*?)\/(.*?)\/(.+)/', $uri, $match)) {
125     // Match image style, schema, file subdirectory and file name.
126     // Get the image style ID.
127     $image_style = $match[1];
128     // Get the file path without query parameter.
129     $parsed_uri = UrlHelper::parse($match[3]);
130     // Get the file URI using parsed schema and file path.
131     $file_uri = $match[2] . '://' . $parsed_uri['path'];
132
133     // Prevent double hashing, if there is a hash argument already, do not add
134     // it again.
135     if (!empty($parsed_uri['query']['h'])) {
136       return;
137     }
138
139     /** @var \Drupal\image\Entity\ImageStyle $image_style */
140     if (!$image_style = ImageStyle::load($image_style)) {
141       return;
142     }
143
144     if ($crop = Crop::getCropFromImageStyle($file_uri, $image_style)) {
145       // Found a crop for this image, append a hash of it to the URL,
146       // so that browsers reload the image and CDNs and proxies can be bypassed.
147       $shortened_hash = substr(md5(implode($crop->position()) . implode($crop->anchor())), 0, 8);
148
149       // If the URI has a schema and that is not http, https or data, convert
150       // the URI to the external URL. Otherwise the appended query argument
151       // will be encoded.
152       // @see file_create_url()
153       $scheme = \Drupal::service('file_system')->uriScheme($uri);
154       if ($scheme && !in_array($scheme, ['http', 'https', 'data'])) {
155         if ($wrapper = \Drupal::service('stream_wrapper_manager')->getViaUri($uri)) {
156           $uri = $wrapper->getExternalUrl();
157         }
158       }
159
160       // Append either with a ? or a & if there are existing query arguments.
161       if (strpos($uri, '?') === FALSE) {
162         $uri .= '?h=' . $shortened_hash;
163       }
164       else {
165         $uri .= '&h=' . $shortened_hash;
166       }
167     }
168   }
169 }