Chris@0: renderer = $renderer; Chris@0: $this->imageFactory = $image_factory; Chris@0: $this->tempStore = $temp_store_factory->get('quickedit'); 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@0: $container->get('user.private_tempstore') 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@0: if (isset($destination) && !file_prepare_directory($destination, FILE_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@0: $entity_view_mode_ids = array_keys($this->entityManager()->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: }