Chris@0: renderer = $renderer; Chris@0: $this->imageFactory = $image_factory; Chris@0: $this->tempStore = $temp_store_factory->get('quickedit'); Chris@18: if (!$entity_display_repository) { Chris@18: @trigger_error('The entity_display.repository service must be passed to QuickEditImageController::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED); Chris@18: $entity_display_repository = \Drupal::service('entity_display.repository'); Chris@18: } Chris@18: $this->entityDisplayRepository = $entity_display_repository; Chris@18: if (!$file_system) { Chris@18: @trigger_error('The file_system service must be passed to QuickEditImageController::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED); Chris@18: $file_system = \Drupal::service('file_system'); Chris@18: } Chris@18: $this->fileSystem = $file_system; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function create(ContainerInterface $container) { Chris@0: return new static( Chris@0: $container->get('renderer'), Chris@0: $container->get('image.factory'), Chris@18: $container->get('tempstore.private'), Chris@18: $container->get('entity_display.repository'), Chris@18: $container->get('file_system') Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns JSON representing the new file upload, or validation errors. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity of which an image field is being rendered. Chris@0: * @param string $field_name Chris@0: * The name of the (image) field that is being rendered Chris@0: * @param string $langcode Chris@0: * The language code of the field that is being rendered. Chris@0: * @param string $view_mode_id Chris@0: * The view mode of the field that is being rendered. Chris@0: * Chris@0: * @return \Symfony\Component\HttpFoundation\JsonResponse Chris@0: * The JSON response. Chris@0: */ Chris@0: public function upload(EntityInterface $entity, $field_name, $langcode, $view_mode_id) { Chris@0: $field = $this->getField($entity, $field_name, $langcode); Chris@0: $field_validators = $field->getUploadValidators(); Chris@0: $field_settings = $field->getFieldDefinition()->getSettings(); Chris@0: $destination = $field->getUploadLocation(); Chris@0: Chris@0: // Add upload resolution validation. Chris@0: if ($field_settings['max_resolution'] || $field_settings['min_resolution']) { Chris@0: $field_validators['file_validate_image_resolution'] = [$field_settings['max_resolution'], $field_settings['min_resolution']]; Chris@0: } Chris@0: Chris@0: // Create the destination directory if it does not already exist. Chris@18: if (isset($destination) && !$this->fileSystem->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY)) { Chris@0: return new JsonResponse(['main_error' => $this->t('The destination directory could not be created.'), 'errors' => '']); Chris@0: } Chris@0: Chris@0: // Attempt to save the image given the field's constraints. Chris@0: $result = file_save_upload('image', $field_validators, $destination); Chris@0: if (is_array($result) && $result[0]) { Chris@0: /** @var \Drupal\file\Entity\File $file */ Chris@0: $file = $result[0]; Chris@0: $image = $this->imageFactory->get($file->getFileUri()); Chris@0: Chris@0: // Set the value in the Entity to the new file. Chris@0: /** @var \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $field_list */ Chris@0: $value = $entity->$field_name->getValue(); Chris@0: $value[0]['target_id'] = $file->id(); Chris@0: $value[0]['width'] = $image->getWidth(); Chris@0: $value[0]['height'] = $image->getHeight(); Chris@0: $entity->$field_name->setValue($value); Chris@0: Chris@0: // Render the new image using the correct formatter settings. Chris@18: $entity_view_mode_ids = array_keys($this->entityDisplayRepository->getViewModes($entity->getEntityTypeId())); Chris@0: if (in_array($view_mode_id, $entity_view_mode_ids, TRUE)) { Chris@0: $output = $entity->$field_name->view($view_mode_id); Chris@0: } Chris@0: else { Chris@0: // Each part of a custom (non-Entity Display) view mode ID is separated Chris@0: // by a dash; the first part must be the module name. Chris@0: $mode_id_parts = explode('-', $view_mode_id, 2); Chris@0: $module = reset($mode_id_parts); Chris@0: $args = [$entity, $field_name, $view_mode_id, $langcode]; Chris@0: $output = $this->moduleHandler()->invoke($module, 'quickedit_render_field', $args); Chris@0: } Chris@0: Chris@0: // Save the Entity to tempstore. Chris@0: $this->tempStore->set($entity->uuid(), $entity); Chris@0: Chris@0: $data = [ Chris@0: 'fid' => $file->id(), Chris@0: 'html' => $this->renderer->renderRoot($output), Chris@0: ]; Chris@0: return new JsonResponse($data); Chris@0: } Chris@0: else { Chris@0: // Return a JSON object containing the errors from Drupal and our Chris@0: // "main_error", which is displayed inside the dropzone area. Chris@0: $messages = StatusMessages::renderMessages('error'); Chris@0: return new JsonResponse(['errors' => $this->renderer->render($messages), 'main_error' => $this->t('The image failed validation.')]); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns JSON representing an image field's metadata. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity of which an image field is being rendered. Chris@0: * @param string $field_name Chris@0: * The name of the (image) field that is being rendered Chris@0: * @param string $langcode Chris@0: * The language code of the field that is being rendered. Chris@0: * @param string $view_mode_id Chris@0: * The view mode of the field that is being rendered. Chris@0: * Chris@0: * @return \Drupal\Core\Cache\CacheableJsonResponse Chris@0: * The JSON response. Chris@0: */ Chris@0: public function getInfo(EntityInterface $entity, $field_name, $langcode, $view_mode_id) { Chris@0: $field = $this->getField($entity, $field_name, $langcode); Chris@0: $settings = $field->getFieldDefinition()->getSettings(); Chris@0: $info = [ Chris@0: 'alt' => $field->alt, Chris@0: 'title' => $field->title, Chris@0: 'alt_field' => $settings['alt_field'], Chris@0: 'title_field' => $settings['title_field'], Chris@0: 'alt_field_required' => $settings['alt_field_required'], Chris@0: 'title_field_required' => $settings['title_field_required'], Chris@0: ]; Chris@0: $response = new CacheableJsonResponse($info); Chris@0: $response->addCacheableDependency($entity); Chris@0: return $response; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns JSON representing the current state of the field. Chris@0: * Chris@0: * @param \Drupal\Core\Entity\EntityInterface $entity Chris@0: * The entity of which an image field is being rendered. Chris@0: * @param string $field_name Chris@0: * The name of the (image) field that is being rendered Chris@0: * @param string $langcode Chris@0: * The language code of the field that is being rendered. Chris@0: * Chris@0: * @return \Drupal\image\Plugin\Field\FieldType\ImageItem Chris@0: * The field for this request. Chris@0: * Chris@0: * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException Chris@0: * Throws an exception if the request is invalid. Chris@0: */ Chris@0: protected function getField(EntityInterface $entity, $field_name, $langcode) { Chris@0: // Ensure that this is a valid Entity. Chris@0: if (!($entity instanceof ContentEntityInterface)) { Chris@0: throw new BadRequestHttpException('Requested Entity is not a Content Entity.'); Chris@0: } Chris@0: Chris@0: // Check that this field exists. Chris@0: /** @var \Drupal\Core\Field\FieldItemListInterface $field_list */ Chris@0: $field_list = $entity->getTranslation($langcode)->get($field_name); Chris@0: if (!$field_list) { Chris@0: throw new BadRequestHttpException('Requested Field does not exist.'); Chris@0: } Chris@0: Chris@0: // If the list is empty, append an empty item to use. Chris@0: if ($field_list->isEmpty()) { Chris@0: $field = $field_list->appendItem(); Chris@0: } Chris@0: // Otherwise, use the first item. Chris@0: else { Chris@0: $field = $entity->getTranslation($langcode)->get($field_name)->first(); Chris@0: } Chris@0: Chris@0: // Ensure that the field is the type we expect. Chris@0: if (!($field instanceof ImageItem)) { Chris@0: throw new BadRequestHttpException('Requested Field is not of type "image".'); Chris@0: } Chris@0: Chris@0: return $field; Chris@0: } Chris@0: Chris@0: }