/**
  * Form API callback: Processes a crop_image field element.
  *
  * Expands the image_image type to include the alt and title fields.
  *
  * This method is assigned as a #process callback in formElement() method.
  */
 public static function process($element, FormStateInterface $form_state, $form)
 {
     $item = $element['#value'];
     $item['fids'] = $element['fids']['#value'];
     $edit = FALSE;
     $route_params = \Drupal::requestStack()->getCurrentRequest()->attributes->get('_route_params');
     if (isset($route_params['_entity_form']) && preg_match('/.edit/', $route_params['_entity_form'])) {
         $edit = TRUE;
     }
     $element['#theme'] = 'image_widget';
     $element['#attached']['library'][] = 'image/form';
     $element['#attached']['library'][] = 'image_widget_crop/drupal.image_widget_crop.admin';
     $element['#attached']['library'][] = 'image_widget_crop/drupal.image_widget_crop.upload.admin';
     // Add the image preview.
     if (!empty($element['#files']) && $element['#preview_image_style']) {
         $file = reset($element['#files']);
         $variables = array('style_name' => $element['#preview_image_style'], 'uri' => $file->getFileUri(), 'file_id' => $file->id());
         /** @var \Drupal\image_widget_crop\ImageWidgetCrop $ImageWidgetCrop */
         $ImageWidgetCrop = new ImageWidgetCrop();
         // Determine image dimensions.
         if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
             $variables['width'] = $element['#value']['width'];
             $variables['height'] = $element['#value']['height'];
         } else {
             $image = \Drupal::service('image.factory')->get($file->getFileUri());
             if ($image->isValid()) {
                 $variables['width'] = $image->getWidth();
                 $variables['height'] = $image->getHeight();
             } else {
                 $variables['width'] = $variables['height'] = NULL;
             }
         }
         $element['crop_preview_wrapper'] = ['#type' => 'container', '#prefix' => '<ul>', '#suffix' => '</ul>', '#attributes' => ['class' => ['preview-wrapper-crop']], '#weight' => 100];
         $image_styles = \Drupal::service('entity.manager')->getStorage('image_style')->loadByProperties(['status' => TRUE]);
         if ($image_styles) {
             /** @var \Drupal\image\Entity\ImageStyle $image_style */
             foreach ($image_styles as $image_style) {
                 if (in_array($image_style->getName(), $element['#crop_list'])) {
                     // Get the ratio of image by ImageStyle.
                     $ratio = $ImageWidgetCrop->getSizeRatio($image_style);
                     // Generation of html List with image & crop informations.
                     // @todo Create new elements for styling the crop container & lists.
                     $element['crop_preview_wrapper'][$image_style->getName()] = ['#type' => 'container', '#prefix' => "<li data-ratio={$ratio}>", '#suffix' => '</li>', '#attributes' => ['class' => ['crop-preview-wrapper-list']], '#weight' => -10];
                     $element['crop_preview_wrapper'][$image_style->getName()]['title'] = ['#prefix' => '<p>', '#suffix' => '</p>', '#markup' => t('@style_label - ( <b>real ratio</b> @ratio )', ['@style_label' => $image_style->label(), '@ratio' => $ratio])];
                     $element['crop_preview_wrapper'][$image_style->getName()]['image'] = ['#theme' => 'image_style', '#style_name' => $element['#crop_preview_image_style'], '#uri' => $variables['uri']];
                     // GET CROP LIBRARIE VALUES.
                     $crop_elements = ['x1' => ['label' => t('crop x1'), 'value' => NULL], 'x2' => ['label' => t('crop x2'), 'value' => NULL], 'y1' => ['label' => t('crop y1'), 'value' => NULL], 'y2' => ['label' => t('crop y2'), 'value' => NULL], 'crop-w' => ['label' => t('crop size width'), 'value' => NULL], 'crop-h' => ['label' => t('crop size height'), 'value' => NULL], 'thumb-w' => ['label' => t('Thumbnail Width'), 'value' => NULL], 'thumb-h' => ['label' => t('Thumbnail Height'), 'value' => NULL]];
                     if ($edit) {
                         $crop = \Drupal::service('entity.manager')->getStorage('crop')->loadByProperties(['type' => $ImageWidgetCrop->getCropType($image_style), 'uri' => $variables['uri'], 'image_style' => $image_style->getName()]);
                         // Only if the crop already exist pre-populate,
                         // all cordinates values.
                         if (!empty($crop)) {
                             /** @var \Drupal\crop\Entity\Crop $crop_entity */
                             foreach ($crop as $crop_id => $crop_entity) {
                                 $crop_properties = ['anchor' => $crop_entity->position(), 'size' => $crop_entity->size()];
                             }
                             // If the current crop have a position & sizes,
                             // calculate properties to apply crop selection into preview.
                             if (isset($crop_properties)) {
                                 $values = static::getThumbnailCropProperties($variables['uri'], $crop_properties);
                             }
                             if (!empty($values)) {
                                 // Populate form crop value with values store into crop API.
                                 foreach ($crop_elements as $properties => $value) {
                                     $crop_elements[$properties]['value'] = $values[$properties];
                                 }
                             }
                         }
                     }
                     // Generate all cordinates elements into the form when,
                     // process is active.
                     foreach ($crop_elements as $crop_elements_name => $crop_elements_value) {
                         $element['crop_preview_wrapper'][$image_style->getName()][$crop_elements_name] = ['#type' => 'textfield', '#title' => $crop_elements_value['label'], '#attributes' => ['class' => ["crop-{$crop_elements_name}"]], '#default_value' => !empty($edit) ? $crop_elements_value['value'] : NULL];
                     }
                     // Stock Original File Values.
                     $element['file-uri'] = ['#type' => 'value', '#value' => $variables['uri']];
                     $element['file-id'] = ['#type' => 'value', '#value' => $variables['file_id']];
                 }
             }
         }
     }
     return parent::process($element, $form_state, $form);
 }
 /**
  * Save the crop when this crop not exist.
  *
  * @param array $crop_properties
  *   The properties of the crop applied to the original image (dimensions).
  * @param array|mixed $field_value
  *   An array of values for the contained properties of image_crop widget.
  * @param string $image_style_name
  *   The machine name of ImageStyle.
  * @param ImageWidgetCrop $image_crop
  *   Instance of ImageWidgetCrop.
  */
 public function saveCrop(array $crop_properties, $field_value, $image_style_name, ImageWidgetCrop $image_crop)
 {
     // Load the style image corresponding to the crop previously.
     /** @var \Drupal\image\Entity\ImageStyle $image_style */
     $image_style = \Drupal::entityManager()->getStorage('image_style')->load($image_style_name);
     if ($crop_type = $image_crop->getCropType($image_style)) {
         $values = ['type' => $crop_type, 'entity_id' => $field_value['file-id'], 'entity_type' => 'file', 'uri' => $field_value['file-uri'], 'x' => $crop_properties['x'], 'y' => $crop_properties['y'], 'width' => $crop_properties['width'], 'height' => $crop_properties['height'], 'image_style' => $image_style_name];
         // Save crop with previous values.
         /** @var \Drupal\crop\CropInterface $crop */
         $crop = \Drupal::entityManager()->getStorage('crop')->create($values);
         $crop->save();
         // Generate the image derivate uri.
         $destination_uri = $image_style->buildUri($field_value['file-uri']);
         // Create a derivate of the original image with a good uri.
         $image_style->createDerivative($field_value['file-uri'], $destination_uri);
         // Flush the cache of this ImageStyle.
         $image_style->flush($field_value['file-uri']);
     } else {
         drupal_set_message(t("The type of crop does not exist, please check the configuration of the ImageStyle ('@imageStyle')", ['@imageStyle' => $image_style_name]), 'error');
     }
 }