Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
27pchrisl committed Nov 14, 2023
1 parent 409dd56 commit df5f016
Show file tree
Hide file tree
Showing 28 changed files with 414 additions and 13 deletions.
23 changes: 23 additions & 0 deletions doc/modelling/types/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,27 @@ class LodataServiceProvider extends ServiceProvider
Lodata::add($set);
}
}
```

## Immutable properties

Lodata supports annotating a property as `Immutable` meaning that it can be provided as part of a create request, but
will be ignored during an update request.

```php
class LodataServiceProvider extends ServiceProvider
{
public function boot()
{
$entityType = new \Flat3\Lodata\EntityType('example');
$entityType->setKey(new \Flat3\Lodata\DeclaredProperty('id', \Flat3\Lodata\Type::string()));
$entityType->addDeclaredProperty('name', \Flat3\Lodata\Type::string());
$dob = new \Flat3\Lodata\DeclaredProperty('dob', \Flat3\Lodata\Type::date());
$dob->addAnnotation(new \Flat3\Lodata\Annotation\Core\V1\Immutable);
$entityType->addProperty($dob);
$entitySet = new \Flat3\Lodata\Drivers\CollectionEntitySet('examples', $entityType);
$entitySet->setCollection($collection);
\Lodata::add($entitySet);
}
}
```
26 changes: 17 additions & 9 deletions src/ComplexType.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ public function getOpenAPIUpdateSchema(): array
/**
* Ensure the provided property values are valid against this type
* @param PropertyValues $propertyValues Property values
* @return void
* @return PropertyValues
*/
public function assertPropertyValues(PropertyValues $propertyValues): void
public function assertPropertyValues(PropertyValues $propertyValues): PropertyValues
{
if ($this->isOpen()) {
return;
return $propertyValues;
}

$properties = $this->getProperties();
Expand All @@ -310,26 +310,32 @@ public function assertPropertyValues(PropertyValues $propertyValues): void
)
);
}

return $propertyValues;
}

/**
* Ensure the provided property values meet the update requirements of the entity type
* @param PropertyValues $propertyValues Property values
* @return void
* @return PropertyValues
*/
public function assertUpdateProperties(PropertyValues $propertyValues)
public function assertUpdateProperties(PropertyValues $propertyValues): PropertyValues
{
$this->assertPropertyValues($propertyValues);
return $this->assertPropertyValues($propertyValues)->filter(function (PropertyValue $propertyValue) {
return !$propertyValue->getProperty()->isImmutable();
});
}

/**
* Ensure the provided property values meet the create requirements of the entity type
* @param PropertyValues $propertyValues Property values
* @param PropertyValue|null $foreignKey Foreign key value
* @return void
* @return PropertyValues
*/
public function assertCreateProperties(PropertyValues $propertyValues, ?PropertyValue $foreignKey = null)
{
public function assertCreateProperties(
PropertyValues $propertyValues,
?PropertyValue $foreignKey = null
): PropertyValues {
$declaredProperties = $this->getDeclaredProperties();

$this->assertPropertyValues($propertyValues);
Expand Down Expand Up @@ -364,5 +370,7 @@ public function assertCreateProperties(PropertyValues $propertyValues, ?Property

$declaredProperty->assertAllowsValue(null);
}

return $propertyValues;
}
}
2 changes: 1 addition & 1 deletion src/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public function patch(Transaction $transaction, ?ContextInterface $context = nul

$propertyValues = $entitySet->arrayToPropertyValues($entitySet->getTransaction()->getBodyAsArray());

$this->getType()->assertUpdateProperties($propertyValues);
$propertyValues = $this->getType()->assertUpdateProperties($propertyValues);

$entity = $entitySet->update($this->getEntityId(), $propertyValues);

Expand Down
6 changes: 3 additions & 3 deletions src/EntitySet.php
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ public function response(Transaction $transaction, ?ContextInterface $context =
Gate::create($this, $transaction)->ensure();

$propertyValues = $this->arrayToPropertyValues($this->getTransaction()->getBodyAsArray());
$this->getType()->assertCreateProperties($propertyValues, $this->navigationSource);
$propertyValues = $this->getType()->assertCreateProperties($propertyValues, $this->navigationSource);

$transaction->getResponse()->setStatusCode(Response::HTTP_CREATED);

Expand Down Expand Up @@ -858,7 +858,7 @@ public function processDeltaCreate(Transaction $transaction): Entity
Gate::create($this, $transaction)->ensure();

$propertyValues = $this->arrayToPropertyValues($this->transaction->getBodyAsArray());
$this->getType()->assertCreateProperties($propertyValues, $this->navigationSource);
$propertyValues = $this->getType()->assertCreateProperties($propertyValues, $this->navigationSource);
$entity = $this->create($propertyValues);
$transaction->processDeltaPayloads($entity);

Expand All @@ -882,7 +882,7 @@ public function processDeltaModify(Transaction $transaction, Entity $entity): En

$propertyValues = $this->arrayToPropertyValues($transaction->getBodyAsArray());

$this->getType()->assertUpdateProperties($propertyValues);
$propertyValues = $this->getType()->assertUpdateProperties($propertyValues);

$entity = $this->update($entity->getEntityId(), $propertyValues);

Expand Down
10 changes: 10 additions & 0 deletions src/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Flat3\Lodata\Annotation\Core\V1\Computed;
use Flat3\Lodata\Annotation\Core\V1\ComputedDefaultValue;
use Flat3\Lodata\Annotation\Core\V1\Description;
use Flat3\Lodata\Annotation\Core\V1\Immutable;
use Flat3\Lodata\Exception\Protocol\BadRequestException;
use Flat3\Lodata\Exception\Protocol\ConfigurationException;
use Flat3\Lodata\Helper\Constants;
Expand Down Expand Up @@ -411,4 +412,13 @@ public function isComputed(): bool
$this->hasAnnotation(new Computed, Boolean::true()) ||
$this->hasAnnotation(new ComputedDefaultValue, Boolean::true());
}

/**
* Determine whether this property is immutable
* @return bool
*/
public function isImmutable(): bool
{
return $this->hasAnnotation(new Immutable);
}
}
18 changes: 18 additions & 0 deletions tests/EntitySetCreate/EntitySetCreate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Flat3\Lodata\Tests\EntitySetCreate;

use Flat3\Lodata\Annotation\Core\V1\Immutable;
use Flat3\Lodata\Controller\Response;
use Flat3\Lodata\Facades\Lodata;
use Flat3\Lodata\Tests\Helpers\Request;
Expand Down Expand Up @@ -190,4 +191,21 @@ public function test_collection_property()
Response::HTTP_CREATED
);
}

public function test_creates_with_immutable()
{
$type = Lodata::getEntitySet($this->entitySet)->getType();
$type->getProperty('age')->addAnnotation(new Immutable);

$this->assertJsonResponseSnapshot(
(new Request)
->post()
->path($this->entitySetPath)
->body([
'name' => 'Four',
'age' => 4,
]),
Response::HTTP_CREATED
);
}
}
5 changes: 5 additions & 0 deletions tests/EntitySetCreate/FilesystemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,9 @@ public function test_collection_property()
{
$this->expectNotToPerformAssertions();
}

public function test_creates_with_immutable()
{
$this->expectNotToPerformAssertions();
}
}
20 changes: 20 additions & 0 deletions tests/EntitySetCreate/KeyedCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Flat3\Lodata\Tests\EntitySetCreate;

use Flat3\Lodata\Annotation\Core\V1\Immutable;
use Flat3\Lodata\Controller\Response;
use Flat3\Lodata\Facades\Lodata;
use Flat3\Lodata\Tests\Drivers\WithKeyedCollectionDriver;
use Flat3\Lodata\Tests\Helpers\Request;

Expand Down Expand Up @@ -129,4 +131,22 @@ public function test_create_accepts_invalid_property()
Response::HTTP_CREATED
);
}

public function test_creates_with_immutable()
{
$type = Lodata::getEntitySet($this->entitySet)->getType();
$type->getProperty('age')->addAnnotation(new Immutable);

$this->assertJsonResponseSnapshot(
(new Request)
->post()
->path($this->entitySetPath)
->body([
'id' => 'zeta',
'name' => 'Four',
'age' => 4,
]),
Response::HTTP_CREATED
);
}
}
19 changes: 19 additions & 0 deletions tests/EntitySetCreate/RedisTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Flat3\Lodata\Tests\EntitySetCreate;

use Flat3\Lodata\Annotation\Core\V1\Immutable;
use Flat3\Lodata\Controller\Response;
use Flat3\Lodata\Facades\Lodata;
use Flat3\Lodata\Tests\Drivers\WithRedisDriver;
Expand Down Expand Up @@ -150,4 +151,22 @@ public function test_create_accepts_invalid_property()
Response::HTTP_CREATED
);
}

public function test_creates_with_immutable()
{
$type = Lodata::getEntitySet($this->entitySet)->getType();
$type->getProperty('age')->addAnnotation(new Immutable);

$this->assertJsonResponseSnapshot(
(new Request)
->post()
->path($this->entitySetPath)
->body([
'key' => 'zeta',
'name' => 'Four',
'age' => 4,
]),
Response::HTTP_CREATED
);
}
}
16 changes: 16 additions & 0 deletions tests/EntityUpdate/EntityUpdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Flat3\Lodata\Tests\EntityUpdate;

use Flat3\Lodata\Annotation\Core\V1\Immutable;
use Flat3\Lodata\Controller\Response;
use Flat3\Lodata\Facades\Lodata;
use Flat3\Lodata\Tests\Helpers\Request;
Expand Down Expand Up @@ -394,4 +395,19 @@ public function test_collection_property_delete()
->path($this->entityPath.'/emails'),
);
}

public function test_ignores_immutable()
{
$type = Lodata::getEntitySet($this->entitySet)->getType();
$type->getProperty('name')->addAnnotation(new Immutable);

$this->assertJsonResponseSnapshot(
(new Request)
->path($this->entityPath)
->patch()
->body([
'name' => 'Alph',
])
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"@context": "http://localhost/odata/$metadata#Passengers/$entity",
"id": 6,
"flight_id": null,
"name": "Four",
"dob": null,
"age": 4,
"chips": null,
"dq": null,
"in_role": null,
"open_time": null,
"colour": null,
"sock_colours": null,
"emails": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@@ @@
"colour": null,
"sock_colours": null,
"emails": null
+ },
+ {
+ "id": 6,
+ "flight_id": null,
+ "name": "Four",
+ "dob": null,
+ "age": 4,
+ "chips": null,
+ "dq": null,
+ "in_role": null,
+ "open_time": null,
+ "colour": null,
+ "sock_colours": null,
+ "emails": null
}
],
"pets": [
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"@context": "http://localhost/odata/$metadata#passengers/$entity",
"id": "zeta",
"name": "Four",
"age": 4,
"dob": null,
"chips": null,
"dq": null,
"in_role": null,
"open_time": null,
"flight_id": null,
"colour": null,
"sock_colours": null,
"emails": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@@ @@
"in_role": 888.9,
"colour": null,
"sock_colours": null
+ },
+ "zeta": {
+ "id": "zeta",
+ "name": "Four",
+ "age": 4
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"@context": "http://localhost/odata/$metadata#passengers/$entity",
"name": "Four",
"age": 4,
"_id": "four",
"dob": null,
"chips": null,
"dq": null,
"in_role": null,
"open_time": null,
"flight_id": null,
"colour": null,
"sock_colours": null,
"emails": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@@ @@
"in_role": 888.9,
"colour": 0,
"sock_colours": 0
+ },
+ {
+ "_id": "four",
+ "name": "Four",
+ "age": 4
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"@context": "http://localhost/odata/$metadata#passengers/$entity",
"name": "Four",
"age": 4,
"id": 5,
"dob": null,
"chips": null,
"dq": null,
"in_role": null,
"open_time": null,
"flight_id": null,
"colour": null,
"sock_colours": null,
"emails": []
}
Loading

0 comments on commit df5f016

Please sign in to comment.