Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Serializer/OperationContextTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected function createOperationContext(array $context, ?string $resourceClass
// At some point we should merge the jsonld context here, there's a TODO to simplify this somewhere else
if ($propertyMetadata) {
$context['output'] ??= [];
$context['output']['gen_id'] = $propertyMetadata->getGenId() ?? true;
$context['output']['gen_id'] = $propertyMetadata->getGenId() ?? ($context['gen_id'] ?? true);
}

if (!$resourceClass) {
Expand Down
43 changes: 43 additions & 0 deletions tests/Fixtures/TestBundle/ApiResource/GenIdFalse/GenIdDefault.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Operation;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

#[Get(uriTemplate: '/gen_id_default', provider: [self::class, 'getData'], normalizationContext: ['hydra_prefix' => false])]
class GenIdDefault
{
public function __construct(
public string $id,
#[ApiProperty] public Collection $subresources,
) {
}

public static function getData(Operation $operation, array $uriVariables = [], array $context = []): self
{
return new self(
'1',
new ArrayCollection(
[
new Subresource('foo'),
new Subresource('bar'),
]
)
);
}
}
43 changes: 43 additions & 0 deletions tests/Fixtures/TestBundle/ApiResource/GenIdFalse/GenIdTrue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Operation;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

#[Get(uriTemplate: '/gen_id_truthy', provider: [self::class, 'getData'], normalizationContext: ['hydra_prefix' => false])]
class GenIdTrue
{
public function __construct(
public string $id,
#[ApiProperty(genId: true)] public Collection $subresources,
) {
}

public static function getData(Operation $operation, array $uriVariables = [], array $context = []): self
{
return new self(
'1',
new ArrayCollection(
[
new Subresource('foo'),
new Subresource('bar'),
]
)
);
}
}
24 changes: 24 additions & 0 deletions tests/Fixtures/TestBundle/ApiResource/GenIdFalse/Subresource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse;

use ApiPlatform\Metadata\ApiProperty;

class Subresource
{
public function __construct(
#[ApiProperty] public string $title,
) {
}
}
18 changes: 16 additions & 2 deletions tests/Fixtures/app/AppKernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,15 @@ class AppKernel extends Kernel
{
use MicroKernelTrait;

public function __construct(string $environment, bool $debug)
private $genIdDefault;

public function __construct(string $environment, bool $debug, ?bool $genIdDefault = null)
{
parent::__construct($environment, $debug);

// patch for behat/symfony2-extension not supporting %env(APP_ENV)%
$this->environment = $_SERVER['APP_ENV'] ?? $environment;
$this->genIdDefault = $genIdDefault ?? $_SERVER['GEN_ID_DEFAULT'] ?? null;
}

public function registerBundles(): array
Expand Down Expand Up @@ -106,6 +109,11 @@ public function getProjectDir(): string
return __DIR__;
}

public function getCacheDir(): string
{
return parent::getCacheDir().(null !== $this->genIdDefault ? '_gen_id_'.$this->genIdDefault : '');
}

protected function configureRoutes($routes): void
{
$routes->import(__DIR__."/config/routing_{$this->getEnvironment()}.yml");
Expand All @@ -114,6 +122,7 @@ protected function configureRoutes($routes): void
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void
{
$c->setParameter('kernel.project_dir', __DIR__);
$c->setParameter('app.gen_id_default', $this->genIdDefault);

$loader->load(__DIR__."/config/config_{$this->getEnvironment()}.yml");

Expand Down Expand Up @@ -274,7 +283,12 @@ class_exists(NativePasswordHasher::class) ? 'password_hashers' : 'encoders' => [
'vary' => ['Accept', 'Cookie'],
'public' => true,
],
'normalization_context' => ['skip_null_values' => false],
'normalization_context' => null !== $this->genIdDefault ? [
'skip_null_values' => false,
'gen_id' => (bool) $this->genIdDefault,
] : [
'skip_null_values' => false,
],
'operations' => [
Get::class,
GetCollection::class,
Expand Down
101 changes: 101 additions & 0 deletions tests/Functional/GenIdGlobalOptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\Functional;

use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\AggregateRating;
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdDefault;
use ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\GenIdFalse\GenIdTrue;
use ApiPlatform\Tests\SetupClassResourcesTrait;

final class GenIdGlobalOptionTest extends ApiTestCase
{
use SetupClassResourcesTrait;

protected static ?bool $alwaysBootKernel = true;

/**
* @return class-string[]
*/
public static function getResources(): array
{
return [
AggregateRating::class,
GenIdDefault::class,
GenIdTrue::class,
];
}

protected function setUp(): void
{
parent::setUp();
unset($_SERVER['GEN_ID_DEFAULT']);
}

protected function tearDown(): void
{
unset($_SERVER['GEN_ID_DEFAULT']);
parent::tearDown();
}

/**
* When gen_id is globally false and no #[ApiProperty(genId: ...)] on the property,
* the nested object must not expose an @id.
*/
public function testGlobalGenIdFalseDisablesSkolemIdByDefaultOnProperties(): void
{
$_SERVER['GEN_ID_DEFAULT'] = 0; // simulate global defaults.normalization_context.gen_id: false

$response = self::createClient()->request(
'GET',
'/gen_id_default'
);
$this->assertResponseIsSuccessful();
$data = $response->toArray();

$this->assertArrayNotHasKey('@id', $data['subresources'][0]);
}

/**
* #[ApiProperty(genId: true)] on the property must take precedence.
*/
public function testApiPropertyGenIdTrueTakesPrecedenceOverGlobalFalse(): void
{
$_SERVER['GEN_ID_DEFAULT'] = 0; // simulate global defaults.normalization_context.gen_id: false

$response = self::createClient()->request(
'GET',
'/gen_id_truthy'
);
$this->assertResponseIsSuccessful();
$data = $response->toArray();

$this->assertArrayHasKey('@id', $data['subresources'][0]);
}

/**
* Without a global option and without an attribute, genId must be true by default.
*/
public function testWhenNoGlobalOptionAndNoAttributeGenIdIsTrueByDefault(): void
{
$response = self::createClient()->request(
'GET',
'/gen_id_default'
);
$this->assertResponseIsSuccessful();
$data = $response->toArray();

$this->assertArrayHasKey('@id', $data['subresources'][0]);
}
}
Loading