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 }
|