Skip to content

Commit bc2a8f6

Browse files
authored
Merge pull request #3112 from soyuka/fix-metadata-disabled
Add the ability to declare empty item operations
2 parents 115cf92 + 912fca4 commit bc2a8f6

File tree

7 files changed

+163
-13
lines changed

7 files changed

+163
-13
lines changed

features/main/operation.feature

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,11 @@ Feature: Operation support
5555
}
5656
}
5757
"""
58+
59+
Scenario: Get the collection of a resource that have disabled item operation
60+
When I send a "GET" request to "/disable_item_operations"
61+
Then the response status code should be 200
62+
63+
Scenario: Get a 404 response for the disabled item operation
64+
When I send a "GET" request to "/disable_item_operations/1"
65+
Then the response status code should be 404

src/Action/NotFoundAction.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Action;
15+
16+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17+
18+
/**
19+
* An action which always returns HTTP 404 Not Found. Useful for disabling an operation.
20+
*/
21+
final class NotFoundAction
22+
{
23+
public function __invoke()
24+
{
25+
throw new NotFoundHttpException();
26+
}
27+
}

src/Bridge/Symfony/Bundle/Resources/config/api.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@
229229
<service id="api_platform.action.put_item" alias="api_platform.action.placeholder" public="true" />
230230
<service id="api_platform.action.delete_item" alias="api_platform.action.placeholder" public="true" />
231231
<service id="api_platform.action.get_subresource" alias="api_platform.action.placeholder" public="true" />
232+
<service id="api_platform.action.not_found" class="ApiPlatform\Core\Action\NotFoundAction" public="true" />
233+
<service id="ApiPlatform\Core\Action\NotFoundAction" alias="api_platform.action.not_found" public="true" />
232234

233235
<service id="api_platform.action.entrypoint" class="ApiPlatform\Core\Action\EntrypointAction" public="true">
234236
<argument type="service" id="api_platform.metadata.resource.name_collection_factory" />

tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\DependencyInjection;
1515

16+
use ApiPlatform\Core\Action\NotFoundAction;
1617
use ApiPlatform\Core\Api\FilterInterface;
1718
use ApiPlatform\Core\Api\IdentifiersExtractorInterface;
1819
use ApiPlatform\Core\Api\IriConverterInterface;
@@ -843,6 +844,7 @@ private function getPartialContainerBuilderProphecy()
843844
'api_platform.action.documentation',
844845
'api_platform.action.entrypoint',
845846
'api_platform.action.exception',
847+
'api_platform.action.not_found',
846848
'api_platform.action.placeholder',
847849
'api_platform.cache.identifiers_extractor',
848850
'api_platform.cache.metadata.property',
@@ -938,23 +940,24 @@ private function getPartialContainerBuilderProphecy()
938940
'api_platform.property_accessor' => 'property_accessor',
939941
'api_platform.property_info' => 'property_info',
940942
'api_platform.serializer' => 'serializer',
941-
Pagination::class => 'api_platform.pagination',
942-
IriConverterInterface::class => 'api_platform.iri_converter',
943-
UrlGeneratorInterface::class => 'api_platform.router',
944-
SerializerContextBuilderInterface::class => 'api_platform.serializer.context_builder',
945943
CollectionDataProviderInterface::class => 'api_platform.collection_data_provider',
946-
ItemDataProviderInterface::class => 'api_platform.item_data_provider',
947-
SubresourceDataProviderInterface::class => 'api_platform.subresource_data_provider',
948944
DataPersisterInterface::class => 'api_platform.data_persister',
949-
ResourceNameCollectionFactoryInterface::class => 'api_platform.metadata.resource.name_collection_factory',
950-
ResourceMetadataFactoryInterface::class => 'api_platform.metadata.resource.metadata_factory',
945+
GroupFilter::class => 'api_platform.serializer.group_filter',
946+
IdentifiersExtractorInterface::class => 'api_platform.identifiers_extractor.cached',
947+
IriConverterInterface::class => 'api_platform.iri_converter',
948+
ItemDataProviderInterface::class => 'api_platform.item_data_provider',
949+
NotFoundAction::class => 'api_platform.action.not_found',
950+
OperationAwareFormatsProviderInterface::class => 'api_platform.formats_provider',
951+
Pagination::class => 'api_platform.pagination',
952+
PropertyFilter::class => 'api_platform.serializer.property_filter',
951953
PropertyNameCollectionFactoryInterface::class => 'api_platform.metadata.property.name_collection_factory',
952954
PropertyMetadataFactoryInterface::class => 'api_platform.metadata.property.metadata_factory',
953955
ResourceClassResolverInterface::class => 'api_platform.resource_class_resolver',
954-
PropertyFilter::class => 'api_platform.serializer.property_filter',
955-
GroupFilter::class => 'api_platform.serializer.group_filter',
956-
OperationAwareFormatsProviderInterface::class => 'api_platform.formats_provider',
957-
IdentifiersExtractorInterface::class => 'api_platform.identifiers_extractor.cached',
956+
ResourceNameCollectionFactoryInterface::class => 'api_platform.metadata.resource.name_collection_factory',
957+
ResourceMetadataFactoryInterface::class => 'api_platform.metadata.resource.metadata_factory',
958+
SerializerContextBuilderInterface::class => 'api_platform.serializer.context_builder',
959+
SubresourceDataProviderInterface::class => 'api_platform.subresource_data_provider',
960+
UrlGeneratorInterface::class => 'api_platform.router',
958961
];
959962

960963
foreach ($aliases as $alias => $service) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Document;
15+
16+
use ApiPlatform\Core\Action\NotFoundAction;
17+
use ApiPlatform\Core\Annotation\ApiResource;
18+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
19+
20+
/**
21+
* @ApiResource(
22+
* collectionOperations={
23+
* "get",
24+
* },
25+
* itemOperations={
26+
* "get"={
27+
* "controller"=NotFoundAction::class,
28+
* "read"=false,
29+
* "output"=false,
30+
* },
31+
* },
32+
* )
33+
* @ODM\Document
34+
*/
35+
class DisableItemOperation
36+
{
37+
/**
38+
* @ODM\Id(strategy="INCREMENT", type="integer")
39+
*/
40+
private $id;
41+
42+
/**
43+
* @var string The dummy name
44+
*
45+
* @ODM\Field
46+
*/
47+
public $name;
48+
49+
public function getId()
50+
{
51+
return $this->id;
52+
}
53+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity;
15+
16+
use ApiPlatform\Core\Action\NotFoundAction;
17+
use ApiPlatform\Core\Annotation\ApiResource;
18+
use Doctrine\ORM\Mapping as ORM;
19+
20+
/**
21+
* @ApiResource(
22+
* collectionOperations={
23+
* "get",
24+
* },
25+
* itemOperations={
26+
* "get"={
27+
* "controller"=NotFoundAction::class,
28+
* "read"=false,
29+
* "output"=false,
30+
* },
31+
* },
32+
* )
33+
* @ORM\Entity
34+
*/
35+
class DisableItemOperation
36+
{
37+
/**
38+
* @var int The id
39+
*
40+
* @ORM\Column(type="integer", nullable=true)
41+
* @ORM\Id
42+
* @ORM\GeneratedValue(strategy="AUTO")
43+
*/
44+
private $id;
45+
46+
/**
47+
* @var string The dummy name
48+
*
49+
* @ORM\Column
50+
*/
51+
public $name;
52+
53+
public function getId()
54+
{
55+
return $this->id;
56+
}
57+
}

tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function testExecuteWithTooManyOptions()
6868
{
6969
$this->tester->run(['command' => 'api:json-schema:generate', 'resource' => $this->entityClass, '--collectionOperation' => 'get', '--itemOperation' => 'get', '--type' => 'output']);
7070

71-
$this->assertStringStartsWith('[ERROR] You can only use one of "--itemOperation" and "--collectionOperation"', trim(str_replace(["\r", "\n"], '', $this->tester->getDisplay())));
71+
$this->assertStringStartsWith('[ERROR] You can only use one of "--itemOperation" and "--collectionOperation" options at the same time.', trim(preg_replace('/\s+/', ' ', $this->tester->getDisplay())));
7272
}
7373

7474
public function testExecuteWithJsonldFormatOption()

0 commit comments

Comments
 (0)