Skip to content

Commit bfefdc0

Browse files
committed
Add request model support
1 parent d9d10a8 commit bfefdc0

5 files changed

Lines changed: 495 additions & 22 deletions

File tree

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222
"bench": "vendor/bin/phpbench run --report=benchmark"
2323
},
2424
"require": {
25-
"php": ">=8.1",
25+
"php": ">=8.3",
2626
"utopia-php/compression": "0.1.*",
2727
"utopia-php/telemetry": "0.1.*"
2828
},
2929
"require-dev": {
30-
"phpunit/phpunit": "^9.5.25",
31-
"laravel/pint": "^1.2",
32-
"phpstan/phpstan": "^1.10",
33-
"phpbench/phpbench": "^1.2"
30+
"phpunit/phpunit": "9.*",
31+
"laravel/pint": "1.*",
32+
"phpstan/phpstan": "1.*",
33+
"phpbench/phpbench": "1.*"
3434
},
3535
"config": {
3636
"allow-plugins": {

src/App.php

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -693,21 +693,50 @@ protected function getArguments(Hook $hook, array $values, array $requestParams)
693693

694694
$value = $existsInValues ? $values[$key] : $arg;
695695

696-
if (!$param['skipValidation']) {
697-
if (!$paramExists && !$param['optional']) {
698-
throw new Exception('Param "' . $key . '" is not optional.', 400);
699-
}
696+
if (!$param['skipValidation']&& !$paramExists && !$param['optional']) {
697+
throw new Exception('Param "' . $key . '" is not optional.', 400);
698+
}
700699

701-
if ($paramExists) {
702-
$this->validate($key, $param, $value);
700+
if ($param['model'] && $paramExists) {
701+
$model = $param['model'];
702+
703+
if (!\is_string($model) || !\class_exists($model)) {
704+
throw new Exception('Model class does not exist: ' . $model, 500);
705+
}
706+
if (!\is_a($model, Model::class, true)) {
707+
throw new Exception('Model class is not an instance of Utopia\\Model', 500);
708+
}
709+
if (($value === null || $value === '') && $param['optional']) {
710+
$value = null;
711+
}
712+
if (\is_string($value) && $value !== '') {
713+
try {
714+
$value = \json_decode($value, true, flags: JSON_THROW_ON_ERROR);
715+
} catch (\Throwable $e) {
716+
throw new Exception('Failed to parse JSON for model param "' . $key . '": ' . $e->getMessage(), 400);
717+
}
718+
}
719+
if (!\is_array($value) && $value !== null && $value !== '') {
720+
throw new Exception('Model param "' . $key . '" must be a JSON string, or an array', 400);
721+
}
722+
if (\is_array($value)) {
723+
try {
724+
$value = $model::fromArray($value);
725+
} catch (\Throwable $e) {
726+
throw new Exception('Failed to create model instance for param "' . $key . '": ' . $e->getMessage(), 400);
727+
}
703728
}
704729
}
705730

731+
if (!$param['skipValidation'] && $paramExists && $value !== null && $value !== '') {
732+
$this->validate($key, $param, $value);
733+
}
734+
706735
$hook->setParamValue($key, $value);
707736
$arguments[$param['order']] = $value;
708737
}
709738

710-
foreach ($hook->getInjections() as $key => $injection) {
739+
foreach ($hook->getInjections() as $injection) {
711740
$arguments[$injection['order']] = $this->getResource($injection['name']);
712741
}
713742

src/Hook.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,19 @@ public function inject(string $injection): static
190190
/**
191191
* Add Param
192192
*
193-
* @param string $key
194-
* @param mixed $default
195-
* @param Validator|callable $validator
196-
* @param string $description
197-
* @param bool $optional
198-
* @param array $injections
199-
* @param bool $skipValidation
200-
* @param bool $deprecated
201-
* @param string $example
193+
* @param string $key
194+
* @param mixed $default
195+
* @param Validator|callable $validator
196+
* @param string $description
197+
* @param bool $optional
198+
* @param array $injections
199+
* @param bool $skipValidation
200+
* @param bool $deprecated
201+
* @param string $example
202+
* @param string|null $model
202203
* @return static
203204
*/
204-
public function param(string $key, mixed $default, Validator|callable $validator, string $description = '', bool $optional = false, array $injections = [], bool $skipValidation = false, bool $deprecated = false, string $example = ''): static
205+
public function param(string $key, mixed $default, Validator|callable $validator, string $description = '', bool $optional = false, array $injections = [], bool $skipValidation = false, bool $deprecated = false, string $example = '', ?string $model = null): static
205206
{
206207
$this->params[$key] = [
207208
'default' => $default,
@@ -212,6 +213,7 @@ public function param(string $key, mixed $default, Validator|callable $validator
212213
'skipValidation' => $skipValidation,
213214
'deprecated' => $deprecated,
214215
'example' => $example,
216+
'model' => $model,
215217
'value' => null,
216218
'order' => count($this->params) + count($this->injections),
217219
];

src/Model.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Utopia;
4+
5+
interface Model
6+
{
7+
public static function fromArray(array $value): static;
8+
}

0 commit comments

Comments
 (0)