Loading js/api-fetch.es6.js +5 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ */ function errorHandler(errorResponse, reject, fallbackMessage = null) { let errorMessage; let rawHTML = false; if (errorResponse.responseJSON) { const responseJSON = errorResponse.responseJSON; if (typeof responseJSON.error === 'string') { Loading @@ -50,6 +51,9 @@ // ExceptionJsonSubscriber error handler. errorMessage = responseJSON.message; } if (errorMessage && responseJSON.rawHTML) { rawHTML = responseJSON.rawHTML; } } if (!errorMessage && fallbackMessage) { Loading @@ -57,7 +61,7 @@ } if (errorMessage) { Drupal.notifyError(errorMessage); Drupal.notifyError(errorMessage, rawHTML); } else { // eslint-disable-next-line no-console console.warn( Loading js/api-fetch.js +5 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ var fallbackMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var errorMessage = void 0; var rawHTML = false; if (errorResponse.responseJSON) { var responseJSON = errorResponse.responseJSON; if (typeof responseJSON.error === 'string') { Loading @@ -41,6 +42,9 @@ } else if (typeof responseJSON.message === 'string') { errorMessage = responseJSON.message; } if (errorMessage && responseJSON.rawHTML) { rawHTML = responseJSON.rawHTML; } } if (!errorMessage && fallbackMessage) { Loading @@ -48,7 +52,7 @@ } if (errorMessage) { Drupal.notifyError(errorMessage); Drupal.notifyError(errorMessage, rawHTML); } else { console.warn('API error: unexpected error message: ' + JSON.stringify(errorResponse)); } Loading js/gutenberg.es6.js +6 −2 Original line number Diff line number Diff line Loading @@ -41,24 +41,28 @@ * Display error message. * * @param {string} message Notice message. * @param {boolean} rawHTML Render as HTML. * * @return {Object} Action object. */ Drupal.notifyError = message => Drupal.notifyError = (message, rawHTML = false) => wp.data.dispatch('core/notices').createErrorNotice(message, { isDismissible: true, __unstableHTML: rawHTML, }); /** * Display success message. * * @param {string} message Notice message. * @param {boolean} rawHTML Render as HTML. * * @return {Object} Action object. */ Drupal.notifySuccess = message => Drupal.notifySuccess = (message, rawHTML = false) => wp.data.dispatch('core/notices').createSuccessNotice(message, { isDismissible: true, __unstableHTML: rawHTML, }); /** Loading js/gutenberg.js +6 −2 Original line number Diff line number Diff line Loading @@ -28,14 +28,18 @@ function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, a }; Drupal.notifyError = function (message) { var rawHTML = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return wp.data.dispatch('core/notices').createErrorNotice(message, { isDismissible: true isDismissible: true, __unstableHTML: rawHTML }); }; Drupal.notifySuccess = function (message) { var rawHTML = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return wp.data.dispatch('core/notices').createSuccessNotice(message, { isDismissible: true isDismissible: true, __unstableHTML: rawHTML }); }; Loading src/Controller/MediaController.php +76 −8 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ namespace Drupal\gutenberg\Controller; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Render\RendererInterface; use Drupal\file\Entity\File; use Drupal\gutenberg\MediaSelectionProcessor\MediaSelectionProcessorManagerInterface; use Drupal\gutenberg\Service\FileEntityNotFoundException; Loading @@ -14,9 +15,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Drupal\editor\Entity\Editor; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; Loading @@ -39,6 +38,13 @@ class MediaController extends ControllerBase { */ protected $mediaSelectionProcessorManager; /** * Drupal\Core\Render\RendererInterface instance. * * @var \Drupal\Core\Render\RendererInterface */ protected $renderer; /** * MediaController constructor. * Loading @@ -46,10 +52,17 @@ class MediaController extends ControllerBase { * The media service. * @param \Drupal\gutenberg\MediaSelectionProcessor\MediaSelectionProcessorManagerInterface $media_selection_processor_manager * The media selection processor manager. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. */ public function __construct(MediaService $media_service, MediaSelectionProcessorManagerInterface $media_selection_processor_manager) { public function __construct( MediaService $media_service, MediaSelectionProcessorManagerInterface $media_selection_processor_manager, RendererInterface $renderer ) { $this->mediaService = $media_service; $this->mediaSelectionProcessorManager = $media_selection_processor_manager; $this->renderer = $renderer; } /** Loading @@ -58,7 +71,8 @@ class MediaController extends ControllerBase { public static function create(ContainerInterface $container) { return new static( $container->get('gutenberg.media_service'), $container->get('gutenberg.media_selection_processor_manager') $container->get('gutenberg.media_selection_processor_manager'), $container->get('renderer') ); } Loading Loading @@ -165,14 +179,18 @@ class MediaController extends ControllerBase { $uploaded_file = $files['fid'] ?? NULL; if (!$uploaded_file instanceof UploadedFile) { throw new UnprocessableEntityHttpException('Invalid file has been uploaded.'); throw new UnprocessableEntityHttpException('The uploaded file is invalid.'); } try { return new JsonResponse($this->mediaService->processMediaEntityUpload($uploaded_file, $editor)); return new JsonResponse($this->mediaService->processMediaEntityUpload('fid', $uploaded_file, $editor)); } catch (\Exception $exception) { throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $exception->getMessage(), $exception); // DefaultExceptionSubscriber::on4xx only normalizes 4xx client errors. return new JsonResponse( $this->getErrorResponse($exception->getMessage()), JsonResponse::HTTP_INTERNAL_SERVER_ERROR ); } } Loading Loading @@ -248,7 +266,7 @@ class MediaController extends ControllerBase { $this->mediaService->updateMediaData($fid, $data); } catch (\Throwable $exception) { throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Data could not be updated'); return new JsonResponse(['message' => 'Data could not be updated'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR); } return new JsonResponse(['status' => 'ok']); Loading @@ -269,4 +287,54 @@ class MediaController extends ControllerBase { ); } /** * Returns the error response including status messages. * * @param string $error * The original error. * * @return array * JSON response to return to the client. */ protected function getErrorResponse($error) { $messages = $this->messenger()->deleteAll(); if ($messages) { // Display the status messages along with the original error. // @todo (HACKY) Leverage AjaxRenderer + "_wrapper_format=drupal_ajax" to handle this instead. $message_entries = []; foreach (['error', 'warning', 'status'] as $status) { if (isset($messages[$status])) { /* @noinspection SlowArrayOperationsInLoopInspection */ $message_entries = array_merge($message_entries, $messages[$status]); } } if ($message_entries) { $render = [ '#type' => 'inline_template', '#template' => '<div class="gutenberg-error--initial">{{ error }}</div><div class="gutenberg-error--other-messages">{{ messages }}</div>', '#context' => [ 'error' => $error, 'messages' => [ '#theme' => 'item_list', '#list_type' => 'ul', '#items' => $message_entries, ], ], ]; $output = $this->renderer->renderRoot($render); return [ 'error' => $output, // Render as Raw HTML. 'rawHTML' => TRUE, ]; } } return [ 'error' => $error, ]; } } Loading
js/api-fetch.es6.js +5 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ */ function errorHandler(errorResponse, reject, fallbackMessage = null) { let errorMessage; let rawHTML = false; if (errorResponse.responseJSON) { const responseJSON = errorResponse.responseJSON; if (typeof responseJSON.error === 'string') { Loading @@ -50,6 +51,9 @@ // ExceptionJsonSubscriber error handler. errorMessage = responseJSON.message; } if (errorMessage && responseJSON.rawHTML) { rawHTML = responseJSON.rawHTML; } } if (!errorMessage && fallbackMessage) { Loading @@ -57,7 +61,7 @@ } if (errorMessage) { Drupal.notifyError(errorMessage); Drupal.notifyError(errorMessage, rawHTML); } else { // eslint-disable-next-line no-console console.warn( Loading
js/api-fetch.js +5 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ var fallbackMessage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var errorMessage = void 0; var rawHTML = false; if (errorResponse.responseJSON) { var responseJSON = errorResponse.responseJSON; if (typeof responseJSON.error === 'string') { Loading @@ -41,6 +42,9 @@ } else if (typeof responseJSON.message === 'string') { errorMessage = responseJSON.message; } if (errorMessage && responseJSON.rawHTML) { rawHTML = responseJSON.rawHTML; } } if (!errorMessage && fallbackMessage) { Loading @@ -48,7 +52,7 @@ } if (errorMessage) { Drupal.notifyError(errorMessage); Drupal.notifyError(errorMessage, rawHTML); } else { console.warn('API error: unexpected error message: ' + JSON.stringify(errorResponse)); } Loading
js/gutenberg.es6.js +6 −2 Original line number Diff line number Diff line Loading @@ -41,24 +41,28 @@ * Display error message. * * @param {string} message Notice message. * @param {boolean} rawHTML Render as HTML. * * @return {Object} Action object. */ Drupal.notifyError = message => Drupal.notifyError = (message, rawHTML = false) => wp.data.dispatch('core/notices').createErrorNotice(message, { isDismissible: true, __unstableHTML: rawHTML, }); /** * Display success message. * * @param {string} message Notice message. * @param {boolean} rawHTML Render as HTML. * * @return {Object} Action object. */ Drupal.notifySuccess = message => Drupal.notifySuccess = (message, rawHTML = false) => wp.data.dispatch('core/notices').createSuccessNotice(message, { isDismissible: true, __unstableHTML: rawHTML, }); /** Loading
js/gutenberg.js +6 −2 Original line number Diff line number Diff line Loading @@ -28,14 +28,18 @@ function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, a }; Drupal.notifyError = function (message) { var rawHTML = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return wp.data.dispatch('core/notices').createErrorNotice(message, { isDismissible: true isDismissible: true, __unstableHTML: rawHTML }); }; Drupal.notifySuccess = function (message) { var rawHTML = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; return wp.data.dispatch('core/notices').createSuccessNotice(message, { isDismissible: true isDismissible: true, __unstableHTML: rawHTML }); }; Loading
src/Controller/MediaController.php +76 −8 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ namespace Drupal\gutenberg\Controller; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Render\RendererInterface; use Drupal\file\Entity\File; use Drupal\gutenberg\MediaSelectionProcessor\MediaSelectionProcessorManagerInterface; use Drupal\gutenberg\Service\FileEntityNotFoundException; Loading @@ -14,9 +15,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Drupal\editor\Entity\Editor; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; Loading @@ -39,6 +38,13 @@ class MediaController extends ControllerBase { */ protected $mediaSelectionProcessorManager; /** * Drupal\Core\Render\RendererInterface instance. * * @var \Drupal\Core\Render\RendererInterface */ protected $renderer; /** * MediaController constructor. * Loading @@ -46,10 +52,17 @@ class MediaController extends ControllerBase { * The media service. * @param \Drupal\gutenberg\MediaSelectionProcessor\MediaSelectionProcessorManagerInterface $media_selection_processor_manager * The media selection processor manager. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. */ public function __construct(MediaService $media_service, MediaSelectionProcessorManagerInterface $media_selection_processor_manager) { public function __construct( MediaService $media_service, MediaSelectionProcessorManagerInterface $media_selection_processor_manager, RendererInterface $renderer ) { $this->mediaService = $media_service; $this->mediaSelectionProcessorManager = $media_selection_processor_manager; $this->renderer = $renderer; } /** Loading @@ -58,7 +71,8 @@ class MediaController extends ControllerBase { public static function create(ContainerInterface $container) { return new static( $container->get('gutenberg.media_service'), $container->get('gutenberg.media_selection_processor_manager') $container->get('gutenberg.media_selection_processor_manager'), $container->get('renderer') ); } Loading Loading @@ -165,14 +179,18 @@ class MediaController extends ControllerBase { $uploaded_file = $files['fid'] ?? NULL; if (!$uploaded_file instanceof UploadedFile) { throw new UnprocessableEntityHttpException('Invalid file has been uploaded.'); throw new UnprocessableEntityHttpException('The uploaded file is invalid.'); } try { return new JsonResponse($this->mediaService->processMediaEntityUpload($uploaded_file, $editor)); return new JsonResponse($this->mediaService->processMediaEntityUpload('fid', $uploaded_file, $editor)); } catch (\Exception $exception) { throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, $exception->getMessage(), $exception); // DefaultExceptionSubscriber::on4xx only normalizes 4xx client errors. return new JsonResponse( $this->getErrorResponse($exception->getMessage()), JsonResponse::HTTP_INTERNAL_SERVER_ERROR ); } } Loading Loading @@ -248,7 +266,7 @@ class MediaController extends ControllerBase { $this->mediaService->updateMediaData($fid, $data); } catch (\Throwable $exception) { throw new HttpException(Response::HTTP_INTERNAL_SERVER_ERROR, 'Data could not be updated'); return new JsonResponse(['message' => 'Data could not be updated'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR); } return new JsonResponse(['status' => 'ok']); Loading @@ -269,4 +287,54 @@ class MediaController extends ControllerBase { ); } /** * Returns the error response including status messages. * * @param string $error * The original error. * * @return array * JSON response to return to the client. */ protected function getErrorResponse($error) { $messages = $this->messenger()->deleteAll(); if ($messages) { // Display the status messages along with the original error. // @todo (HACKY) Leverage AjaxRenderer + "_wrapper_format=drupal_ajax" to handle this instead. $message_entries = []; foreach (['error', 'warning', 'status'] as $status) { if (isset($messages[$status])) { /* @noinspection SlowArrayOperationsInLoopInspection */ $message_entries = array_merge($message_entries, $messages[$status]); } } if ($message_entries) { $render = [ '#type' => 'inline_template', '#template' => '<div class="gutenberg-error--initial">{{ error }}</div><div class="gutenberg-error--other-messages">{{ messages }}</div>', '#context' => [ 'error' => $error, 'messages' => [ '#theme' => 'item_list', '#list_type' => 'ul', '#items' => $message_entries, ], ], ]; $output = $this->renderer->renderRoot($render); return [ 'error' => $output, // Render as Raw HTML. 'rawHTML' => TRUE, ]; } } return [ 'error' => $error, ]; } }