Skip to content

Commit

Permalink
Merge branch '2.x' into annotated-4-0
Browse files Browse the repository at this point in the history
  • Loading branch information
butschster authored Jan 8, 2024
2 parents 785e63a + 6673bae commit 436f8c3
Show file tree
Hide file tree
Showing 20 changed files with 471 additions and 38 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.json]
indent_size = 2
13 changes: 11 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,30 @@
"cycle/schema-builder": "^2.6",
"doctrine/inflector": "^1.4 || ^2.0",
"spiral/attributes": "^2.10 || ^3.0",
"spiral/framework": "^3.11.1",
"spiral/reactor": "^3.0",
"spiral/scaffolder": "^3.0",
"spiral/prototype": "^3.0",
"spiral/console": "^3.0",
"spiral/core": "^3.0",
"spiral/boot": "^3.0",
"spiral/auth": "^3.0",
"spiral/tokenizer": "^3.0",
"spiral/config": "^3.0",
"spiral/filters": "^3.10",
"spiral/data-grid-bridge": "^3.0",
"psr/container": "^1.1 || ^2.0"
},
"require-dev": {
"doctrine/collections": "^1.6",
"doctrine/collections": "^2.0",
"illuminate/collections": "^9.0",
"infection/infection": "^0.26.6",
"mockery/mockery": "^1.5",
"phpunit/phpunit": "^9.5.20",
"spiral/framework": "^3.11.1",
"spiral/testing": "^2.4",
"spiral/validator": "^1.5",
"spiral/nyholm-bridge": "^1.3",
"spiral-packages/database-seeder": "^3.1",
"vimeo/psalm": "^4.27"
},
"autoload": {
Expand Down
2 changes: 1 addition & 1 deletion src/Console/Command/Migrate/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ protected function verifyEnvironment(string $message = 'Confirmation is required

$this->error($message);

if (!$this->askConfirmation()) {
if (!$this->askConfirmation() || !$this->isInteractive()) {
$this->comment('Cancelling operation...');

return false;
Expand Down
76 changes: 76 additions & 0 deletions src/Filter/EntityCaster.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace Spiral\Cycle\Filter;

use Cycle\ORM\ORMInterface;
use Psr\Container\ContainerInterface;
use Spiral\Exceptions\ExceptionReporterInterface;
use Spiral\Filters\Exception\SetterException;
use Spiral\Filters\Model\FilterInterface;
use Spiral\Filters\Model\Mapper\CasterInterface;

final class EntityCaster implements CasterInterface
{
/**
* @var array<class-string, non-empty-string>
*/
private static array $cache = [];
private ?ORMInterface $orm = null;

public function __construct(
protected readonly ContainerInterface $container,
protected readonly ExceptionReporterInterface $reporter,
) {
}

public function supports(\ReflectionNamedType $type): bool
{
if ($type->isBuiltin()) {
return false;
}

return $this->getOrm()->getSchema()->defines($type->getName());
}

public function setValue(FilterInterface $filter, \ReflectionProperty $property, mixed $value): void
{
try {
$role = $this->resolveRole($property->getType());
$object = $this->getOrm()->getRepository($role)->findByPK($value);
} catch (\Throwable $e) {
$this->reporter->report($e);
throw new SetterException(previous: $e);
}

if ($object === null && !$property->getType()->allowsNull()) {
throw new SetterException(
message: \sprintf('Unable to find entity `%s` by primary key "%s"', $role, $value),
);
}

$property->setValue($filter, $object);
}

private function resolveRole(\ReflectionNamedType $type): string
{
if (isset(self::$cache[$type->getName()])) {
return self::$cache[$type->getName()];
}

$role = $this->getOrm()->resolveRole($type->getName());
self::$cache[$type->getName()] = $role;

return $role;
}

private function getOrm(): ORMInterface
{
if ($this->orm === null) {
$this->orm = $this->container->get(ORMInterface::class);
}

return $this->orm;
}
}
7 changes: 7 additions & 0 deletions tests/app/Bootloader/AppBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Spiral\App\Repositories\RoleRepositoryInterface;
use Spiral\Bootloader\DomainBootloader;
use Spiral\Core\CoreInterface;
use Spiral\Cycle\Filter\EntityCaster;
use Spiral\Cycle\Interceptor\CycleInterceptor;
use Spiral\Filters\Model\Mapper\CasterRegistryInterface;

final class AppBootloader extends DomainBootloader
{
Expand All @@ -23,4 +25,9 @@ final class AppBootloader extends DomainBootloader
protected const INTERCEPTORS = [
CycleInterceptor::class,
];

public function init(CasterRegistryInterface $casterRegistry, EntityCaster $caster): void
{
$casterRegistry->register($caster);
}
}
21 changes: 21 additions & 0 deletions tests/app/Controller/Filter/RoleFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Spiral\App\Controller\Filter;

use Spiral\App\Entities\Role;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Model\Filter;

final class RoleFilter extends Filter
{
#[Post]
public string $name;

#[Post]
public Role $role;

#[Post]
public ?Role $nullableRole;
}
9 changes: 7 additions & 2 deletions tests/app/Controller/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ class HomeController
{
public function entity(User $user)
{
return $user->getName();
return [
'user' => $user->getName(),
];
}

public function entity2(User $user, Role $role)
{
return 'ok';
return [
'user' => $user->getName(),
'role' => $role->name,
];
}

public function index(): string
Expand Down
31 changes: 31 additions & 0 deletions tests/app/Controller/RoleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Spiral\App\Controller;

use Spiral\App\Controller\Filter\RoleFilter;
use Spiral\App\Entities\Role;
use Spiral\Router\Annotation\Route;

final class RoleController
{
#[Route(route: "/role", methods: ["POST"])]
public function create(RoleFilter $filter): array
{
return [
'name' => $filter->name,
'role' => $filter->role->name,
'id' => $filter->role->id,
];
}

#[Route(route: "/role/<role>", methods: ["GET"])]
public function show(Role $role): array
{
return [
'name' => $role->name,
'id' => $role->id,
];
}
}
32 changes: 32 additions & 0 deletions tests/app/Database/Factory/RoleFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Spiral\App\Database\Factory;

use Spiral\App\Entities\Role;
use Spiral\DatabaseSeeder\Factory\AbstractFactory;
use Spiral\DatabaseSeeder\Factory\FactoryInterface;

/**
* @implements FactoryInterface<Role>
*/
final class RoleFactory extends AbstractFactory
{
public function makeEntity(array $definition): object
{
return new Role($definition['name']);
}

public function entity(): string
{
return Role::class;
}

public function definition(): array
{
return [
'name' => $this->faker->word,
];
}
}
48 changes: 48 additions & 0 deletions tests/app/Database/Factory/UserFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Spiral\App\Database\Factory;

use Spiral\App\Entities\Role;
use Spiral\App\Entities\User;
use Spiral\DatabaseSeeder\Factory\AbstractFactory;
use Spiral\DatabaseSeeder\Factory\FactoryInterface;

/**
* @implements FactoryInterface<User>
*/
final class UserFactory extends AbstractFactory
{
public function makeEntity(array $definition): object
{
$user = new User($definition['name']);
$user->email = $definition['email'];
$user->company = $definition['company'];

return $user;
}

public function addRole(Role $role): self
{
return $this->entityState(static function (User $user) use ($role) {
$user->roles->add($role);

return $user;
});
}

public function entity(): string
{
return User::class;
}

public function definition(): array
{
return [
'name' => $this->faker->name,
'email' => $this->faker->email,
'company' => $this->faker->company,
];
}
}
5 changes: 4 additions & 1 deletion tests/app/Entities/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
use Cycle\Annotated\Annotation\Entity;
use Spiral\App\Repositories\RoleRepository;

#[Entity(repository: RoleRepository::class)]
#[
Entity(repository: RoleRepository::class),
\AllowDynamicProperties
]
class Role
{
#[Column(type: 'primary')]
Expand Down
7 changes: 5 additions & 2 deletions tests/app/Entities/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
use Doctrine\Common\Collections\ArrayCollection;
use Spiral\App\Repositories\UserRepository;

#[Entity(repository: UserRepository::class)]
#[
Entity(repository: UserRepository::class),
\AllowDynamicProperties
]
class User
{
#[Column(type: 'primary')]
Expand Down Expand Up @@ -46,7 +49,7 @@ class User

public function __construct(
#[Column(type: 'string')]
private string $name
private string $name,
) {
$this->friendsAsDoctrineCollection = new ArrayCollection();
$this->roles = new ArrayCollection();
Expand Down
8 changes: 8 additions & 0 deletions tests/src/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
use Spiral\App\Bootloader\AppBootloader;
use Spiral\App\Bootloader\SyncTablesBootloader;
use Spiral\Bootloader as Framework;
use Spiral\Nyholm\Bootloader as Nyholm;
use Spiral\Config\Patch\Set;
use Spiral\Console\Bootloader\ConsoleBootloader;
use Spiral\Core\ConfigsInterface;
use Spiral\Cycle\Bootloader as CycleBridge;
use Spiral\DataGrid\Bootloader\GridBootloader;
use Spiral\Router\Bootloader\AnnotatedRoutesBootloader;
use Spiral\Testing\TestCase;

abstract class BaseTest extends TestCase
Expand Down Expand Up @@ -64,6 +66,12 @@ public function defineBootloaders(): array
CycleBridge\DatabaseBootloader::class,
CycleBridge\MigrationsBootloader::class,

// Http
AnnotatedRoutesBootloader::class,
Framework\Http\RouterBootloader::class,
Nyholm\NyholmBootloader::class,
Framework\Security\FiltersBootloader::class,

// ORM
CycleBridge\SchemaBootloader::class,
CycleBridge\CycleOrmBootloader::class,
Expand Down
19 changes: 16 additions & 3 deletions tests/src/Console/Command/CycleOrm/MigrateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,25 @@ protected function setUp(): void
public function testMigrate(): void
{
// Create migration
$this->assertConsoleCommandOutputContainsStrings('cycle:migrate', [], self::USER_MIGRATION);
$this->assertConsoleCommandOutputContainsStrings('cycle:migrate', [
'--no-interaction' => true,
], self::USER_MIGRATION);

$this->assertConsoleCommandOutputContainsStrings('cycle:migrate', [], [
$this->assertConsoleCommandOutputContainsStrings('cycle:migrate', [
'--no-interaction' => true,
], [
'Outstanding migrations found',
'Detecting schema changes...',
'Please run `migrate` first.',
]);

$this->assertConsoleCommandOutputContainsStrings('migrate', [
'was successfully executed.',
]);

$this->assertConsoleCommandOutputContainsStrings('cycle:migrate', [
'--no-interaction' => true,
], [
'Detecting schema changes...',
'no database changes has been detected',
]);
}
Expand Down
Loading

0 comments on commit 436f8c3

Please sign in to comment.