annotate core/modules/image/src/Controller/QuickEditImageController.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children 12f9dff5fda9
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\image\Controller;
Chris@0 4
Chris@0 5 use Drupal\Core\Cache\CacheableJsonResponse;
Chris@0 6 use Drupal\Core\Controller\ControllerBase;
Chris@0 7 use Drupal\Core\Entity\ContentEntityInterface;
Chris@0 8 use Drupal\Core\Entity\EntityInterface;
Chris@0 9 use Drupal\Core\Image\ImageFactory;
Chris@0 10 use Drupal\Core\Render\Element\StatusMessages;
Chris@0 11 use Drupal\Core\Render\RendererInterface;
Chris@0 12 use Drupal\image\Plugin\Field\FieldType\ImageItem;
Chris@0 13 use Drupal\Core\TempStore\PrivateTempStoreFactory;
Chris@0 14 use Symfony\Component\DependencyInjection\ContainerInterface;
Chris@0 15 use Symfony\Component\HttpFoundation\JsonResponse;
Chris@0 16 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
Chris@0 17
Chris@0 18 /**
Chris@0 19 * Returns responses for our image routes.
Chris@0 20 */
Chris@0 21 class QuickEditImageController extends ControllerBase {
Chris@0 22
Chris@0 23 /**
Chris@0 24 * Stores The Quick Edit tempstore.
Chris@0 25 *
Chris@0 26 * @var \Drupal\Core\TempStore\PrivateTempStore
Chris@0 27 */
Chris@0 28 protected $tempStore;
Chris@0 29
Chris@0 30 /**
Chris@0 31 * The renderer.
Chris@0 32 *
Chris@0 33 * @var \Drupal\Core\Render\RendererInterface
Chris@0 34 */
Chris@0 35 protected $renderer;
Chris@0 36
Chris@0 37 /**
Chris@0 38 * The image factory.
Chris@0 39 *
Chris@0 40 * @var \Drupal\Core\Image\ImageFactory
Chris@0 41 */
Chris@0 42 protected $imageFactory;
Chris@0 43
Chris@0 44 /**
Chris@0 45 * Constructs a new QuickEditImageController.
Chris@0 46 *
Chris@0 47 * @param \Drupal\Core\Render\RendererInterface $renderer
Chris@0 48 * The renderer.
Chris@0 49 * @param \Drupal\Core\Image\ImageFactory $image_factory
Chris@0 50 * The image factory.
Chris@0 51 * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
Chris@0 52 * The tempstore factory.
Chris@0 53 */
Chris@0 54 public function __construct(RendererInterface $renderer, ImageFactory $image_factory, PrivateTempStoreFactory $temp_store_factory) {
Chris@0 55 $this->renderer = $renderer;
Chris@0 56 $this->imageFactory = $image_factory;
Chris@0 57 $this->tempStore = $temp_store_factory->get('quickedit');
Chris@0 58 }
Chris@0 59
Chris@0 60 /**
Chris@0 61 * {@inheritdoc}
Chris@0 62 */
Chris@0 63 public static function create(ContainerInterface $container) {
Chris@0 64 return new static(
Chris@0 65 $container->get('renderer'),
Chris@0 66 $container->get('image.factory'),
Chris@0 67 $container->get('tempstore.private')
Chris@0 68 );
Chris@0 69 }
Chris@0 70
Chris@0 71 /**
Chris@0 72 * Returns JSON representing the new file upload, or validation errors.
Chris@0 73 *
Chris@0 74 * @param \Drupal\Core\Entity\EntityInterface $entity
Chris@0 75 * The entity of which an image field is being rendered.
Chris@0 76 * @param string $field_name
Chris@0 77 * The name of the (image) field that is being rendered
Chris@0 78 * @param string $langcode
Chris@0 79 * The language code of the field that is being rendered.
Chris@0 80 * @param string $view_mode_id
Chris@0 81 * The view mode of the field that is being rendered.
Chris@0 82 *
Chris@0 83 * @return \Symfony\Component\HttpFoundation\JsonResponse
Chris@0 84 * The JSON response.
Chris@0 85 */
Chris@0 86 public function upload(EntityInterface $entity, $field_name, $langcode, $view_mode_id) {
Chris@0 87 $field = $this->getField($entity, $field_name, $langcode);
Chris@0 88 $field_validators = $field->getUploadValidators();
Chris@0 89 $field_settings = $field->getFieldDefinition()->getSettings();
Chris@0 90 $destination = $field->getUploadLocation();
Chris@0 91
Chris@0 92 // Add upload resolution validation.
Chris@0 93 if ($field_settings['max_resolution'] || $field_settings['min_resolution']) {
Chris@0 94 $field_validators['file_validate_image_resolution'] = [$field_settings['max_resolution'], $field_settings['min_resolution']];
Chris@0 95 }
Chris@0 96
Chris@0 97 // Create the destination directory if it does not already exist.
Chris@0 98 if (isset($destination) && !file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
Chris@0 99 return new JsonResponse(['main_error' => $this->t('The destination directory could not be created.'), 'errors' => '']);
Chris@0 100 }
Chris@0 101
Chris@0 102 // Attempt to save the image given the field's constraints.
Chris@0 103 $result = file_save_upload('image', $field_validators, $destination);
Chris@0 104 if (is_array($result) && $result[0]) {
Chris@0 105 /** @var \Drupal\file\Entity\File $file */
Chris@0 106 $file = $result[0];
Chris@0 107 $image = $this->imageFactory->get($file->getFileUri());
Chris@0 108
Chris@0 109 // Set the value in the Entity to the new file.
Chris@0 110 /** @var \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $field_list */
Chris@0 111 $value = $entity->$field_name->getValue();
Chris@0 112 $value[0]['target_id'] = $file->id();
Chris@0 113 $value[0]['width'] = $image->getWidth();
Chris@0 114 $value[0]['height'] = $image->getHeight();
Chris@0 115 $entity->$field_name->setValue($value);
Chris@0 116
Chris@0 117 // Render the new image using the correct formatter settings.
Chris@0 118 $entity_view_mode_ids = array_keys($this->entityManager()->getViewModes($entity->getEntityTypeId()));
Chris@0 119 if (in_array($view_mode_id, $entity_view_mode_ids, TRUE)) {
Chris@0 120 $output = $entity->$field_name->view($view_mode_id);
Chris@0 121 }
Chris@0 122 else {
Chris@0 123 // Each part of a custom (non-Entity Display) view mode ID is separated
Chris@0 124 // by a dash; the first part must be the module name.
Chris@0 125 $mode_id_parts = explode('-', $view_mode_id, 2);
Chris@0 126 $module = reset($mode_id_parts);
Chris@0 127 $args = [$entity, $field_name, $view_mode_id, $langcode];
Chris@0 128 $output = $this->moduleHandler()->invoke($module, 'quickedit_render_field', $args);
Chris@0 129 }
Chris@0 130
Chris@0 131 // Save the Entity to tempstore.
Chris@0 132 $this->tempStore->set($entity->uuid(), $entity);
Chris@0 133
Chris@0 134 $data = [
Chris@0 135 'fid' => $file->id(),
Chris@0 136 'html' => $this->renderer->renderRoot($output),
Chris@0 137 ];
Chris@0 138 return new JsonResponse($data);
Chris@0 139 }
Chris@0 140 else {
Chris@0 141 // Return a JSON object containing the errors from Drupal and our
Chris@0 142 // "main_error", which is displayed inside the dropzone area.
Chris@0 143 $messages = StatusMessages::renderMessages('error');
Chris@0 144 return new JsonResponse(['errors' => $this->renderer->render($messages), 'main_error' => $this->t('The image failed validation.')]);
Chris@0 145 }
Chris@0 146 }
Chris@0 147
Chris@0 148 /**
Chris@0 149 * Returns JSON representing an image field's metadata.
Chris@0 150 *
Chris@0 151 * @param \Drupal\Core\Entity\EntityInterface $entity
Chris@0 152 * The entity of which an image field is being rendered.
Chris@0 153 * @param string $field_name
Chris@0 154 * The name of the (image) field that is being rendered
Chris@0 155 * @param string $langcode
Chris@0 156 * The language code of the field that is being rendered.
Chris@0 157 * @param string $view_mode_id
Chris@0 158 * The view mode of the field that is being rendered.
Chris@0 159 *
Chris@0 160 * @return \Drupal\Core\Cache\CacheableJsonResponse
Chris@0 161 * The JSON response.
Chris@0 162 */
Chris@0 163 public function getInfo(EntityInterface $entity, $field_name, $langcode, $view_mode_id) {
Chris@0 164 $field = $this->getField($entity, $field_name, $langcode);
Chris@0 165 $settings = $field->getFieldDefinition()->getSettings();
Chris@0 166 $info = [
Chris@0 167 'alt' => $field->alt,
Chris@0 168 'title' => $field->title,
Chris@0 169 'alt_field' => $settings['alt_field'],
Chris@0 170 'title_field' => $settings['title_field'],
Chris@0 171 'alt_field_required' => $settings['alt_field_required'],
Chris@0 172 'title_field_required' => $settings['title_field_required'],
Chris@0 173 ];
Chris@0 174 $response = new CacheableJsonResponse($info);
Chris@0 175 $response->addCacheableDependency($entity);
Chris@0 176 return $response;
Chris@0 177 }
Chris@0 178
Chris@0 179 /**
Chris@0 180 * Returns JSON representing the current state of the field.
Chris@0 181 *
Chris@0 182 * @param \Drupal\Core\Entity\EntityInterface $entity
Chris@0 183 * The entity of which an image field is being rendered.
Chris@0 184 * @param string $field_name
Chris@0 185 * The name of the (image) field that is being rendered
Chris@0 186 * @param string $langcode
Chris@0 187 * The language code of the field that is being rendered.
Chris@0 188 *
Chris@0 189 * @return \Drupal\image\Plugin\Field\FieldType\ImageItem
Chris@0 190 * The field for this request.
Chris@0 191 *
Chris@0 192 * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
Chris@0 193 * Throws an exception if the request is invalid.
Chris@0 194 */
Chris@0 195 protected function getField(EntityInterface $entity, $field_name, $langcode) {
Chris@0 196 // Ensure that this is a valid Entity.
Chris@0 197 if (!($entity instanceof ContentEntityInterface)) {
Chris@0 198 throw new BadRequestHttpException('Requested Entity is not a Content Entity.');
Chris@0 199 }
Chris@0 200
Chris@0 201 // Check that this field exists.
Chris@0 202 /** @var \Drupal\Core\Field\FieldItemListInterface $field_list */
Chris@0 203 $field_list = $entity->getTranslation($langcode)->get($field_name);
Chris@0 204 if (!$field_list) {
Chris@0 205 throw new BadRequestHttpException('Requested Field does not exist.');
Chris@0 206 }
Chris@0 207
Chris@0 208 // If the list is empty, append an empty item to use.
Chris@0 209 if ($field_list->isEmpty()) {
Chris@0 210 $field = $field_list->appendItem();
Chris@0 211 }
Chris@0 212 // Otherwise, use the first item.
Chris@0 213 else {
Chris@0 214 $field = $entity->getTranslation($langcode)->get($field_name)->first();
Chris@0 215 }
Chris@0 216
Chris@0 217 // Ensure that the field is the type we expect.
Chris@0 218 if (!($field instanceof ImageItem)) {
Chris@0 219 throw new BadRequestHttpException('Requested Field is not of type "image".');
Chris@0 220 }
Chris@0 221
Chris@0 222 return $field;
Chris@0 223 }
Chris@0 224
Chris@0 225 }