Skip to content

Commit

Permalink
Add not found exception (#47)
Browse files Browse the repository at this point in the history
* Add not found exception for get by id

* Remove nullable

* Apply php-cs-fixer changes

* Add null to phpdoc type

---------

Co-authored-by: mattamon <mattamon@users.noreply.github.com>
  • Loading branch information
mattamon and mattamon authored Apr 30, 2024
1 parent 4132aa3 commit 28b5e1e
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 25 deletions.
4 changes: 3 additions & 1 deletion src/Asset/Controller/GetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Path\IdParameter;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Content\OneOfAssetJson;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\MethodNotAllowedResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\NotFoundResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnauthorizedResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnprocessableContentResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnsupportedMediaTypeResponse;
Expand Down Expand Up @@ -55,10 +56,11 @@ public function __construct(
)]
#[IdParameter(type: 'asset')]
#[SuccessResponse(
description: 'Paginated assets with total count as header param',
description: 'One of asset types',
content: new OneOfAssetJson()
)]
#[UnauthorizedResponse]
#[NotFoundResponse]
#[MethodNotAllowedResponse]
#[UnsupportedMediaTypeResponse]
#[UnprocessableContentResponse]
Expand Down
12 changes: 7 additions & 5 deletions src/DataIndex/Adapter/AssetSearchAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Pimcore\Bundle\StudioBackendBundle\DataIndex\AssetSearchResult;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\Hydrator\AssetHydratorServiceInterface;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface;
use Pimcore\Bundle\StudioBackendBundle\Exception\ElementNotFoundException;

final readonly class AssetSearchAdapter implements AssetSearchAdapterInterface
{
Expand Down Expand Up @@ -53,13 +54,14 @@ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult
/**
* @throws Exception
*/
public function getAssetById(int $id): ?Asset
public function getAssetById(int $id): Asset
{
$searchResult = $this->searchService->byId($id);
if ($searchResult === null) {
return null;
$asset = $this->searchService->byId($id);

if (!$asset) {
throw new ElementNotFoundException($id);
}

return $this->assetHydratorService->hydrate($searchResult);
return $this->assetHydratorService->hydrate($asset);
}
}
2 changes: 1 addition & 1 deletion src/DataIndex/Adapter/AssetSearchAdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ interface AssetSearchAdapterInterface
{
public function searchAssets(QueryInterface $assetQuery): AssetSearchResult;

public function getAssetById(int $id): ?Asset;
public function getAssetById(int $id): Asset;
}
23 changes: 14 additions & 9 deletions src/DataIndex/Adapter/DataObjectSearchAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
use Pimcore\Bundle\StudioBackendBundle\DataIndex\DataObjectSearchResult;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Schema\DataObject;
use Pimcore\Bundle\StudioBackendBundle\Exception\ElementNotFoundException;
use Pimcore\Bundle\StudioBackendBundle\Exception\InvalidSearchException;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Model\Element\ElementInterface;

final readonly class DataObjectSearchAdapter implements DataObjectSearchAdapterInterface
{
Expand Down Expand Up @@ -52,12 +52,10 @@ public function searchDataObjects(QueryInterface $dataObjectQuery): DataObjectSe
);
}
$searchResult = $this->searchService->search($search);
$result = [];
foreach($searchResult->getIds() as $id) {
/** @var Concrete $dataObject */
$dataObject = $this->getDataObjectById($id);
$result[] = new DataObject($dataObject->getId(), $dataObject->getClassName());
}

$result = array_map(function ($id) {
return $this->getDataObjectById($id);
}, $searchResult->getIds());

return new DataObjectSearchResult(
$result,
Expand All @@ -67,8 +65,15 @@ public function searchDataObjects(QueryInterface $dataObjectQuery): DataObjectSe
);
}

public function getDataObjectById(int $id): ?ElementInterface
public function getDataObjectById(int $id): DataObject
{
return $this->serviceResolver->getElementById('object', $id);
/** @var null|Concrete $dataObject */
$dataObject = $this->serviceResolver->getElementById('object', $id);

if (!$dataObject) {
throw new ElementNotFoundException($id);
}

return new DataObject($dataObject->getId(), $dataObject->getClassName());
}
}
4 changes: 2 additions & 2 deletions src/DataIndex/Adapter/DataObjectSearchAdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

use Pimcore\Bundle\StudioBackendBundle\DataIndex\DataObjectSearchResult;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface;
use Pimcore\Model\Element\ElementInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Schema\DataObject;

interface DataObjectSearchAdapterInterface
{
public function searchDataObjects(QueryInterface $dataObjectQuery): DataObjectSearchResult;

public function getDataObjectById(int $id): ?ElementInterface;
public function getDataObjectById(int $id): DataObject;
}
2 changes: 1 addition & 1 deletion src/DataIndex/AssetSearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function searchAssets(QueryInterface $assetQuery): AssetSearchResult
return $this->assetSearchAdapter->searchAssets($assetQuery);
}

public function getAssetById(int $id): Asset|Archive|Audio|Document|Folder|Image|Text|Unknown|Video|null
public function getAssetById(int $id): Asset|Archive|Audio|Document|Folder|Image|Text|Unknown|Video
{
return $this->assetSearchAdapter->getAssetById($id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/DataIndex/AssetSearchServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ interface AssetSearchServiceInterface
{
public function searchAssets(QueryInterface $assetQuery): AssetSearchResult;

public function getAssetById(int $id): Asset|Archive|Audio|Document|Folder|Image|Text|Unknown|Video|null;
public function getAssetById(int $id): Asset|Archive|Audio|Document|Folder|Image|Text|Unknown|Video;
}
6 changes: 3 additions & 3 deletions src/DataIndex/DataObjectSearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use Pimcore\Bundle\StudioBackendBundle\DataIndex\Adapter\DataObjectSearchAdapterInterface;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Schema\DataObject;

final readonly class DataObjectSearchService implements DataObjectSearchServiceInterface
{
Expand All @@ -31,8 +31,8 @@ public function searchDataObjects(QueryInterface $dataObjectQuery): DataObjectSe
return $this->dataObjectSearchAdapter->searchDataObjects($dataObjectQuery);
}

public function getDataObjectById(int $id): Concrete|null
public function getDataObjectById(int $id): DataObject
{
return null;
return $this->dataObjectSearchAdapter->getDataObjectById($id);
}
}
4 changes: 2 additions & 2 deletions src/DataIndex/DataObjectSearchServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
namespace Pimcore\Bundle\StudioBackendBundle\DataIndex;

use Pimcore\Bundle\StudioBackendBundle\DataIndex\Query\QueryInterface;
use Pimcore\Model\DataObject\Concrete;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Schema\DataObject;

interface DataObjectSearchServiceInterface
{
public function searchDataObjects(QueryInterface $dataObjectQuery): DataObjectSearchResult;

public function getDataObjectById(int $id): Concrete|null;
public function getDataObjectById(int $id): DataObject;
}
72 changes: 72 additions & 0 deletions src/DataObject/Controller/GetController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\StudioBackendBundle\DataObject\Controller;

use OpenApi\Attributes\Get;
use OpenApi\Attributes\JsonContent;
use Pimcore\Bundle\StudioBackendBundle\Controller\AbstractApiController;
use Pimcore\Bundle\StudioBackendBundle\DataIndex\DataObjectSearchServiceInterface;
use Pimcore\Bundle\StudioBackendBundle\DataObject\Schema\DataObject;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Parameters\Path\IdParameter;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\MethodNotAllowedResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\NotFoundResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnauthorizedResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnprocessableContentResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error\UnsupportedMediaTypeResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\SuccessResponse;
use Pimcore\Bundle\StudioBackendBundle\OpenApi\Config\Tags;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;

/**
* @internal
*/
final class GetController extends AbstractApiController
{
public function __construct(
SerializerInterface $serializer,
private readonly DataObjectSearchServiceInterface $dataObjectSearchService,
) {
parent::__construct($serializer);
}

#[Route('/data-objects/{id}', name: 'pimcore_studio_api_get_data_object', methods: ['GET'])]
//#[IsGranted('STUDIO_API')]
#[GET(
path: self::API_PATH . '/data-objects/{id}',
operationId: 'getDataObjectById',
description: 'Get data object by id by path parameter',
summary: 'Get data object by id',
security: self::SECURITY_SCHEME,
tags: [Tags::DataObjects->name]
)]
#[IdParameter(type: 'data-object')]
#[SuccessResponse(
description: 'Data object response',
content: new JsonContent(ref: DataObject::class)
)]
#[UnauthorizedResponse]
#[NotFoundResponse]
#[MethodNotAllowedResponse]
#[UnsupportedMediaTypeResponse]
#[UnprocessableContentResponse]
public function getAssetById(int $id): JsonResponse
{
return $this->jsonResponse($this->dataObjectSearchService->getDataObjectById($id));
}
}
28 changes: 28 additions & 0 deletions src/Exception/ElementNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\StudioBackendBundle\Exception;

/**
* @internal
*/
final class ElementNotFoundException extends AbstractApiException
{
public function __construct(int $id)
{
parent::__construct(404, 'Element with ID ' . $id . ' not found');
}
}
40 changes: 40 additions & 0 deletions src/OpenApi/Attributes/Response/Error/NotFoundResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\StudioBackendBundle\OpenApi\Attributes\Response\Error;

use Attribute;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\Response;
use OpenApi\Attributes\Schema;
use Pimcore\Bundle\StudioBackendBundle\Response\Schemas;

#[Attribute(Attribute::TARGET_METHOD)]
final class NotFoundResponse extends Response
{
public function __construct()
{
parent::__construct(
response: 404,
description: 'Resource not found',
content: new JsonContent(
oneOf: array_map(static function ($class) {
return new Schema(ref: $class);
}, Schemas::ERRORS),
)
);
}
}

0 comments on commit 28b5e1e

Please sign in to comment.