Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / crop / crop.module
index a5aeafa62cbe729ab525332d7bf6ad520d551039..18e19853bed7956e9c41078a3803f3ef7e2aa59d 100644 (file)
@@ -6,13 +6,15 @@
  *
  * Provides storage and API for image crops.
  */
-
-use \Drupal\Core\Form\FormStateInterface;
+use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\crop\Entity\Crop;
 use Drupal\image\Entity\ImageStyle;
-use \Drupal\media_entity\MediaBundleInterface;
-use \Drupal\file\FileInterface;
+use Drupal\media\Entity\MediaType;
+use Drupal\media\MediaTypeInterface;
+use Drupal\media_entity\MediaBundleInterface;
+use Drupal\file\FileInterface;
 
 /**
  * Implements hook_theme().
@@ -38,25 +40,54 @@ function template_preprocess_crop_crop_summary(&$variables) {
 }
 
 /**
- * Implements hook_form_BASE_ID_alter().
+ * Implements hook_form_FORM_ID_alter().
  *
- * Adds crop configuraiton fields to media bundle form.
+ * Adds crop configuration fields to media type form.
  */
-function crop_form_media_bundle_form_alter(&$form, FormStateInterface $form_state, $form_id) {
-  /** @var \Drupal\media_entity\MediaBundleInterface $bundle */
-  $bundle = $form['#entity'];
+function crop_form_media_type_edit_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
+  _crop_media_provider_form($form, $form_state);
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * Adds crop configuration fields to media bundle form.
+ */
+function crop_form_media_bundle_edit_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
+  _crop_media_provider_form($form, $form_state);
+}
+
+/**
+ * Helper function to avoid uneeded code duplication.
+ *
+ * @todo Delete this and media entity fallback when media is stable.
+ */
+function _crop_media_provider_form(array &$form, FormStateInterface $form_state) {
+  /** @var \Drupal\Core\Config\Entity\ConfigEntityBundleBase $entity_type */
+  $entity_type = $form_state->getFormObject()->getEntity();
   $options = [];
   $allowed_field_types = ['file', 'image'];
-  foreach (\Drupal::service('entity_field.manager')->getFieldDefinitions('media', $bundle->id()) as $field_name => $field) {
+
+  /** @var \Drupal\Core\Field\FieldDefinitionInterface[] $fields */
+  $fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('media', $entity_type->id());
+  foreach ($fields as $field_name => $field) {
     if (in_array($field->getType(), $allowed_field_types) && !$field->getFieldStorageDefinition()->isBaseField()) {
       $options[$field_name] = $field->getLabel();
     }
   }
 
-  $form['#entity_builders'][] = 'crop_media_bundle_form_builder';
+  // Maintain compatibility with Media Entity.
+  if ($entity_type instanceof MediaType) {
+    $form['#entity_builders'][] = 'crop_media_type_form_builder';
+  }
+  else {
+    $form['#entity_builders'][] = 'crop_media_bundle_form_builder';
+  }
+
   $form['crop'] = [
     '#type' => 'fieldset',
     '#title' => t('Crop configuration'),
+    '#group' => 'source_dependent',
   ];
 
   if (empty($options)) {
@@ -75,11 +106,14 @@ function crop_form_media_bundle_form_alter(&$form, FormStateInterface $form_stat
   $form['crop']['image_field'] = [
     '#type' => 'select',
     '#title' => t('Image field'),
-    '#default_value' => $bundle->getThirdPartySetting('crop', 'image_field'),
+    '#default_value' => $entity_type->getThirdPartySetting('crop', 'image_field'),
     '#options' => $options,
+    '#empty_option' => t('- Skip field -'),
+    '#empty_value' => '_none',
     '#description' => t('Select field that stores image which needs to be cropped.'),
   ];
 
+  return $form;
 }
 
 /**
@@ -93,6 +127,17 @@ function crop_media_bundle_form_builder($entity_type, MediaBundleInterface $bund
   $bundle->setThirdPartySetting('crop', 'image_field', $form_state->getValue('image_field'));
 }
 
+/**
+ * Entity builder for Media type.
+ *
+ * Adds third party settings to Media type config entity.
+ *
+ * @see crop_form_media_type_edit_form_alter()
+ */
+function crop_media_type_form_builder($entity_type, MediaTypeInterface $bundle, array &$form, FormStateInterface $form_state) {
+  $bundle->setThirdPartySetting('crop', 'image_field', $form_state->getValue('image_field'));
+}
+
 /**
  * Implements hook_ENTITY_TYPE_delete().
  *
@@ -114,41 +159,49 @@ function crop_file_delete(FileInterface $file) {
  */
 function crop_file_url_alter(&$uri) {
   // Process only files that are stored in "styles" directory.
-  if (strpos($uri, PublicStream::basePath() . '/styles/') !== FALSE) {
-    // Handle the case of multiple "/styles/" in URI.
-    $uri_parts = explode('/styles/', $uri);
-    $image_style_part = end($uri_parts);
+  if (strpos($uri, '/styles/') !== FALSE && preg_match('/\/styles\/(.*?)\/(.*?)\/(.+)/', $uri, $match)) {
     // Match image style, schema, file subdirectory and file name.
-    preg_match("/(.*?)\/(.*?)\/(.*+)/", $image_style_part, $match);
     // Get the image style ID.
     $image_style = $match[1];
     // Get the file path without query parameter.
-    $parsed_uri = parse_url($match[3]);
+    $parsed_uri = UrlHelper::parse($match[3]);
     // Get the file URI using parsed schema and file path.
     $file_uri = $match[2] . '://' . $parsed_uri['path'];
 
-    /** @var \Drupal\image\Entity\ImageStyle $image_style */
-    if (!$image_style = ImageStyle::load($image_style)) {
+    // Prevent double hashing, if there is a hash argument already, do not add
+    // it again.
+    if (!empty($parsed_uri['query']['h'])) {
       return;
     }
 
-    $crop_type = NULL;
-    // Find whether matched image style uses "crop_type" effect.
-    /* @var  \Drupal\image\ImageEffectInterface $effect */
-    foreach ($image_style->getEffects() as $uuid => $effect) {
-      $data_effect = $image_style->getEffect($uuid)->getConfiguration()['data'];
-      if (isset($data_effect['crop_type'])) {
-        $crop_type = $data_effect['crop_type'];
-        break;
-      }
+    /** @var \Drupal\image\Entity\ImageStyle $image_style */
+    if (!$image_style = ImageStyle::load($image_style)) {
+      return;
     }
 
-    // In case the image style uses "crop_type" effect, load the crop entity.
-    if ($crop_type && $crop = Crop::findCrop($file_uri, $crop_type)) {
+    if ($crop = Crop::getCropFromImageStyle($file_uri, $image_style)) {
       // Found a crop for this image, append a hash of it to the URL,
       // so that browsers reload the image and CDNs and proxies can be bypassed.
       $shortened_hash = substr(md5(implode($crop->position()) . implode($crop->anchor())), 0, 8);
-      $uri .= '&h=' . $shortened_hash;
+
+      // If the URI has a schema and that is not http, https or data, convert
+      // the URI to the external URL. Otherwise the appended query argument
+      // will be encoded.
+      // @see file_create_url()
+      $scheme = \Drupal::service('file_system')->uriScheme($uri);
+      if ($scheme && !in_array($scheme, ['http', 'https', 'data'])) {
+        if ($wrapper = \Drupal::service('stream_wrapper_manager')->getViaUri($uri)) {
+          $uri = $wrapper->getExternalUrl();
+        }
+      }
+
+      // Append either with a ? or a & if there are existing query arguments.
+      if (strpos($uri, '?') === FALSE) {
+        $uri .= '?h=' . $shortened_hash;
+      }
+      else {
+        $uri .= '&h=' . $shortened_hash;
+      }
     }
   }
 }