*
* 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().
}
/**
- * 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)) {
$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;
}
/**
$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().
*
*/
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;
+ }
}
}
}