Skip to content

Commit

Permalink
EZP-29104: Implemented UI for ImageAsset Field Type (#580)
Browse files Browse the repository at this point in the history
Co-authored-by: Dawid Parafiński <[email protected]>
Co-authored-by: Jakub Brzegowski <[email protected]>
  • Loading branch information
3 people authored and alongosz committed Sep 12, 2018
1 parent 48d3751 commit 6db696b
Show file tree
Hide file tree
Showing 27 changed files with 1,066 additions and 30 deletions.
164 changes: 164 additions & 0 deletions src/bundle/Controller/AssetController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\EzPlatformAdminUiBundle\Controller;

use Exception;
use eZ\Publish\Core\FieldType\Image\Value as ImageValue;
use eZ\Publish\Core\FieldType\ImageAsset\AssetMapper as ImageAssetMapper;
use EzSystems\EzPlatformAdminUi\Form\Data\Asset\ImageAssetUploadData;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class AssetController extends Controller
{
const CSRF_TOKEN_HEADER = 'X-CSRF-Token';

const LANGUAGE_CODE_KEY = 'languageCode';
const FILE_KEY = 'file';

/** @var \Symfony\Component\Validator\Validator\ValidatorInterface */
private $validator;

/** @var \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface */
private $csrfTokenManager;

/** @var \eZ\Publish\Core\FieldType\ImageAsset\AssetMapper */
private $imageAssetMapper;

/** @var \Symfony\Component\Translation\TranslatorInterface */
private $translator;

/**
* @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator
* @param \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface $csrfTokenManager
* @param \eZ\Publish\Core\FieldType\ImageAsset\AssetMapper $imageAssetMapper
* @param \Symfony\Component\Translation\TranslatorInterface $translator
*/
public function __construct(
ValidatorInterface $validator,
CsrfTokenManagerInterface $csrfTokenManager,
ImageAssetMapper $imageAssetMapper,
TranslatorInterface $translator)
{
$this->validator = $validator;
$this->csrfTokenManager = $csrfTokenManager;
$this->imageAssetMapper = $imageAssetMapper;
$this->translator = $translator;
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentType
*/
public function uploadImageAction(Request $request): Response
{
if ($this->isValidCsrfToken($request)) {
$data = new ImageAssetUploadData(
$request->files->get(self::FILE_KEY),
$request->request->get(self::LANGUAGE_CODE_KEY)
);

$errors = $this->validator->validate($data);
if ($errors->count() === 0) {
try {
$file = $data->getFile();

$content = $this->imageAssetMapper->createAsset(
$file->getClientOriginalName(),
new ImageValue([
'path' => $file->getRealPath(),
'fileSize' => $file->getSize(),
'fileName' => $file->getClientOriginalName(),
'alternativeText' => null,
]),
$data->getLanguageCode()
);

return new JsonResponse([
'destinationContent' => [
'id' => $content->contentInfo->id,
'name' => $content->getName(),
'locationId' => $content->contentInfo->mainLocationId,
],
'value' => $this->imageAssetMapper->getAssetValue($content),
]);
} catch (Exception $e) {
return $this->createGenericErrorResponse($e->getMessage());
}
} else {
return $this->createInvalidInputResponse($errors);
}
}

return $this->createInvalidCsrfResponse();
}

/**
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
private function createInvalidCsrfResponse(): JsonResponse
{
$errorMessage = $this->translator->trans(
/** @Desc("Missing or invalid CSRF token") */ 'asset.upload.invalid_csrf', [], 'assets'
);

return $this->createGenericErrorResponse($errorMessage);
}

/**
* @param \Symfony\Component\Validator\ConstraintViolationListInterface $errors
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
private function createInvalidInputResponse(ConstraintViolationListInterface $errors): JsonResponse
{
$errorMessages = [];
foreach ($errors as $error) {
$errorMessages[] = $error->getMessage();
}

return $this->createGenericErrorResponse(implode(', ', $errorMessages));
}

/**
* @param string $errorMessage
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
private function createGenericErrorResponse(string $errorMessage): JsonResponse
{
return new JsonResponse([
'status' => 'failed',
'error' => $errorMessage,
]);
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return bool
*/
private function isValidCsrfToken(Request $request): bool
{
$csrfTokenValue = $request->headers->get(self::CSRF_TOKEN_HEADER);

return $this->csrfTokenManager->isTokenValid(
new CsrfToken('authenticate', $csrfTokenValue)
);
}
}
1 change: 1 addition & 0 deletions src/bundle/Resources/config/bazinga_js_translation.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
active_domains:
- 'universal_discovery_widget'
- 'alloy_editor'
- 'fieldtypes_edit'
8 changes: 8 additions & 0 deletions src/bundle/Resources/config/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -778,3 +778,11 @@ ezplatform.notifications.mark_as_read:
methods: [GET]
requirements:
notificationId: '\d+'

ezplatform.asset.upload_image:
path: /asset/image
options:
expose: true
defaults:
_controller: 'EzPlatformAdminUiBundle:Asset:uploadImage'
methods: [POST]
3 changes: 3 additions & 0 deletions src/bundle/Resources/config/services/controllers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ services:
arguments:
$defaultPaginationLimit: '$pagination.bookmark_limit$'

EzSystems\EzPlatformAdminUiBundle\Controller\AssetController:
parent: EzSystems\EzPlatformAdminUiBundle\Controller\Controller

EzSystems\EzPlatformAdminUiBundle\Controller\NotificationController:
parent: EzSystems\EzPlatformAdminUiBundle\Controller\Controller
arguments:
Expand Down
4 changes: 4 additions & 0 deletions src/bundle/Resources/config/services/ui_config/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ services:
tags:
- { name: ezplatform.admin_ui.config_provider, key: 'richTextCustomTags' }

EzSystems\EzPlatformAdminUi\UI\Config\Provider\FieldType\ImageAsset\Mapping:
tags:
- { name: ezplatform.admin_ui.config_provider, key: 'imageAssetMapping' }

# Notifications
EzSystems\EzPlatformAdminUi\UI\Config\Provider\Notifications:
tags:
Expand Down
3 changes: 3 additions & 0 deletions src/bundle/Resources/config/universal_discovery_widget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ system:
multiple: false
content_on_the_fly:
allowed_content_types: ['image']
image_asset:
multiple: false
visible_tabs: ['browse', 'search', 'bookmarks']
5 changes: 5 additions & 0 deletions src/bundle/Resources/config/views.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ system:
controller: 'EzPlatformAdminUiBundle:ContentView:locationView'
template: '@ezdesign\fieldtypes\preview\ezobjectrelationlist_row.html.twig'
match: true
preview_ezimageasset:
default:
controller: 'EzPlatformAdminUiBundle:ContentView:locationView'
template: '@ezdesign\fieldtypes\preview\ezimageasset.html.twig'
match: true

content_edit_view:
full:
Expand Down
Loading

0 comments on commit 6db696b

Please sign in to comment.