Skip to content

Commit

Permalink
fix stan
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Jun 25, 2024
1 parent db81e02 commit e23c175
Show file tree
Hide file tree
Showing 19 changed files with 122 additions and 81 deletions.
3 changes: 1 addition & 2 deletions src/Laravel/ApiPlatformProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ public function register(): void
)
)
),
$app->make(ModelMetadata::class)
);
});

Expand Down Expand Up @@ -316,7 +315,7 @@ public function register(): void
});

$this->app->singleton(ValidateProvider::class, function (Application $app) {
return new ValidateProvider($app->make(ReadProvider::class), $app, $app->make(SerializerInterface::class), $app->make(SerializerContextBuilderInterface::class));
return new ValidateProvider($app->make(ReadProvider::class), $app);
});

$this->app->singleton(JsonApiProvider::class, function (Application $app) use ($config) {
Expand Down
20 changes: 13 additions & 7 deletions src/Laravel/ApiResource/ValidationError.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,19 @@
class ValidationError extends RuntimeException implements \Stringable, ProblemExceptionInterface, HttpExceptionInterface, SymfonyHttpExceptionInterface
{
private int $status = 422;
private mixed $id;
private string $id;

public function __construct(string $message = '', mixed $code = null, int|\Throwable|null $previous = null, protected array $violations = [])
/**
* @param array<int, array{propertyPath: string, message: string, code?: string}> $violations
*/
public function __construct(string $message = '', mixed $code = null, ?\Throwable $previous = null, protected array $violations = [])
{
$this->id = $code;
$this->id = (string) $code;
$this->setDetail($message);
parent::__construct($message ?: $this->__toString(), 422, $previous);
}

public function getId()
public function getId(): string
{
return $this->id;
}
Expand Down Expand Up @@ -130,11 +133,11 @@ public function getInstance(): ?string
return null;
}

#[SerializedName('violations')]
#[Groups(['json', 'jsonld'])]
/**
* @return array<int, array{propertyPath: string, message: string}>
* @return array<int,array{propertyPath:string,message:string,code?:string}>
*/
#[SerializedName('violations')]
#[Groups(['json', 'jsonld'])]
public function getViolations(): array
{
return $this->violations;
Expand All @@ -145,6 +148,9 @@ public function getStatusCode(): int
return $this->status;
}

/**
* @return array<string, string>
*/
public function getHeaders(): array
{
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ public function __construct(private readonly ?PropertyMetadataFactoryInterface $

public function create(string $resourceClass, string $property, array $options = []): ApiProperty
{
if (!class_exists($resourceClass)) {
return $this->decorated?->create($resourceClass, $property, $options) ?? new ApiProperty();
}

$refl = new \ReflectionClass($resourceClass);
$model = $refl->newInstanceWithoutConstructor();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public function create(string $resourceClass, array $options = []): PropertyName
{
$properties = $this->decorated ? iterator_to_array($this->decorated->create($resourceClass, $options)) : [];

if (!class_exists($resourceClass)) {
return new PropertyNameCollection($properties);
}

$refl = new \ReflectionClass($resourceClass);
$attributes = $refl->getAttributes(ApiProperty::class);
foreach ($attributes as $attribute) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public function __construct(private ModelMetadata $modelMetadata, private Proper
*/
public function create(string $resourceClass, array $options = []): PropertyNameCollection
{
if (!class_exists($resourceClass)) {
return $this->decorated->create($resourceClass, $options);
}

try {
$refl = new \ReflectionClass($resourceClass);
$model = $refl->newInstanceWithoutConstructor();
Expand All @@ -45,7 +49,7 @@ public function create(string $resourceClass, array $options = []): PropertyName

$properties = [];
// When it's an Eloquent model we read attributes from database (@see ShowModelCommand)
foreach ($this->modelMetadata->getAttributes($model) as $property) { // @phpstan-ignore-line
foreach ($this->modelMetadata->getAttributes($model) as $property) {
if (!$property['primary'] && $property['hidden']) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace ApiPlatform\Laravel\Eloquent\Metadata\Factory\Resource;

use ApiPlatform\Laravel\Eloquent\Metadata\ModelMetadata;
use ApiPlatform\Laravel\Eloquent\State\CollectionProvider;
use ApiPlatform\Laravel\Eloquent\State\ItemProvider;
use ApiPlatform\Laravel\Eloquent\State\PersistProcessor;
Expand All @@ -24,11 +23,10 @@
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
use Illuminate\Database\Eloquent\Model;

class EloquentResourceCollectionMetadataFactory implements ResourceMetadataCollectionFactoryInterface
final class EloquentResourceCollectionMetadataFactory implements ResourceMetadataCollectionFactoryInterface
{
public function __construct(
private readonly ResourceMetadataCollectionFactoryInterface $decorated,
private readonly ModelMetadata $modelMetadata
) {
}

Expand Down
71 changes: 31 additions & 40 deletions src/Laravel/Eloquent/Metadata/ModelMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;

Expand All @@ -28,7 +29,7 @@ final class ModelMetadata
/**
* The methods that can be called in a model to indicate a relation.
*
* @var array
* @var string[]
*/
public const RELATION_METHODS = [
'hasMany',
Expand Down Expand Up @@ -63,9 +64,9 @@ public function getPolicy($model)
*
* @param Model $model
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<string, mixed>
*/
public function getAttributes($model)
public function getAttributes($model): Collection
{
$connection = $model->getConnection();
$schema = $connection->getSchemaBuilder();
Expand All @@ -90,6 +91,9 @@ public function getAttributes($model)
->merge($this->getVirtualAttributes($model, $columns));
}

/**
* @param array<int, array{columns: string[]}> $indexes
*/
private function isColumnPrimaryKey(array $indexes, string $column): bool
{
foreach ($indexes as $index) {
Expand All @@ -104,12 +108,11 @@ private function isColumnPrimaryKey(array $indexes, string $column): bool
/**
* Get the virtual (non-column) attributes for the given model.
*
* @param Model $model
* @param array $columns
* @param array<string, mixed> $columns
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<int, mixed>
*/
public function getVirtualAttributes($model, $columns)
public function getVirtualAttributes(Model $model, $columns): Collection
{
$class = new \ReflectionClass($model);

Expand Down Expand Up @@ -148,11 +151,9 @@ public function getVirtualAttributes($model, $columns)
/**
* Get the relations from the given model.
*
* @param Model $model
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<int, mixed>
*/
public function getRelations($model)
public function getRelations(Model $model): Collection
{
return collect(get_class_methods($model))
->map(fn ($method) => new \ReflectionMethod($model, $method))
Expand All @@ -168,11 +169,19 @@ public function getRelations($model)
return true;
}

if (false === $method->getFileName()) {
return false;
}

$file = new \SplFileObject($method->getFileName());
$file->seek($method->getStartLine() - 1);
$code = '';
while ($file->key() < $method->getEndLine()) {
$code .= trim($file->current());
$current = $file->current();
if (\is_string($current)) {
$code .= trim($current);
}

$file->next();
}

Expand All @@ -199,11 +208,9 @@ public function getRelations($model)
/**
* Get the Events that the model dispatches.
*
* @param Model $model
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<int, mixed>
*/
public function getEvents($model)
public function getEvents(Model $model): Collection
{
return collect($model->dispatchesEvents())
->map(fn (string $class, string $event) => [
Expand All @@ -214,13 +221,8 @@ public function getEvents($model)

/**
* Get the cast type for the given column.
*
* @param string $column
* @param Model $model
*
* @return string|null
*/
private function getCastType($column, $model)
private function getCastType(string $column, Model $model): ?string
{
if ($model->hasGetMutator($column) || $model->hasSetMutator($column)) {
return 'accessor';
Expand All @@ -236,11 +238,9 @@ private function getCastType($column, $model)
/**
* Get the model casts, including any date casts.
*
* @param Model $model
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<string, mixed>
*/
private function getCastsWithDates($model)
private function getCastsWithDates(Model $model): Collection
{
return collect($model->getDates())
->filter()
Expand All @@ -252,12 +252,11 @@ private function getCastsWithDates($model)
/**
* Get the default value for the given column.
*
* @param array $column
* @param Model $model
* @param array<string, mixed>&array{name: string, default: string} $column
*
* @return mixed|null
*/
private function getColumnDefault($column, $model)
private function getColumnDefault(array $column, Model $model): mixed
{
$attributeDefault = $model->getAttributes()[$column['name']] ?? null;

Expand All @@ -270,13 +269,8 @@ private function getColumnDefault($column, $model)

/**
* Determine if the given attribute is hidden.
*
* @param string $attribute
* @param Model $model
*
* @return bool
*/
private function attributeIsHidden($attribute, $model)
private function attributeIsHidden(string $attribute, Model $model): bool
{
if (\count($model->getHidden()) > 0) {
return \in_array($attribute, $model->getHidden(), true);
Expand All @@ -292,12 +286,9 @@ private function attributeIsHidden($attribute, $model)
/**
* Determine if the given attribute is unique.
*
* @param string $column
* @param array $indexes
*
* @return bool
* @param array<int, array{columns: string[], unique: bool}> $indexes
*/
private function columnIsUnique($column, $indexes)
private function columnIsUnique(string $column, array $indexes): bool
{
return collect($indexes)->contains(
fn ($index) => 1 === \count($index['columns']) && $index['columns'][0] === $column && $index['unique']
Expand Down
12 changes: 12 additions & 0 deletions src/Laravel/Eloquent/PropertyAccess/PropertyAccessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,17 @@ public function __construct(private readonly PropertyAccessorInterface $inner)
{
}

/**
* @param array<mixed, mixed>|object $objectOrArray
*/
public function setValue(object|array &$objectOrArray, string|PropertyPathInterface $propertyPath, mixed $value): void
{
$this->inner->setValue($objectOrArray, $propertyPath, $value);
}

/**
* @param array<mixed, mixed>|object $objectOrArray
*/
public function getValue(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): mixed
{
$value = $this->inner->getValue($objectOrArray, $propertyPath);
Expand All @@ -42,11 +48,17 @@ public function getValue(object|array $objectOrArray, string|PropertyPathInterfa
return $value;
}

/**
* @param array<mixed, mixed>|object $objectOrArray
*/
public function isWritable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool
{
return $this->inner->isWritable($objectOrArray, $propertyPath);
}

/**
* @param array<mixed, mixed>|object $objectOrArray
*/
public function isReadable(object|array $objectOrArray, string|PropertyPathInterface $propertyPath): bool
{
return $this->inner->isReadable($objectOrArray, $propertyPath);
Expand Down
7 changes: 5 additions & 2 deletions src/Laravel/Eloquent/State/CollectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class CollectionProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;

/**
* @param LinksHandlerInterface<Model> $linksHandler
*/
public function __construct(private readonly Pagination $pagination, private readonly LinksHandlerInterface $linksHandler, ?ContainerInterface $handleLinksLocator = null)
{
$this->handleLinksLocator = $handleLinksLocator;
Expand All @@ -44,9 +47,9 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
$model = new ($operation->getClass())();

if ($handleLinks = $this->getLinksHandler($operation)) {
$query = $handleLinks($model->query(), $uriVariables, ['operation' => $operation] + $context);
$query = $handleLinks($model->query(), $uriVariables, ['operation' => $operation, 'modelClass' => $operation->getClass()] + $context);
} else {
$query = $this->linksHandler->handleLinks($model->query(), $uriVariables, ['operation' => $operation] + $context);
$query = $this->linksHandler->handleLinks($model->query(), $uriVariables, ['operation' => $operation, 'modelClass' => $operation->getClass()] + $context);
}

if (false === $this->pagination->isEnabled($operation, $context)) {
Expand Down
4 changes: 4 additions & 0 deletions src/Laravel/Eloquent/State/ItemProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use Illuminate\Database\Eloquent\Model;
use Psr\Container\ContainerInterface;

/**
Expand All @@ -24,6 +25,9 @@ class ItemProvider implements ProviderInterface
{
use LinksHandlerLocatorTrait;

/**
* @param LinksHandlerInterface<Model> $linksHandler
*/
public function __construct(private readonly LinksHandlerInterface $linksHandler, ?ContainerInterface $handleLinksLocator = null)
{
$this->handleLinksLocator = $handleLinksLocator;
Expand Down
Loading

0 comments on commit e23c175

Please sign in to comment.