From 629d3a9eef58718ea0fd22194930c3b2d9c3a106 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 03:12:46 +0200 Subject: [PATCH 01/57] added migration for feature test. --- ...11109_create_all_main_and_pivot_tables.php | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php diff --git a/tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php b/tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php new file mode 100644 index 0000000..aff7db1 --- /dev/null +++ b/tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php @@ -0,0 +1,91 @@ +unsignedBigInteger('id')->primary(); + $table->string('name'); + }); + + Schema::create('roles', function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->string('name'); + }); + + Schema::create('products', function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->string('name'); + }); + + Schema::create('orders', function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->string('order_number'); + }); + + Schema::create('categories', function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->string('name'); + }); + + Schema::create('tags', function (Blueprint $table) { + $table->unsignedBigInteger('id')->primary(); + $table->string('name'); + }); + + Schema::create('role_user', function (Blueprint $table) { + $table->unsignedBigInteger('role_id'); + $table->unsignedBigInteger('user_id'); + $table->primary(['role_id', 'user_id']); + + $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + + Schema::create('order_product', function (Blueprint $table) { + $table->unsignedBigInteger('order_id'); + $table->unsignedBigInteger('product_id'); + $table->primary(['order_id', 'product_id']); + + $table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade'); + $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); + }); + + Schema::create('category_product', function (Blueprint $table) { + $table->unsignedBigInteger('category_id'); + $table->unsignedBigInteger('product_id'); + $table->primary(['category_id', 'product_id']); + + $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); + $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); + }); + + Schema::create('product_tag', function (Blueprint $table) { + $table->unsignedBigInteger('product_id'); + $table->unsignedBigInteger('tag_id'); + $table->primary(['product_id', 'tag_id']); + + $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); + $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade'); + }); + } + + public function down(): void + { + Schema::dropIfExists('product_tag'); + Schema::dropIfExists('category_product'); + Schema::dropIfExists('order_product'); + Schema::dropIfExists('role_user'); + Schema::dropIfExists('tags'); + Schema::dropIfExists('categories'); + Schema::dropIfExists('orders'); + Schema::dropIfExists('products'); + Schema::dropIfExists('roles'); + Schema::dropIfExists('users'); + } +}; From 7b18f21638a2f1d6c295c44aa13568a30624b732 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 11:57:04 +0200 Subject: [PATCH 02/57] added migration for feature test, refactored DBTestCase to being able to select migrations for testcases. --- tests/DbTestCase.php | 19 ++++++++++++++++++- ...5_05_090000_create_package_test_tables.php | 0 ...11109_create_all_main_and_pivot_tables.php | 0 3 files changed, 18 insertions(+), 1 deletion(-) rename tests/Resources/Database/Migrations/{ => default}/2020_05_05_090000_create_package_test_tables.php (100%) rename tests/Resources/Database/Migrations/{ => features/schema-normalization}/2025_06_21_011109_create_all_main_and_pivot_tables.php (100%) diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index a63e60c..d26ac8b 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -7,13 +7,30 @@ class DbTestCase extends TestCase { + protected array $migrations = []; + protected function setUp(): void { parent::setUp(); - $this->loadMigrationsFrom($this->resourceFolder.'/Database/Migrations/'); + $this->loadMigrationsFrom($this->getMigrations()); $this->loadLaravelMigrations(['--database' => env('DB_CONNECTION', 'mysql')]); } + public function getMigrations(): array + { + if (0 === count($this->migrations)) { + $this->setMigrations([ + $this->resourceFolder.'/Database/Migrations/default/', + ]); + } + return $this->migrations; + } + + public function setMigrations(array $migrations): void + { + $this->migrations = $migrations; + } + protected function skipUnlessDatabase(string $engine): void { if (env('DB_CONNECTION') !== $engine) { diff --git a/tests/Resources/Database/Migrations/2020_05_05_090000_create_package_test_tables.php b/tests/Resources/Database/Migrations/default/2020_05_05_090000_create_package_test_tables.php similarity index 100% rename from tests/Resources/Database/Migrations/2020_05_05_090000_create_package_test_tables.php rename to tests/Resources/Database/Migrations/default/2020_05_05_090000_create_package_test_tables.php diff --git a/tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php b/tests/Resources/Database/Migrations/features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php similarity index 100% rename from tests/Resources/Database/Migrations/2025_06_21_011109_create_all_main_and_pivot_tables.php rename to tests/Resources/Database/Migrations/features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php From 19a7aa61227bbf0a7f15af3e21208a340121a4c2 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 12:01:03 +0200 Subject: [PATCH 03/57] feature branches fixed. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e9786..b5a2aa9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,11 +2,11 @@ name: CI on: push: - branches: [ feature-*, develop, dev-*, master ] + branches: [ feature/*, develop, dev-*, master ] tags: - '*' pull_request: - branches: [ feature-*, develop, dev-*, master ] + branches: [ feature/*, develop, dev-*, master ] jobs: test-mysql: From 1b2da0908cc5322fc34804e440d415c23b0e5e42 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 12:34:51 +0200 Subject: [PATCH 04/57] added multiple laravel migrations. --- phpunit.xml | 1 + tests/DbTestCase.php | 9 ++++++-- ...5_05_090000_create_package_test_tables.php | 0 ...11109_create_all_main_and_pivot_tables.php | 0 tests/TestCase.php | 21 ++++++++++++++----- 5 files changed, 24 insertions(+), 7 deletions(-) rename tests/Resources/Database/Migrations/{default => Default}/2020_05_05_090000_create_package_test_tables.php (100%) rename tests/Resources/Database/Migrations/{features => Features}/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php (100%) diff --git a/phpunit.xml b/phpunit.xml index da6ba6e..f776bf3 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -39,6 +39,7 @@ + diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index d26ac8b..3efdb37 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -7,12 +7,17 @@ class DbTestCase extends TestCase { + protected array $migrations = []; protected function setUp(): void { parent::setUp(); - $this->loadMigrationsFrom($this->getMigrations()); + $migrations = $this->getMigrations(); + foreach ($migrations as $migrationPath) { + $this->loadMigrationsFrom($migrationPath); + } + $this->loadLaravelMigrations(['--database' => env('DB_CONNECTION', 'mysql')]); } @@ -20,7 +25,7 @@ public function getMigrations(): array { if (0 === count($this->migrations)) { $this->setMigrations([ - $this->resourceFolder.'/Database/Migrations/default/', + $this->resourceFolder . 'Database/Migrations/Default/', ]); } return $this->migrations; diff --git a/tests/Resources/Database/Migrations/default/2020_05_05_090000_create_package_test_tables.php b/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php similarity index 100% rename from tests/Resources/Database/Migrations/default/2020_05_05_090000_create_package_test_tables.php rename to tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php diff --git a/tests/Resources/Database/Migrations/features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php b/tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php similarity index 100% rename from tests/Resources/Database/Migrations/features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php rename to tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php diff --git a/tests/TestCase.php b/tests/TestCase.php index 6a5808e..b669f65 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -16,11 +16,11 @@ abstract class TestCase extends OrchestraTestCase protected function setUp(): void { parent::setUp(); - $this->resourceFolder = __DIR__.'/Resources/'; + $this->resourceFolder = __DIR__ . '/Resources/'; } /** - * @param Application $app + * @param Application $app * @return array|string[] */ protected function getPackageProviders($app): array @@ -31,7 +31,7 @@ protected function getPackageProviders($app): array } /** - * @param Application $app + * @param Application $app * @return array */ protected function getPackageAliases($app): array @@ -41,7 +41,7 @@ protected function getPackageAliases($app): array } /** - * @param Application $app + * @param Application $app */ protected function getEnvironmentSetUp($app): void { @@ -88,7 +88,7 @@ public function getDoctrineConnection(DatabaseManager $dbManager): Connection if (array_key_exists($dbConfig['name'], $dbMap)) { $dbConfig['driver'] = $dbMap[$dbConfig['name']]; } - + $connectionParams = [ 'dbname' => $dbConfig['database'], @@ -100,4 +100,15 @@ public function getDoctrineConnection(DatabaseManager $dbManager): Connection return DriverManager::getConnection($connectionParams); } + + /** + * Get the application timezone. + * + * @param \Illuminate\Foundation\Application $app + * @return string|null + */ + protected function getApplicationTimezone($app): ?string + { + return 'Europe/Berlin'; + } } From 4297baf6ec39dd56984be51ca5e5d4eef502b1c1 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:10:47 +0200 Subject: [PATCH 05/57] added normalization classes. --- src/Config/migration-generator.php | 5 +- .../MigrationGeneratorServiceProvider.php | 18 +++-- src/Service/Generator/MigrationGenerator.php | 31 +++++++-- .../Generator/MigrationGeneratorInterface.php | 4 +- .../Processors/ConstraintProcessor.php | 8 +++ .../Processors/PivotProcessor.php | 8 +++ .../Processors/ProcessorInterface.php | 10 +++ .../SchemaNormalizationManager.php | 69 +++++++++++++++++++ .../SchemaNormalizationManagerInterface.php | 20 ++++++ 9 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 src/Service/Generator/Normalization/Processors/ConstraintProcessor.php create mode 100644 src/Service/Generator/Normalization/Processors/PivotProcessor.php create mode 100644 src/Service/Generator/Normalization/Processors/ProcessorInterface.php create mode 100644 src/Service/Generator/Normalization/SchemaNormalizationManager.php create mode 100644 src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 4e9373f..5cfe708 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -1,7 +1,7 @@ [ @@ -32,4 +32,7 @@ 'requires' => ['table'], ], ], + 'normalizer' => [ + + ], ]; \ No newline at end of file diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 91a0c27..9aa3c85 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -30,10 +30,10 @@ class MigrationGeneratorServiceProvider extends ServiceProvider */ public function boot(): void { - $this->loadViewsFrom(__DIR__.'/../Stubs/', 'migration-generator'); + $this->loadViewsFrom(__DIR__ . '/../Stubs/', 'migration-generator'); $this->publishes( [ - __DIR__.'/../Config/migration-generator.php' => config_path('migration-generator.php'), + __DIR__ . '/../Config/migration-generator.php' => config_path('migration-generator.php'), ], 'migration-generator' ); @@ -46,7 +46,7 @@ public function boot(): void */ public function register(): void { - $this->mergeConfigFrom(__DIR__.'/../Config/migration-generator.php', 'migration-generator'); + $this->mergeConfigFrom(__DIR__ . '/../Config/migration-generator.php', 'migration-generator'); $this->registerParserFactory(); $this->registerParser(); $this->registerCompilerEngine(); @@ -97,12 +97,12 @@ function (Application $app, array $params = []) { protected function getDefinitions(): array { - return (array) app('config')->get('migration-generator.definitions'); + return (array)app('config')->get('migration-generator.definitions'); } protected function getMapper(): array { - return (array) app('config')->get('migration-generator.mapper'); + return (array)app('config')->get('migration-generator.mapper'); } protected function registerDefinitionResolver(): void @@ -118,7 +118,7 @@ protected function registerDefinitionResolver(): void static function (Application $app, array $params) use ($definitions) { $key = 'connection'; if (!array_key_exists($key, $params)) { - throw new \InvalidArgumentException('missing key '.$key.' in params.'); + throw new \InvalidArgumentException('missing key ' . $key . ' in params.'); } return new DefinitionResolver($params[$key], $definitions); @@ -139,7 +139,7 @@ static function (Application $app, array $params) { $key = 'connectionName'; if (!array_key_exists($key, $params)) { - throw new \InvalidArgumentException('missing key '.$key.' in params.'); + throw new \InvalidArgumentException('missing key ' . $key . ' in params.'); } /** @@ -168,6 +168,10 @@ static function (Application $app, array $params) { ); } + protected function registerNormalizer(): void + { + } + protected function registerCompilerEngine(): void { $this->app->bind(ReplaceEngine::class, ReplaceEngine::class); diff --git a/src/Service/Generator/MigrationGenerator.php b/src/Service/Generator/MigrationGenerator.php index 8d85938..7579c9b 100644 --- a/src/Service/Generator/MigrationGenerator.php +++ b/src/Service/Generator/MigrationGenerator.php @@ -5,6 +5,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\MigrationCompilerInterface; use N3XT0R\MigrationGenerator\Service\Generator\DTO\MigrationTimingDto; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolverInterface; class MigrationGenerator implements MigrationGeneratorInterface @@ -12,13 +13,15 @@ class MigrationGenerator implements MigrationGeneratorInterface protected DefinitionResolverInterface $resolver; protected MigrationCompilerInterface $compiler; + + protected ?SchemaNormalizationManagerInterface $normalizationManager = null; protected string $migrationDir = ''; protected array $errorMessages = []; protected array $migrationFiles = []; public function __construct(DefinitionResolverInterface $resolver, MigrationCompilerInterface $compiler) { - $this->setMigrationDir(database_path().DIRECTORY_SEPARATOR.'migrations'.DIRECTORY_SEPARATOR); + $this->setMigrationDir(database_path() . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR); $this->setResolver($resolver); $this->setCompiler($compiler); } @@ -43,6 +46,16 @@ public function getCompiler(): MigrationCompilerInterface return $this->compiler; } + public function getNormalizationManager(): ?SchemaNormalizationManagerInterface + { + return $this->normalizationManager; + } + + public function setNormalizationManager(?SchemaNormalizationManagerInterface $normalizationManager): void + { + $this->normalizationManager = $normalizationManager; + } + /** * @return string */ @@ -52,7 +65,7 @@ public function getMigrationDir(): string } /** - * @param string $migrationDir + * @param string $migrationDir */ public function setMigrationDir(string $migrationDir): void { @@ -68,7 +81,7 @@ public function getErrorMessages(): array } /** - * @param array $errorMessages + * @param array $errorMessages */ public function setErrorMessages(array $errorMessages): void { @@ -89,7 +102,7 @@ public function getMigrationFiles(): array } /** - * @param array $migrationFiles + * @param array $migrationFiles */ public function setMigrationFiles(array $migrationFiles): void { @@ -99,7 +112,7 @@ public function setMigrationFiles(array $migrationFiles): void public function generateMigrationForTable( string $database, string $table, - MigrationTimingDto $timingDto = new MigrationTimingDto() + MigrationTimingDto $timingDto = new MigrationTimingDto(), ): bool { $this->setErrorMessages([]); $result = false; @@ -108,9 +121,15 @@ public function generateMigrationForTable( try { $schemaResult = $resolver->resolveTableSchema($database, $table); + + $normalizationManager = $this->getNormalizationManager(); + if ($normalizationManager) { + $schemaResult = $normalizationManager->normalize($schemaResult); + } + $compiler->generateByResult($schemaResult); $result = $compiler->writeToDisk( - 'Create'.ucfirst($table).'Table', + 'Create' . ucfirst($table) . 'Table', $this->getMigrationDir(), $timingDto, ); diff --git a/src/Service/Generator/MigrationGeneratorInterface.php b/src/Service/Generator/MigrationGeneratorInterface.php index 48787c8..9134988 100644 --- a/src/Service/Generator/MigrationGeneratorInterface.php +++ b/src/Service/Generator/MigrationGeneratorInterface.php @@ -15,11 +15,11 @@ public function __construct(DefinitionResolverInterface $resolver, MigrationComp public function setMigrationDir(string $migrationDir): void; public function getMigrationDir(): string; - + public function generateMigrationForTable( string $database, string $table, - MigrationTimingDto $timingDto + MigrationTimingDto $timingDto, ): bool; public function getMigrationFiles(): array; diff --git a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php new file mode 100644 index 0000000..fde5e3f --- /dev/null +++ b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php @@ -0,0 +1,8 @@ +addProcessor($processor); + } + } + + /** + * Adds a new processor to the normalization chain. + */ + public function addProcessor(ProcessorInterface|iterable $processor): void + { + $this->processors[] = $processor; + } + + public function getProcessors(): iterable + { + return $this->processors; + } + + public function setProcessors(iterable $processors = []): void + { + $this->processors = $processors; + } + + /** + * Executes all processors on the given schema result. + * + * @param ResultEntity $result + * @return ResultEntity + */ + public function normalize(ResultEntity $result): ResultEntity + { + $processors = $this->getProcessors(); + foreach ($processors as $processor) { + $result = $processor->process($result); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php new file mode 100644 index 0000000..2cf53e4 --- /dev/null +++ b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php @@ -0,0 +1,20 @@ + Date: Sat, 21 Jun 2025 13:15:47 +0200 Subject: [PATCH 06/57] added normalization classes. --- .../Normalization/Processors/ConstraintProcessor.php | 6 ++++++ .../Normalization/Processors/PivotProcessor.php | 6 ++++++ .../Normalization/Processors/ProcessorInterface.php | 2 +- .../Normalization/SchemaNormalizationManager.php | 11 +++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php index fde5e3f..ff7c8e9 100644 --- a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php +++ b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php @@ -2,7 +2,13 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; + class ConstraintProcessor implements ProcessorInterface { + public function __invoke(ResultEntity $result): ResultEntity + { + return $result; + } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index ddb9aef..7872526 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -2,7 +2,13 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; + class PivotProcessor implements ProcessorInterface { + public function __invoke(ResultEntity $result): ResultEntity + { + return $result; + } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php index 8de2e8f..78fcde7 100644 --- a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php +++ b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php @@ -6,5 +6,5 @@ interface ProcessorInterface { - public function process(ResultEntity $result): ResultEntity; + public function __invoke(ResultEntity $result): ResultEntity; } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 1d53b80..9ee007f 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -17,9 +17,9 @@ class SchemaNormalizationManager implements SchemaNormalizationManagerInterface { /** - * @var ProcessorInterface[] + * @var ProcessorInterface|\Closure[] */ - protected iterable $processors = []; + protected array $processors = []; /** * SchemaNormalizationManager constructor. @@ -36,7 +36,7 @@ public function __construct(iterable $processors = []) /** * Adds a new processor to the normalization chain. */ - public function addProcessor(ProcessorInterface|iterable $processor): void + public function addProcessor(ProcessorInterface|\Closure $processor): void { $this->processors[] = $processor; } @@ -61,7 +61,10 @@ public function normalize(ResultEntity $result): ResultEntity { $processors = $this->getProcessors(); foreach ($processors as $processor) { - $result = $processor->process($result); + if (!is_callable($processor)) { + throw new \LogicException('Processor is not callable.'); + } + $result = $processor($result); } return $result; From b9f28f7d5ff901f90bb5bc9a3f387190bb28941f Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:19:27 +0200 Subject: [PATCH 07/57] added normalization classes. --- .../Normalization/Processors/ConstraintProcessor.php | 2 +- .../Generator/Normalization/Processors/PivotProcessor.php | 2 +- .../Normalization/Processors/ProcessorInterface.php | 2 +- .../Generator/Normalization/SchemaNormalizationManager.php | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php index ff7c8e9..8556459 100644 --- a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php +++ b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php @@ -6,7 +6,7 @@ class ConstraintProcessor implements ProcessorInterface { - public function __invoke(ResultEntity $result): ResultEntity + public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity { return $result; } diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index 7872526..36ee94b 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -6,7 +6,7 @@ class PivotProcessor implements ProcessorInterface { - public function __invoke(ResultEntity $result): ResultEntity + public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity { return $result; } diff --git a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php index 78fcde7..3cda64d 100644 --- a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php +++ b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php @@ -6,5 +6,5 @@ interface ProcessorInterface { - public function __invoke(ResultEntity $result): ResultEntity; + public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity; } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 9ee007f..b50704f 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -60,11 +60,15 @@ public function setProcessors(iterable $processors = []): void public function normalize(ResultEntity $result): ResultEntity { $processors = $this->getProcessors(); + $previous = clone $result; + foreach ($processors as $processor) { if (!is_callable($processor)) { throw new \LogicException('Processor is not callable.'); } - $result = $processor($result); + $current = $processor($result, $previous); + $previous = $result; + $result = $current; } return $result; From d23f349eaadc37de6820302287c48c57bc26da1a Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:36:58 +0200 Subject: [PATCH 08/57] added normalization classes. --- .../Context/NormalizationContext.php | 41 +++++++++++++++++++ .../Processors/ConstraintProcessor.php | 14 ++++++- .../Processors/PivotProcessor.php | 5 ++- .../Processors/PrimaryKeyProcessor.php | 18 ++++++++ .../Processors/ProcessorInterface.php | 3 +- .../SchemaNormalizationManager.php | 41 ++++++++++--------- .../SchemaNormalizationManagerInterface.php | 2 +- 7 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 src/Service/Generator/Normalization/Context/NormalizationContext.php create mode 100644 src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php diff --git a/src/Service/Generator/Normalization/Context/NormalizationContext.php b/src/Service/Generator/Normalization/Context/NormalizationContext.php new file mode 100644 index 0000000..6ca1e72 --- /dev/null +++ b/src/Service/Generator/Normalization/Context/NormalizationContext.php @@ -0,0 +1,41 @@ +original = clone $entity; + $this->previous = clone $entity; + $this->current = $entity; + } + + public function getTableResults(string $tableName): array + { + return $this->current->getResults()[$tableName] ?? []; + } + + public function getCurrent(): ResultEntity + { + return $this->current; + } + + public function getPrevious(): ResultEntity + { + return $this->previous; + } + + + public function update(ResultEntity $new): void + { + $this->previous = clone $this->current; + $this->current = $new; + } +} \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php index 8556459..71d0cf2 100644 --- a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php +++ b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php @@ -3,11 +3,23 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; class ConstraintProcessor implements ProcessorInterface { - public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity + public function process(NormalizationContext $context): ResultEntity { + $result = $context->getCurrent(); + + foreach ($result->getResults() as $table => $tableData) { + // Beispiel: Normalize FK-Definitionsstruktur + if (isset($tableData['foreign_keys'])) { + // ... modifiziere $tableData ... + //$result->getResults()[$table]['foreign_keys'] = $this->normalizeFks($tableData['foreign_keys']); + } + } + + $context->update($result); return $result; } diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index 36ee94b..333d46e 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -3,12 +3,13 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; class PivotProcessor implements ProcessorInterface { - public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity + public function process(NormalizationContext $context): ResultEntity { - return $result; + return $context->getCurrent(); } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php b/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php new file mode 100644 index 0000000..99a5b94 --- /dev/null +++ b/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php @@ -0,0 +1,18 @@ +getCurrent(); + + + return $current; + } + +} \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php index 3cda64d..e01d387 100644 --- a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php +++ b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php @@ -3,8 +3,9 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; interface ProcessorInterface { - public function __invoke(ResultEntity $result, ?ResultEntity $previousResult = null): ResultEntity; + public function process(NormalizationContext $context): ResultEntity; } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index b50704f..368f200 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -3,6 +3,7 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\ProcessorInterface; /** @@ -17,14 +18,12 @@ class SchemaNormalizationManager implements SchemaNormalizationManagerInterface { /** - * @var ProcessorInterface|\Closure[] + * @var ProcessorInterface[] */ protected array $processors = []; /** - * SchemaNormalizationManager constructor. - * - * @param iterable|ProcessorInterface[] $processors + * @param iterable $processors */ public function __construct(iterable $processors = []) { @@ -36,41 +35,45 @@ public function __construct(iterable $processors = []) /** * Adds a new processor to the normalization chain. */ - public function addProcessor(ProcessorInterface|\Closure $processor): void + public function addProcessor(ProcessorInterface $processor): void { $this->processors[] = $processor; } + /** + * Returns all registered processors. + */ public function getProcessors(): iterable { return $this->processors; } + /** + * Replaces all processors. + */ public function setProcessors(iterable $processors = []): void { - $this->processors = $processors; + $this->processors = []; + foreach ($processors as $processor) { + $this->addProcessor($processor); + } } /** - * Executes all processors on the given schema result. + * Executes all processors on the given schema result using a shared context. * * @param ResultEntity $result * @return ResultEntity */ public function normalize(ResultEntity $result): ResultEntity { - $processors = $this->getProcessors(); - $previous = clone $result; - - foreach ($processors as $processor) { - if (!is_callable($processor)) { - throw new \LogicException('Processor is not callable.'); - } - $current = $processor($result, $previous); - $previous = $result; - $result = $current; + $context = new NormalizationContext($result); + + foreach ($this->processors as $processor) { + $updated = $processor->process($context); + $context->update($updated); } - return $result; + return $context->getCurrent(); } -} \ No newline at end of file +} diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php index 2cf53e4..5cfe857 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php @@ -12,7 +12,7 @@ public function __construct(iterable $processors = []); public function addProcessor(ProcessorInterface $processor): void; - public function normalize(ResultEntity $result): mixed; + public function normalize(ResultEntity $result): ResultEntity; public function getProcessors(): iterable; From 6ed180bc89480c9806b184f6a0f1daf36db320a8 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:38:42 +0200 Subject: [PATCH 09/57] added normalization classes. --- .../Context/NormalizationContext.php | 56 ++++++++++++++----- .../Processors/PrimaryKeyProcessor.php | 5 +- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/Service/Generator/Normalization/Context/NormalizationContext.php b/src/Service/Generator/Normalization/Context/NormalizationContext.php index 6ca1e72..2fe6101 100644 --- a/src/Service/Generator/Normalization/Context/NormalizationContext.php +++ b/src/Service/Generator/Normalization/Context/NormalizationContext.php @@ -4,38 +4,64 @@ use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; +/** + * Holds normalization state throughout the processing pipeline. + * + * Provides access to original, previous and current versions + * of the result for comparative or cumulative normalization steps. + */ class NormalizationContext { - protected readonly ResultEntity $original; - protected ResultEntity $previous; - protected ResultEntity $current; + private readonly ResultEntity $original; + private ResultEntity $previous; + private ResultEntity $current; - public function __construct(ResultEntity $entity) + public function __construct(ResultEntity $initial) { - $this->original = clone $entity; - $this->previous = clone $entity; - $this->current = $entity; + // Deep clone for immutability of original state + $this->original = clone $initial; + $this->previous = clone $initial; + $this->current = $initial; } - public function getTableResults(string $tableName): array - { - return $this->current->getResults()[$tableName] ?? []; - } - - public function getCurrent(): ResultEntity + /** + * Returns the original unmodified schema result. + */ + public function getOriginal(): ResultEntity { - return $this->current; + return $this->original; } + /** + * Returns the last state before the current processor ran. + */ public function getPrevious(): ResultEntity { return $this->previous; } + /** + * Returns the current schema state. + */ + public function getCurrent(): ResultEntity + { + return $this->current; + } + /** + * Updates the current state with a new result and stores the previous. + */ public function update(ResultEntity $new): void { $this->previous = clone $this->current; $this->current = $new; } -} \ No newline at end of file + + /** + * Returns the current table result for a given table name. + */ + public function getTableResults(string $tableName): array + { + return $this->current->getResults()[$tableName] ?? []; + } +} diff --git a/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php b/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php index 99a5b94..fca22e7 100644 --- a/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php @@ -9,10 +9,7 @@ class PrimaryKeyProcessor implements ProcessorInterface { public function process(NormalizationContext $context): ResultEntity { - $current = $context->getCurrent(); - - - return $current; + return $context->getCurrent(); } } \ No newline at end of file From 4ef27ebb052fbaad9a48d42b0acd610ac7cae91a Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:40:56 +0200 Subject: [PATCH 10/57] added normalization classes. --- .../Context/NormalizationContext.php | 47 ++++++++++++------- .../SchemaNormalizationManager.php | 3 +- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/Service/Generator/Normalization/Context/NormalizationContext.php b/src/Service/Generator/Normalization/Context/NormalizationContext.php index 2fe6101..23e19b9 100644 --- a/src/Service/Generator/Normalization/Context/NormalizationContext.php +++ b/src/Service/Generator/Normalization/Context/NormalizationContext.php @@ -18,50 +18,65 @@ class NormalizationContext public function __construct(ResultEntity $initial) { - // Deep clone for immutability of original state $this->original = clone $initial; $this->previous = clone $initial; $this->current = $initial; } - /** - * Returns the original unmodified schema result. - */ public function getOriginal(): ResultEntity { return $this->original; } - /** - * Returns the last state before the current processor ran. - */ public function getPrevious(): ResultEntity { return $this->previous; } - /** - * Returns the current schema state. - */ public function getCurrent(): ResultEntity { return $this->current; } - /** - * Updates the current state with a new result and stores the previous. - */ public function update(ResultEntity $new): void { $this->previous = clone $this->current; $this->current = $new; } - /** - * Returns the current table result for a given table name. - */ public function getTableResults(string $tableName): array { return $this->current->getResults()[$tableName] ?? []; } + + /** + * Checks whether current differs from previous. + */ + public function hasChanged(): bool + { + return $this->serializeEntity($this->current) !== $this->serializeEntity($this->previous); + } + + /** + * Returns basic diff information between current and previous for a specific table. + * Shows added and removed keys (not deep diffs). + */ + public function diffTable(string $tableName): array + { + $current = $this->getCurrent()->getResults()[$tableName] ?? []; + $previous = $this->getPrevious()->getResults()[$tableName] ?? []; + + $added = array_diff_key($current, $previous); + $removed = array_diff_key($previous, $current); + + return [ + 'added_keys' => array_keys($added), + 'removed_keys' => array_keys($removed), + ]; + } + + private function serializeEntity(ResultEntity $entity): string + { + return md5(json_encode($entity->getResults(), JSON_THROW_ON_ERROR)); + } } diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 368f200..24febd7 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -68,8 +68,9 @@ public function setProcessors(iterable $processors = []): void public function normalize(ResultEntity $result): ResultEntity { $context = new NormalizationContext($result); + $processors = $this->getProcessors(); - foreach ($this->processors as $processor) { + foreach ($processors as $processor) { $updated = $processor->process($context); $context->update($updated); } From d6c94f91414193244a50d12f6f53ce695f8c5b07 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sat, 21 Jun 2025 13:41:33 +0200 Subject: [PATCH 11/57] added normalization classes. --- .../Generator/Normalization/Context/NormalizationContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Generator/Normalization/Context/NormalizationContext.php b/src/Service/Generator/Normalization/Context/NormalizationContext.php index 23e19b9..174c918 100644 --- a/src/Service/Generator/Normalization/Context/NormalizationContext.php +++ b/src/Service/Generator/Normalization/Context/NormalizationContext.php @@ -54,7 +54,7 @@ public function getTableResults(string $tableName): array */ public function hasChanged(): bool { - return $this->serializeEntity($this->current) !== $this->serializeEntity($this->previous); + return $this->serializeEntity($this->getCurrent()) !== $this->serializeEntity($this->getPrevious()); } /** From a5cf0de309841324affe58f185ef15b531194be8 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 22 Jun 2025 21:29:34 +0200 Subject: [PATCH 12/57] changed tests class. --- tests/DbTestCase.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index 3efdb37..12fe3ce 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -8,14 +8,16 @@ class DbTestCase extends TestCase { - protected array $migrations = []; + protected array $migrations = [ + 'Database/Migrations/Default/', + ]; protected function setUp(): void { parent::setUp(); $migrations = $this->getMigrations(); foreach ($migrations as $migrationPath) { - $this->loadMigrationsFrom($migrationPath); + $this->loadMigrationsFrom($this->resourceFolder . $migrationPath); } $this->loadLaravelMigrations(['--database' => env('DB_CONNECTION', 'mysql')]); @@ -23,11 +25,6 @@ protected function setUp(): void public function getMigrations(): array { - if (0 === count($this->migrations)) { - $this->setMigrations([ - $this->resourceFolder . 'Database/Migrations/Default/', - ]); - } return $this->migrations; } From e2a5261041f27916ad51e760602342396a9df2a0 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:13:30 +0200 Subject: [PATCH 13/57] added pk entity, definition and mapping. --- src/Config/migration-generator.php | 22 +++++++--- .../Compiler/Mapper/AbstractMapper.php | 4 +- .../Generator/Compiler/Mapper/IndexMapper.php | 39 ++++++++++------- .../Compiler/Mapper/PrimaryKeyMapper.php | 31 ++++++++++++++ .../Generator/Compiler/MigrationCompiler.php | 28 +++++++------ .../Definition/Entity/AbstractIndexEntity.php | 18 ++++++++ .../Definition/Entity/ForeignKeyEntity.php | 21 +--------- .../Definition/Entity/IndexEntity.php | 21 +--------- .../Definition/Entity/PrimaryKeyEntity.php | 19 +++++++++ .../Definition/Entity/ResultEntity.php | 13 +++++- .../Definition/PrimaryKeyDefinition.php | 29 +++++++++++++ src/Service/Generator/MigrationGenerator.php | 1 + .../Generator/MigrationGeneratorInterface.php | 15 ++++++- .../Processors/ConstraintProcessor.php | 26 ------------ .../Processors/PivotProcessor.php | 40 +++++++++++++++++- .../Processors/PrimaryKeyProcessor.php | 15 ------- tests/DbTestCase.php | 7 +++- .../MigrationGeneratorNormalizedTest.php | 42 +++++++++++++++++++ .../Generator/MigrationGeneratorTest.php | 16 +++---- ...11109_create_all_main_and_pivot_tables.php | 18 ++++---- 20 files changed, 292 insertions(+), 133 deletions(-) create mode 100644 src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php create mode 100644 src/Service/Generator/Definition/Entity/AbstractIndexEntity.php create mode 100644 src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php create mode 100644 src/Service/Generator/Definition/PrimaryKeyDefinition.php delete mode 100644 src/Service/Generator/Normalization/Processors/ConstraintProcessor.php delete mode 100644 src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php create mode 100644 tests/Integration/Service/Generator/MigrationGeneratorNormalizedTest.php diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 5cfe708..43ed157 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -2,6 +2,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\Mapper; use N3XT0R\MigrationGenerator\Service\Generator\Definition; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\PivotProcessor; return [ 'definitions' => [ @@ -9,30 +10,41 @@ 'class' => Definition\TableDefinition::class, 'requires' => [], ], - 'index' => [ - 'class' => Definition\IndexDefinition::class, + 'primaryKey' => [ + 'class' => Definition\PrimaryKeyDefinition::class, 'requires' => ['table'], ], 'foreignKey' => [ 'class' => Definition\ForeignKeyDefinition::class, 'requires' => ['table'], ], + 'index' => [ + 'class' => Definition\IndexDefinition::class, + 'requires' => ['table', 'foreignKey'], + ], ], 'mapper' => [ 'table' => [ 'class' => Mapper\FieldMapper::class, 'requires' => [], ], - 'index' => [ - 'class' => Mapper\IndexMapper::class, + 'primaryKey' => [ + 'class' => Mapper\PrimaryKeyMapper::class, 'requires' => ['table'], ], 'foreignKey' => [ 'class' => Mapper\ForeignKeyMapper::class, 'requires' => ['table'], ], + 'index' => [ + 'class' => Mapper\IndexMapper::class, + 'requires' => ['table', 'foreignKey'], + ], ], 'normalizer' => [ - + 'pivot' => [ + 'class' => PivotProcessor::class, + 'requires' => ['primary', 'foreignKey', 'table'], + ], ], ]; \ No newline at end of file diff --git a/src/Service/Generator/Compiler/Mapper/AbstractMapper.php b/src/Service/Generator/Compiler/Mapper/AbstractMapper.php index 40dafbc..7f0e1b3 100644 --- a/src/Service/Generator/Compiler/Mapper/AbstractMapper.php +++ b/src/Service/Generator/Compiler/Mapper/AbstractMapper.php @@ -13,9 +13,9 @@ public function chainMethodsToString(array $methods): string if (0 !== count($methods)) { $result = '$table'; foreach ($methods as $method) { - $result .= '->'.$method; + $result .= '->' . $method; } - $result .= ';'.PHP_EOL.' '; + $result .= ';' . PHP_EOL . ' '; } diff --git a/src/Service/Generator/Compiler/Mapper/IndexMapper.php b/src/Service/Generator/Compiler/Mapper/IndexMapper.php index 9345abf..897333e 100644 --- a/src/Service/Generator/Compiler/Mapper/IndexMapper.php +++ b/src/Service/Generator/Compiler/Mapper/IndexMapper.php @@ -1,45 +1,56 @@ generateIndex($field); + dump($field); + if ($field instanceof ForeignKeyEntity) { + $foreignKeyNames[] = $field->getName(); + } + + if (!$field instanceof IndexEntity) { + continue; } + + + if (in_array($field->getName(), $foreignKeyNames, true)) { + continue; + } + + $result[] = $this->generateIndex($field); } return $result; } - public function generateIndex(IndexEntity $index): string + protected function generateIndex(IndexEntity $index): string { - if ('unique' === $index->getType()) { - $method = 'unique('; - } else { - $method = 'index('; - } + $method = $index->getType() === 'unique' ? 'unique(' : 'index('; $columns = $index->getColumns(); - if (1 < count($columns)) { + if (count($columns) > 1) { $method .= "['" . implode("', '", $columns) . "']"; } else { $method .= "'" . $columns[0] . "'"; } $method .= ", '" . $index->getName() . "')"; - $methods = [$method]; return $this->chainMethodsToString($methods); } - -} \ No newline at end of file +} diff --git a/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php b/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php new file mode 100644 index 0000000..297b09c --- /dev/null +++ b/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php @@ -0,0 +1,31 @@ +generatePrimary($field); + } + } + + return $result; + } + + public function generatePrimary(PrimaryKeyEntity $index): string + { + $columns = $index->getColumns(); + $columnList = "['" . implode("', '", $columns) . "']"; + $name = "'" . $index->getName() . "'"; + + return $this->chainMethodsToString([ + "primary($columnList, $name)" + ]); + } +} \ No newline at end of file diff --git a/src/Service/Generator/Compiler/MigrationCompiler.php b/src/Service/Generator/Compiler/MigrationCompiler.php index b15211a..e718edf 100644 --- a/src/Service/Generator/Compiler/MigrationCompiler.php +++ b/src/Service/Generator/Compiler/MigrationCompiler.php @@ -45,7 +45,7 @@ public function getMapper(): array } /** - * @param array $mapper + * @param array $mapper */ public function setMapper(array $mapper): void { @@ -71,7 +71,7 @@ public function getFilesystem(): Filesystem } /** - * @param Filesystem $filesystem + * @param Filesystem $filesystem */ public function setFilesystem(Filesystem $filesystem): void { @@ -87,7 +87,7 @@ public function getMigrationFiles(): array } /** - * @param array $migrationFiles + * @param array $migrationFiles */ public function setMigrationFiles(array $migrationFiles): void { @@ -122,11 +122,12 @@ public function generateByResult(ResultEntity $resultEntity, string $customMigra foreach ($sortedMapper as $mappingName) { $mapping = app()->make($mapper[$mappingName]['class']); - if ($mapping instanceof MapperInterface) { - $resultData = $resultEntity->getResultByTableNameAndKey($tableName, $mappingName); - foreach ($mapping->map($resultData) as $line) { - $columns[] = $line; - } + if (!$mapping instanceof MapperInterface) { + continue; + } + $resultData = $resultEntity->getResultByTableNameAndKey($tableName, $mappingName); + foreach ($mapping->map($resultData) as $line) { + $columns[] = $line; } } @@ -143,8 +144,8 @@ public function generateByResult(ResultEntity $resultEntity, string $customMigra private function resolveMigrationNamespace(string $customClass): string { return (!empty($customClass) && class_exists($customClass)) - ? 'use '.$customClass.';' - : 'use '.Migration::class.';'; + ? 'use ' . $customClass . ';' + : 'use ' . Migration::class . ';'; } private function extractClassFromNamespace(string $namespaceLine): string @@ -163,7 +164,8 @@ public function writeToDisk( $tpl = $this->getRenderedTemplate(); if (!empty($tpl)) { - $fileName = $this->generateFilename($name, + $fileName = $this->generateFilename( + $name, $timingDto->getCurrentAmount(), $timingDto->getMaxAmount(), $timingDto->getTimestamp() @@ -181,13 +183,13 @@ private function generateFilename(string $name, int $currentAmount, int $maxAmou ? $this->getHourMinuteSecondPrefix($currentAmount, $maxAmount, $timestamp) : date('Y_m_d_His'); - return $prefix.'_'.Str::snake($name).'.php'; + return $prefix . '_' . Str::snake($name) . '.php'; } private function writeTemplateToFile(string $path, string $fileName, string $content): bool { $filesystem = $this->getFilesystem(); - $filePath = $path.DIRECTORY_SEPARATOR.$fileName; + $filePath = $path . DIRECTORY_SEPARATOR . $fileName; $success = false; if ($filesystem->exists($path) && !$filesystem->exists($filePath)) { diff --git a/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php b/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php new file mode 100644 index 0000000..1e8eaf9 --- /dev/null +++ b/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php @@ -0,0 +1,18 @@ +name; + } + + public function setName(string $name): void + { + $this->name = $name; + } +} \ No newline at end of file diff --git a/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php b/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php index 86e5ee2..bf9571c 100644 --- a/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php +++ b/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php @@ -4,9 +4,8 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity; -class ForeignKeyEntity +class ForeignKeyEntity extends AbstractIndexEntity { - protected string $name = ''; protected string $localTable = ''; protected string $localColumn = ''; protected string $referencedTable = ''; @@ -14,22 +13,6 @@ class ForeignKeyEntity protected string $onDelete = ''; protected string $onUpdate = ''; - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - */ - public function setName(string $name): void - { - $this->name = $name; - } - /** * @return string */ @@ -61,7 +44,7 @@ public function setLocalColumn(string $localColumn): void { $this->localColumn = $localColumn; } - + /** * @return string diff --git a/src/Service/Generator/Definition/Entity/IndexEntity.php b/src/Service/Generator/Definition/Entity/IndexEntity.php index cb97390..f13ea9b 100644 --- a/src/Service/Generator/Definition/Entity/IndexEntity.php +++ b/src/Service/Generator/Definition/Entity/IndexEntity.php @@ -4,10 +4,9 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity; -class IndexEntity +class IndexEntity extends AbstractIndexEntity { protected string $type = ''; - protected string $name = ''; protected array $columns = []; @@ -24,22 +23,6 @@ public function setType(string $type): void $this->type = $type; } - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @param string $name - */ - public function setName(string $name): void - { - $this->name = $name; - } - /** * @return array */ @@ -55,5 +38,5 @@ public function setColumns(array $columns): void { $this->columns = $columns; } - + } \ No newline at end of file diff --git a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php new file mode 100644 index 0000000..3836380 --- /dev/null +++ b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php @@ -0,0 +1,19 @@ +columns; + } + + public function setColumns(array $columns): void + { + $this->columns = $columns; + } +} \ No newline at end of file diff --git a/src/Service/Generator/Definition/Entity/ResultEntity.php b/src/Service/Generator/Definition/Entity/ResultEntity.php index 49e73c9..f2dada7 100644 --- a/src/Service/Generator/Definition/Entity/ResultEntity.php +++ b/src/Service/Generator/Definition/Entity/ResultEntity.php @@ -48,7 +48,18 @@ public function getResultByTableNameAndKey(string $tableName, string $key): arra public function hasResultForTable(string $tableName): bool { - return array_key_exists($tableName, $this->results); + $results = $this->getResults(); + return array_key_exists($tableName, $results); + } + + public function getResultByTable(string $tableName) + { + $result = []; + if ($this->hasResultForTable($tableName)) { + $result = $this->getResults()[$tableName]; + } + + return $result; } public function hasResultForTableNameAndKey(string $tableName, string $key): bool diff --git a/src/Service/Generator/Definition/PrimaryKeyDefinition.php b/src/Service/Generator/Definition/PrimaryKeyDefinition.php new file mode 100644 index 0000000..c05cea8 --- /dev/null +++ b/src/Service/Generator/Definition/PrimaryKeyDefinition.php @@ -0,0 +1,29 @@ +getAttributeByName('tableName'); + $schema = $this->getSchema(); + + $result = []; + + $tableDetails = $schema->introspectTable($table); + $pk = $tableDetails->getPrimaryKey(); + + if ($pk !== null) { + $entity = new PrimaryKeyEntity(); + $entity->setColumns($pk->getColumns()); + $entity->setName($pk->getName()); + $result[] = $entity; + } + + return $result; + } + +} \ No newline at end of file diff --git a/src/Service/Generator/MigrationGenerator.php b/src/Service/Generator/MigrationGenerator.php index 7579c9b..134f249 100644 --- a/src/Service/Generator/MigrationGenerator.php +++ b/src/Service/Generator/MigrationGenerator.php @@ -124,6 +124,7 @@ public function generateMigrationForTable( $normalizationManager = $this->getNormalizationManager(); if ($normalizationManager) { + //dd($schemaResult); $schemaResult = $normalizationManager->normalize($schemaResult); } diff --git a/src/Service/Generator/MigrationGeneratorInterface.php b/src/Service/Generator/MigrationGeneratorInterface.php index 9134988..af0e5b3 100644 --- a/src/Service/Generator/MigrationGeneratorInterface.php +++ b/src/Service/Generator/MigrationGeneratorInterface.php @@ -6,6 +6,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\MigrationCompilerInterface; use N3XT0R\MigrationGenerator\Service\Generator\DTO\MigrationTimingDto; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolverInterface; interface MigrationGeneratorInterface @@ -14,8 +15,20 @@ public function __construct(DefinitionResolverInterface $resolver, MigrationComp public function setMigrationDir(string $migrationDir): void; - public function getMigrationDir(): string; + public function setResolver(DefinitionResolverInterface $resolver): void; + public function getResolver(): DefinitionResolverInterface; + + public function setCompiler(MigrationCompilerInterface $compiler): void; + + public function getCompiler(): MigrationCompilerInterface; + + public function getNormalizationManager(): ?SchemaNormalizationManagerInterface; + + public function setNormalizationManager(?SchemaNormalizationManagerInterface $normalizationManager): void; + + public function getMigrationDir(): string; + public function generateMigrationForTable( string $database, string $table, diff --git a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php b/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php deleted file mode 100644 index 71d0cf2..0000000 --- a/src/Service/Generator/Normalization/Processors/ConstraintProcessor.php +++ /dev/null @@ -1,26 +0,0 @@ -getCurrent(); - - foreach ($result->getResults() as $table => $tableData) { - // Beispiel: Normalize FK-Definitionsstruktur - if (isset($tableData['foreign_keys'])) { - // ... modifiziere $tableData ... - //$result->getResults()[$table]['foreign_keys'] = $this->normalizeFks($tableData['foreign_keys']); - } - } - - $context->update($result); - return $result; - } - -} \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index 333d46e..fe08811 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -9,7 +9,45 @@ class PivotProcessor implements ProcessorInterface { public function process(NormalizationContext $context): ResultEntity { - return $context->getCurrent(); + $result = $context->getCurrent(); + $results = $result->getResults(); + + foreach ($results as $tableName => $definition) { + $primary = $definition['primary'] ?? []; + + if (is_array($primary) && count($primary) > 1) { + $definition['columns'] = [ + 'id' => [ + 'type' => 'int', + 'primary' => true, + 'autoIncrement' => true, + ] + ] + $definition['columns']; + + foreach ($primary as $column) { + if (isset($definition['columns'][$column])) { + unset($definition['columns'][$column]['primary']); + $definition['columns'][$column]['foreign'] = $this->guessForeignTarget($column); + } + } + + // 3. Neue primary definition + $definition['primary'] = ['id']; + + $results[$tableName] = $definition; + dd($results); + $result->setResults($results); + } + } + + $context->update($result); + return $result; } + private function guessForeignTarget(string $column): string + { + // z. B. user_id → users.id + $name = rtrim($column, '_id') . 's'; + return "$name.id"; + } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php b/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php deleted file mode 100644 index fca22e7..0000000 --- a/src/Service/Generator/Normalization/Processors/PrimaryKeyProcessor.php +++ /dev/null @@ -1,15 +0,0 @@ -getCurrent(); - } - -} \ No newline at end of file diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index 12fe3ce..af92ad8 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -20,7 +20,12 @@ protected function setUp(): void $this->loadMigrationsFrom($this->resourceFolder . $migrationPath); } - $this->loadLaravelMigrations(['--database' => env('DB_CONNECTION', 'mysql')]); + $this->loadLaravelMigrations(['--database' => $this->getDatabaseFromEnv()]); + } + + protected function getDatabaseFromEnv(): string + { + return (string)env('DB_CONNECTION', 'mysql'); } public function getMigrations(): array diff --git a/tests/Integration/Service/Generator/MigrationGeneratorNormalizedTest.php b/tests/Integration/Service/Generator/MigrationGeneratorNormalizedTest.php new file mode 100644 index 0000000..e92faa4 --- /dev/null +++ b/tests/Integration/Service/Generator/MigrationGeneratorNormalizedTest.php @@ -0,0 +1,42 @@ +generator = $this->app->make( + MigrationGeneratorInterface::class, + ['connectionName' => $this->getDatabaseFromEnv()] + ); + } + + public function testGenerateMigrationForTable(): void + { + $path = $this->resourceFolder . 'ExpectedMigrations/'; + $this->generator->setMigrationDir($path); + $schemaNormalizationManager = new SchemaNormalizationManager([new PivotProcessor()]); + $this->generator->setNormalizationManager($schemaNormalizationManager); + $result = $this->generator->generateMigrationForTable($this->getDatabaseFromEnv(), 'role_customer'); + dd($this->generator->getErrorMessages()); + $this->assertTrue($result); + $files = $this->generator->getMigrationFiles(); + foreach ($files as $file) { + $this->assertFileExists($path . DIRECTORY_SEPARATOR . $file); + } + } +} \ No newline at end of file diff --git a/tests/Integration/Service/Generator/MigrationGeneratorTest.php b/tests/Integration/Service/Generator/MigrationGeneratorTest.php index a7918be..5cd6e24 100644 --- a/tests/Integration/Service/Generator/MigrationGeneratorTest.php +++ b/tests/Integration/Service/Generator/MigrationGeneratorTest.php @@ -9,30 +9,32 @@ class MigrationGeneratorTest extends DbTestCase { - protected $generator; + protected MigrationGeneratorInterface $generator; public function setUp(): void { parent::setUp(); - $this->generator = $this->app->make(MigrationGeneratorInterface::class, - ['connectionName' => env('DB_CONNECTION', 'mysql')]); + $this->generator = $this->app->make( + MigrationGeneratorInterface::class, + ['connectionName' => $this->getDatabaseFromEnv()] + ); } public function testGenerateMigrationForTable(): void { - $path = $this->resourceFolder.'ExpectedMigrations/'; + $path = $this->resourceFolder . 'ExpectedMigrations/'; $this->generator->setMigrationDir($path); $result = $this->generator->generateMigrationForTable('testing', 'fields_test'); $this->assertTrue($result); $files = $this->generator->getMigrationFiles(); foreach ($files as $file) { - $this->assertFileExists($path.DIRECTORY_SEPARATOR.$file); + $this->assertFileExists($path . DIRECTORY_SEPARATOR . $file); } } public function testGenerateMigrationForTableWithUnknownTableReturnsFalse(): void { - $path = $this->resourceFolder.'ExpectedMigrations/'; + $path = $this->resourceFolder . 'ExpectedMigrations/'; $this->generator->setMigrationDir($path); $result = $this->generator->generateMigrationForTable('testing', uniqid('test', true)); $this->assertFalse($result); @@ -41,7 +43,7 @@ public function testGenerateMigrationForTableWithUnknownTableReturnsFalse(): voi public function tearDown(): void { - $files = glob($this->resourceFolder.'ExpectedMigrations/*'); + $files = glob($this->resourceFolder . 'ExpectedMigrations/*'); foreach ($files as $file) { if (is_file($file)) { unlink($file); diff --git a/tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php b/tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php index aff7db1..f311e91 100644 --- a/tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php +++ b/tests/Resources/Database/Migrations/Features/schema-normalization/2025_06_21_011109_create_all_main_and_pivot_tables.php @@ -4,11 +4,10 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { public function up(): void { - Schema::create('users', function (Blueprint $table) { + Schema::create('customers', function (Blueprint $table) { $table->unsignedBigInteger('id')->primary(); $table->string('name'); }); @@ -38,13 +37,14 @@ public function up(): void $table->string('name'); }); - Schema::create('role_user', function (Blueprint $table) { + Schema::create('role_customer', function (Blueprint $table) { $table->unsignedBigInteger('role_id'); - $table->unsignedBigInteger('user_id'); - $table->primary(['role_id', 'user_id']); + $table->unsignedBigInteger('customer_id'); + $table->string('sort')->index('test'); + $table->primary(['role_id', 'customer_id']); $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade'); }); Schema::create('order_product', function (Blueprint $table) { @@ -80,12 +80,12 @@ public function down(): void Schema::dropIfExists('product_tag'); Schema::dropIfExists('category_product'); Schema::dropIfExists('order_product'); - Schema::dropIfExists('role_user'); + Schema::dropIfExists('role_customers'); Schema::dropIfExists('tags'); Schema::dropIfExists('categories'); Schema::dropIfExists('orders'); Schema::dropIfExists('products'); Schema::dropIfExists('roles'); - Schema::dropIfExists('users'); + Schema::dropIfExists('customers'); } }; From 4d1bff4272ff22de7fbdae56763ab49751eff0da Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:21:51 +0200 Subject: [PATCH 14/57] moved logic to own method: collectMappedColumns --- .../Generator/Compiler/MigrationCompiler.php | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Service/Generator/Compiler/MigrationCompiler.php b/src/Service/Generator/Compiler/MigrationCompiler.php index e718edf..ae2c771 100644 --- a/src/Service/Generator/Compiler/MigrationCompiler.php +++ b/src/Service/Generator/Compiler/MigrationCompiler.php @@ -117,7 +117,25 @@ public function generateByResult(ResultEntity $resultEntity, string $customMigra $migrationNamespace = $this->resolveMigrationNamespace($customMigrationClass); $migrationClass = $this->extractClassFromNamespace($migrationNamespace); + $columns = $this->collectMappedColumns($sortedMapper, $mapper, $resultEntity, $tableName); + + $data = [ + 'migrationNamespace' => $migrationNamespace, + 'migrationClass' => $migrationClass, + 'tableName' => $tableName, + 'columns' => $columns, + ]; + + $this->setRenderedTemplate($this->render('migration-generator::CreateTableStub', $data)); + } + + protected function collectMappedColumns( + array $sortedMapper, + array $mapper, + ResultEntity $resultEntity, + string $tableName + ): array { $columns = []; foreach ($sortedMapper as $mappingName) { @@ -125,22 +143,17 @@ public function generateByResult(ResultEntity $resultEntity, string $customMigra if (!$mapping instanceof MapperInterface) { continue; } + $resultData = $resultEntity->getResultByTableNameAndKey($tableName, $mappingName); foreach ($mapping->map($resultData) as $line) { $columns[] = $line; } } - $data = [ - 'migrationNamespace' => $migrationNamespace, - 'migrationClass' => $migrationClass, - 'tableName' => $tableName, - 'columns' => $columns, - ]; - - $this->setRenderedTemplate($this->render('migration-generator::CreateTableStub', $data)); + return $columns; } + private function resolveMigrationNamespace(string $customClass): string { return (!empty($customClass) && class_exists($customClass)) From f471811cca2f4a8617676e011655e8992904d8c0 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:35:37 +0200 Subject: [PATCH 15/57] moved logic to multiple mehtods. --- .../Generator/Resolver/DefinitionResolver.php | 74 +++++++++++++------ 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/src/Service/Generator/Resolver/DefinitionResolver.php b/src/Service/Generator/Resolver/DefinitionResolver.php index 1a6f661..11930f0 100644 --- a/src/Service/Generator/Resolver/DefinitionResolver.php +++ b/src/Service/Generator/Resolver/DefinitionResolver.php @@ -4,6 +4,7 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Resolver; use Doctrine\DBAL\Connection as DoctrineConnection; +use Doctrine\DBAL\Schema\AbstractSchemaManager; use N3XT0R\MigrationGenerator\Service\Generator\Definition\DefinitionInterface; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use N3XT0R\MigrationGenerator\Service\Generator\Sort\TopSort; @@ -27,45 +28,72 @@ public function resolveTableSchema(string $schema, string $table): ResultEntity $definitions = $this->getDefinitions(); $sortedDefinitions = TopSort::sort($definitions); $connection = $this->getDoctrineConnection(); - $schemaManager = $connection->createSchemaManager(); - if (false === $schemaManager->tablesExist($table)) { - throw new \InvalidArgumentException('Table ' . $table . ' not exists!'); + + $this->assertTableExists($schemaManager, $table); + + $definitionResult = $this->generateDefinitionResult( + $schemaManager, + $sortedDefinitions, + $definitions, + $schema, + $table + ); + + return $this->buildResultEntity($table, $definitionResult); + } + + + protected function assertTableExists($schemaManager, string $table): void + { + if (!$schemaManager->tablesExist($table)) { + throw new \InvalidArgumentException("Table {$table} not exists!"); } + } + + protected function generateDefinitionResult( + AbstractSchemaManager $schemaManager, + array $sortedDefinitions, + array $definitions, + string $schema, + string $table + ): array { $definitionResult = []; foreach ($sortedDefinitions as $name) { $definitionClass = $this->getDefinitionByName($name); - if (null !== $schemaManager && $definitionClass instanceof DefinitionInterface) { - $dependencies = $definitions[$name]['requires']; - $definitionClass->setAttributes( - [ - 'database' => $schema, - 'tableName' => $table, - ] - ); - - foreach ($dependencies as $dependency) { - if (array_key_exists($dependency, $definitionResult[$table])) { - $definitionClass->addAttribute($dependency, $definitionResult[$table][$dependency]); - } - } - $definitionClass->setSchema($schemaManager); - $definitionClass->generate(); + if (!$definitionClass instanceof DefinitionInterface) { + continue; + } - if (!array_key_exists($table, $definitionResult)) { - $definitionResult[$table] = []; - } + $definitionClass->setAttributes([ + 'database' => $schema, + 'tableName' => $table, + ]); - $definitionResult[$table][$name] = $definitionClass->getResult(); + foreach ($definitions[$name]['requires'] as $dependency) { + if (isset($definitionResult[$table][$dependency])) { + $definitionClass->addAttribute($dependency, $definitionResult[$table][$dependency]); + } } + + $definitionClass->setSchema($schemaManager); + $definitionClass->generate(); + + $definitionResult[$table][$name] = $definitionClass->getResult(); } + return $definitionResult; + } + + protected function buildResultEntity(string $table, array $definitionResult): ResultEntity + { $result = new ResultEntity(); $result->setTableName($table); $result->setResults($definitionResult); return $result; } + } \ No newline at end of file From 2a15b0c47f94286267bcd9ec673986fa0dc324c3 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:36:29 +0200 Subject: [PATCH 16/57] dump removed. --- src/Service/Generator/Compiler/Mapper/IndexMapper.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Service/Generator/Compiler/Mapper/IndexMapper.php b/src/Service/Generator/Compiler/Mapper/IndexMapper.php index 897333e..8af228e 100644 --- a/src/Service/Generator/Compiler/Mapper/IndexMapper.php +++ b/src/Service/Generator/Compiler/Mapper/IndexMapper.php @@ -17,7 +17,6 @@ public function map(array $data): array $result = []; $foreignKeyNames = []; foreach ($data as $field) { - dump($field); if ($field instanceof ForeignKeyEntity) { $foreignKeyNames[] = $field->getName(); } @@ -30,7 +29,7 @@ public function map(array $data): array if (in_array($field->getName(), $foreignKeyNames, true)) { continue; } - + $result[] = $this->generateIndex($field); } From d3059b5be3e8b89523777839aad8ca26a682a509 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:39:06 +0200 Subject: [PATCH 17/57] fixed generation of indexes. --- src/Service/Generator/Definition/IndexDefinition.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/Generator/Definition/IndexDefinition.php b/src/Service/Generator/Definition/IndexDefinition.php index 5ae83ad..3acb9d8 100644 --- a/src/Service/Generator/Definition/IndexDefinition.php +++ b/src/Service/Generator/Definition/IndexDefinition.php @@ -12,7 +12,7 @@ class IndexDefinition extends AbstractDefinition protected function generateData(): array { $table = $this->getAttributeByName('tableName'); - $tableResult = (array) $this->getAttributeByName('table'); + $tableResult = (array)$this->getAttributeByName('table'); $schema = $this->getSchema(); $result = []; @@ -43,7 +43,7 @@ protected function generateIndexes(array $indexes): array $combinedIndexes[$index->getName()] = $indexEntity; } - return $combinedIndexes; + return array_values($combinedIndexes); } } \ No newline at end of file From 82e719835cac876c6b92fced301b0e8930166f21 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:42:08 +0200 Subject: [PATCH 18/57] fixed generation of indexes. --- src/Service/Generator/Compiler/MigrationCompiler.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Service/Generator/Compiler/MigrationCompiler.php b/src/Service/Generator/Compiler/MigrationCompiler.php index ae2c771..a679fd1 100644 --- a/src/Service/Generator/Compiler/MigrationCompiler.php +++ b/src/Service/Generator/Compiler/MigrationCompiler.php @@ -137,6 +137,7 @@ protected function collectMappedColumns( string $tableName ): array { $columns = []; + $tableResults = $resultEntity->getResultByTable($tableName); foreach ($sortedMapper as $mappingName) { $mapping = app()->make($mapper[$mappingName]['class']); @@ -144,9 +145,12 @@ protected function collectMappedColumns( continue; } - $resultData = $resultEntity->getResultByTableNameAndKey($tableName, $mappingName); - foreach ($mapping->map($resultData) as $line) { - $columns[] = $line; + if (!isset($tableResults[$mappingName])) { + continue; + } + + foreach ($mapping->map($tableResults[$mappingName]) as $entity) { + $columns[] = $entity; } } From 32f47ba5a8028926b7c3688ce88091dba3a94ba2 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 00:42:21 +0200 Subject: [PATCH 19/57] fixed generation of indexes. --- src/Service/Generator/Definition/Entity/ResultEntity.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Generator/Definition/Entity/ResultEntity.php b/src/Service/Generator/Definition/Entity/ResultEntity.php index f2dada7..fb1eed7 100644 --- a/src/Service/Generator/Definition/Entity/ResultEntity.php +++ b/src/Service/Generator/Definition/Entity/ResultEntity.php @@ -52,7 +52,7 @@ public function hasResultForTable(string $tableName): bool return array_key_exists($tableName, $results); } - public function getResultByTable(string $tableName) + public function getResultByTable(string $tableName): array { $result = []; if ($this->hasResultForTable($tableName)) { From 628227db6a073b3b12bb884cd171b115264c7a3d Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:43:30 +0200 Subject: [PATCH 20/57] fixed generation of indexes. --- tests/DbTestCase.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index af92ad8..ea45a04 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -4,9 +4,13 @@ namespace Tests; +use Illuminate\Foundation\Testing\RefreshDatabase; + class DbTestCase extends TestCase { + use RefreshDatabase; + protected array $migrations = [ 'Database/Migrations/Default/', From ef1fbf840940fde404488d915878b0ba13536bba Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:43:52 +0200 Subject: [PATCH 21/57] fixed generation of indexes. --- .../Definition/Entity/AbstractIndexEntity.php | 14 +++++ .../Definition/Entity/ForeignKeyEntity.php | 2 + .../Definition/Entity/IndexEntity.php | 2 + .../Definition/Entity/PrimaryKeyEntity.php | 2 + .../Generator/Definition/TableDefinition.php | 2 +- .../Generator/Resolver/DefinitionResolver.php | 55 ++++++++++++++++++- 6 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php b/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php index 1e8eaf9..2ab0c9e 100644 --- a/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php +++ b/src/Service/Generator/Definition/Entity/AbstractIndexEntity.php @@ -6,6 +6,8 @@ abstract class AbstractIndexEntity { protected string $name = ''; + protected string $indexType = ''; + public function getName(): string { return $this->name; @@ -15,4 +17,16 @@ public function setName(string $name): void { $this->name = $name; } + + public function getIndexType(): string + { + return $this->indexType; + } + + public function setIndexType(string $indexType): void + { + $this->indexType = $indexType; + } + + } \ No newline at end of file diff --git a/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php b/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php index bf9571c..7c2bc55 100644 --- a/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php +++ b/src/Service/Generator/Definition/Entity/ForeignKeyEntity.php @@ -13,6 +13,8 @@ class ForeignKeyEntity extends AbstractIndexEntity protected string $onDelete = ''; protected string $onUpdate = ''; + protected string $indexType = 'foreignKey'; + /** * @return string */ diff --git a/src/Service/Generator/Definition/Entity/IndexEntity.php b/src/Service/Generator/Definition/Entity/IndexEntity.php index f13ea9b..5073e3c 100644 --- a/src/Service/Generator/Definition/Entity/IndexEntity.php +++ b/src/Service/Generator/Definition/Entity/IndexEntity.php @@ -9,6 +9,8 @@ class IndexEntity extends AbstractIndexEntity protected string $type = ''; protected array $columns = []; + protected string $indexType = 'index'; + public function getType(): string { diff --git a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php index 3836380..4ef28bf 100644 --- a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php +++ b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php @@ -7,6 +7,8 @@ class PrimaryKeyEntity extends AbstractIndexEntity protected array $columns = []; + protected string $indexType = 'primaryKey'; + public function getColumns(): array { return $this->columns; diff --git a/src/Service/Generator/Definition/TableDefinition.php b/src/Service/Generator/Definition/TableDefinition.php index e28dd7c..027f0b0 100644 --- a/src/Service/Generator/Definition/TableDefinition.php +++ b/src/Service/Generator/Definition/TableDefinition.php @@ -140,7 +140,7 @@ private function prepareFloatingField(FieldEntity $fieldEntity, Column $column): $type = $fieldEntity->getType(); if (true === $unsigned && 'float' !== $type) { - $fieldEntity->setType('unsigned'.ucfirst($type)); + $fieldEntity->setType('unsigned' . ucfirst($type)); } elseif (true === $unsigned) { $fieldEntity->addOption('unsigned', $unsigned); } diff --git a/src/Service/Generator/Resolver/DefinitionResolver.php b/src/Service/Generator/Resolver/DefinitionResolver.php index 11930f0..55ddc44 100644 --- a/src/Service/Generator/Resolver/DefinitionResolver.php +++ b/src/Service/Generator/Resolver/DefinitionResolver.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Connection as DoctrineConnection; use Doctrine\DBAL\Schema\AbstractSchemaManager; use N3XT0R\MigrationGenerator\Service\Generator\Definition\DefinitionInterface; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\AbstractIndexEntity; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use N3XT0R\MigrationGenerator\Service\Generator\Sort\TopSort; @@ -91,9 +92,61 @@ protected function buildResultEntity(string $table, array $definitionResult): Re { $result = new ResultEntity(); $result->setTableName($table); - $result->setResults($definitionResult); + $result->setResults($this->getUniqueIndexes($table, $definitionResult)); return $result; } + + protected function getUniqueIndexes(string $table, array $definitionResult): array + { + // Prepare output + $result = []; + + // Flatten all AbstractIndexEntitys into a flat list by name + $indexEntitiesByName = []; + + foreach ($definitionResult[$table] as $type => $definitions) { + foreach ($definitions as $key => $definition) { + // If not index entity, pass through unmodified + if (!$definition instanceof AbstractIndexEntity) { + $result[$type][$key] = $definition; + continue; + } + + $name = $definition->getName(); + $indexType = $definition->getIndexType(); + + // Group index-type entities by name + if (!isset($indexEntitiesByName[$name])) { + $indexEntitiesByName[$name] = []; + } + + $indexEntitiesByName[$name][] = $definition; + } + } + + // Resolve index-name conflicts: keep foreignKey if present + foreach ($indexEntitiesByName as $name => $entities) { + // Determine if there's a foreignKey among them + $preferred = null; + foreach ($entities as $entity) { + if ($entity->getIndexType() === 'foreignKey') { + $preferred = $entity; + break; + } + } + + // If no foreignKey, pick first one (arbitrary fallback) + if (!$preferred) { + $preferred = $entities[0]; + } + + $indexType = $preferred->getIndexType(); + $result[$indexType][$name] = $preferred; + } + + return [$table => $result]; + } + } \ No newline at end of file From 86270731f0362f8d04bf94d205d6252931906c8b Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:44:50 +0200 Subject: [PATCH 22/57] fixed generation of indexes. --- phpunit.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/phpunit.xml b/phpunit.xml index f776bf3..1b84043 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -35,6 +35,7 @@ ./tests/Integration ./tests/Integration/Service/Generator/Definition/AbstractTableDefinitionTest.php + ./tests/Integration/Service/Generator/Definition/MigrationGeneratorNormalizedTest.php From 7ea0eedcd6c7274bcd521173ddbaaba73802a60b Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:47:50 +0200 Subject: [PATCH 23/57] fixed generation of indexes. --- src/Config/migration-generator.php | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 43ed157..0746665 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -2,7 +2,6 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\Mapper; use N3XT0R\MigrationGenerator\Service\Generator\Definition; -use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\PivotProcessor; return [ 'definitions' => [ @@ -10,10 +9,6 @@ 'class' => Definition\TableDefinition::class, 'requires' => [], ], - 'primaryKey' => [ - 'class' => Definition\PrimaryKeyDefinition::class, - 'requires' => ['table'], - ], 'foreignKey' => [ 'class' => Definition\ForeignKeyDefinition::class, 'requires' => ['table'], @@ -28,10 +23,7 @@ 'class' => Mapper\FieldMapper::class, 'requires' => [], ], - 'primaryKey' => [ - 'class' => Mapper\PrimaryKeyMapper::class, - 'requires' => ['table'], - ], + 'foreignKey' => [ 'class' => Mapper\ForeignKeyMapper::class, 'requires' => ['table'], @@ -41,10 +33,5 @@ 'requires' => ['table', 'foreignKey'], ], ], - 'normalizer' => [ - 'pivot' => [ - 'class' => PivotProcessor::class, - 'requires' => ['primary', 'foreignKey', 'table'], - ], - ], + ]; \ No newline at end of file From 910887684214e11160cab9daa04fd3b2076844a2 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:49:20 +0200 Subject: [PATCH 24/57] fixed generation of indexes. --- src/Config/migration-generator.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 0746665..43ed157 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -2,6 +2,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\Mapper; use N3XT0R\MigrationGenerator\Service\Generator\Definition; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\PivotProcessor; return [ 'definitions' => [ @@ -9,6 +10,10 @@ 'class' => Definition\TableDefinition::class, 'requires' => [], ], + 'primaryKey' => [ + 'class' => Definition\PrimaryKeyDefinition::class, + 'requires' => ['table'], + ], 'foreignKey' => [ 'class' => Definition\ForeignKeyDefinition::class, 'requires' => ['table'], @@ -23,7 +28,10 @@ 'class' => Mapper\FieldMapper::class, 'requires' => [], ], - + 'primaryKey' => [ + 'class' => Mapper\PrimaryKeyMapper::class, + 'requires' => ['table'], + ], 'foreignKey' => [ 'class' => Mapper\ForeignKeyMapper::class, 'requires' => ['table'], @@ -33,5 +41,10 @@ 'requires' => ['table', 'foreignKey'], ], ], - + 'normalizer' => [ + 'pivot' => [ + 'class' => PivotProcessor::class, + 'requires' => ['primary', 'foreignKey', 'table'], + ], + ], ]; \ No newline at end of file From 4b1de2e48ffe9ee8844fbab7b11d1b821fb52eca Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 01:53:08 +0200 Subject: [PATCH 25/57] fixed generation of indexes. --- phpunit.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml b/phpunit.xml index 1b84043..5825345 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -35,7 +35,7 @@ ./tests/Integration ./tests/Integration/Service/Generator/Definition/AbstractTableDefinitionTest.php - ./tests/Integration/Service/Generator/Definition/MigrationGeneratorNormalizedTest.php + ./tests/Integration/Service/Generator/MigrationGeneratorNormalizedTest.php From 8e83b2eb3004f92f617d625a77b010dbcf502a4a Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 02:20:32 +0200 Subject: [PATCH 26/57] fixed generation of indexes. --- .../Definition/Entity/PrimaryKeyEntity.php | 2 +- .../Generator/Resolver/DefinitionResolver.php | 60 ++++++++++++------- .../Compiler/MigrationCompilerTest.php | 33 ++++++++++ ...5_05_090000_create_package_test_tables.php | 7 +-- .../migrationCompilerResultWithPrimary.txt | 37 ++++++++++++ 5 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt diff --git a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php index 4ef28bf..9349d32 100644 --- a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php +++ b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php @@ -7,7 +7,7 @@ class PrimaryKeyEntity extends AbstractIndexEntity protected array $columns = []; - protected string $indexType = 'primaryKey'; + protected string $indexType = 'primary'; public function getColumns(): array { diff --git a/src/Service/Generator/Resolver/DefinitionResolver.php b/src/Service/Generator/Resolver/DefinitionResolver.php index 55ddc44..31b8c79 100644 --- a/src/Service/Generator/Resolver/DefinitionResolver.php +++ b/src/Service/Generator/Resolver/DefinitionResolver.php @@ -100,53 +100,67 @@ protected function buildResultEntity(string $table, array $definitionResult): Re protected function getUniqueIndexes(string $table, array $definitionResult): array { - // Prepare output $result = []; - // Flatten all AbstractIndexEntitys into a flat list by name + // Flatten all AbstractIndexEntitys into flat list grouped by name $indexEntitiesByName = []; foreach ($definitionResult[$table] as $type => $definitions) { foreach ($definitions as $key => $definition) { - // If not index entity, pass through unmodified if (!$definition instanceof AbstractIndexEntity) { + // Pass through unchanged $result[$type][$key] = $definition; continue; } $name = $definition->getName(); - $indexType = $definition->getIndexType(); - // Group index-type entities by name - if (!isset($indexEntitiesByName[$name])) { - $indexEntitiesByName[$name] = []; - } - - $indexEntitiesByName[$name][] = $definition; + // Save both the entity and its origin type + $indexEntitiesByName[$name][] = [ + 'entity' => $definition, + 'originType' => $type, + ]; } } - // Resolve index-name conflicts: keep foreignKey if present - foreach ($indexEntitiesByName as $name => $entities) { - // Determine if there's a foreignKey among them - $preferred = null; - foreach ($entities as $entity) { - if ($entity->getIndexType() === 'foreignKey') { - $preferred = $entity; - break; + // Resolve duplicates by name, with rules + foreach ($indexEntitiesByName as $name => $entries) { + $hasPrimary = false; + $hasForeign = false; + $primaryEntry = null; + $foreignEntry = null; + $fallbackEntry = null; + + foreach ($entries as $entry) { + $entity = $entry['entity']; + $indexType = $entity->getIndexType(); + + if ($indexType === 'primary') { + $hasPrimary = true; + $primaryEntry = $entry; + } elseif ($indexType === 'foreignKey') { + $hasForeign = true; + $foreignEntry = $entry; + } elseif (!$fallbackEntry) { + $fallbackEntry = $entry; } } - // If no foreignKey, pick first one (arbitrary fallback) - if (!$preferred) { - $preferred = $entities[0]; + // Always keep primary + if ($hasPrimary && $primaryEntry !== null) { + $result[$primaryEntry['originType']][$name] = $primaryEntry['entity']; } - $indexType = $preferred->getIndexType(); - $result[$indexType][$name] = $preferred; + // Prefer foreign if present and not already added + if ($hasForeign && $foreignEntry !== null) { + $result[$foreignEntry['originType']][$name] = $foreignEntry['entity']; + } elseif ($fallbackEntry !== null && !$hasForeign && !$hasPrimary) { + $result[$fallbackEntry['originType']][$name] = $fallbackEntry['entity']; + } } return [$table => $result]; } + } \ No newline at end of file diff --git a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php index 99a7fdf..ed6b56d 100644 --- a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php +++ b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php @@ -6,6 +6,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\MigrationCompilerInterface; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\FieldEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\PrimaryKeyEntity; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use Tests\Resources\Classes\CustomMigration; use Tests\TestCase; @@ -42,6 +43,38 @@ public function testGenerateByResultWorks(): void self::assertStringEqualsFile($this->resourceFolder . '/ExpectedResults/migrationCompilerResult.txt', $result); } + public function testGenerateByResultWorksWithPrimaryKey(): void + { + $fieldEntity = new FieldEntity(); + $fieldEntity->setColumnName('test'); + $fieldEntity->setType('bigInteger'); + $fieldEntity->addOption('unsigned', true); + $fieldEntity->addArgument('autoIncrement', true); + $result = new ResultEntity(); + $result->setTableName('test_table'); + + $primaryKey = new PrimaryKeyEntity(); + $primaryKey->setColumns(['test']); + $primaryKey->setName('PRIMARY'); + + $result->setResults( + [ + 'test_table' => [ + 'table' => [$fieldEntity], + 'primary' => $primaryKey, + ], + ] + ); + dd($result->getResults()); + $this->compiler->generateByResult($result); + $result = $this->compiler->getRenderedTemplate(); + file_put_contents($this->resourceFolder . '/ExpectedResults/migrationCompilerResultWithPrimary.txt', $result); + self::assertStringEqualsFile( + $this->resourceFolder . '/ExpectedResults/migrationCompilerResultWithPrimary.txt', + $result + ); + } + public function testGenerateByResultWorksWithCustomMigration(): void { $fieldEntity = new FieldEntity(); diff --git a/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php b/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php index 3495fb4..a5ab548 100644 --- a/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php +++ b/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php @@ -2,18 +2,17 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { public function up(): void { Schema::create( 'fields_test', static function (Blueprint $table) { - $table->bigInteger('id', true)->unsigned(); + $table->bigInteger('id', true)->unsigned()->primary(); $table->smallInteger('small_int')->nullable(); $table->mediumInteger('medium_int')->unique(); $table->tinyInteger('tiny_int')->default(1)->comment('my tiny int'); diff --git a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt new file mode 100644 index 0000000..d99b849 --- /dev/null +++ b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt @@ -0,0 +1,37 @@ +bigInteger('test', true)->unsigned(); + + } + ); + } + + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::dropIfExists('test_table'); + } + +}; From 4694b7f8ae1b6317f235a3c61b424678cf35484b Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 02:25:02 +0200 Subject: [PATCH 27/57] fixed generation of indexes. --- .../Generator/Resolver/DefinitionResolver.php | 91 ++++++++++++------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/src/Service/Generator/Resolver/DefinitionResolver.php b/src/Service/Generator/Resolver/DefinitionResolver.php index 31b8c79..4867c62 100644 --- a/src/Service/Generator/Resolver/DefinitionResolver.php +++ b/src/Service/Generator/Resolver/DefinitionResolver.php @@ -100,66 +100,89 @@ protected function buildResultEntity(string $table, array $definitionResult): Re protected function getUniqueIndexes(string $table, array $definitionResult): array { - $result = []; + $flatIndexEntities = $this->extractIndexEntitiesWithOrigin($definitionResult[$table]); + $filteredIndexes = $this->filterDuplicateIndexesByName($flatIndexEntities); + $rebuilt = $this->rebuildDefinitionResult($definitionResult[$table], $filteredIndexes); + + return [$table => $rebuilt]; + } - // Flatten all AbstractIndexEntitys into flat list grouped by name + + protected function extractIndexEntitiesWithOrigin(array $definitions): array + { $indexEntitiesByName = []; - foreach ($definitionResult[$table] as $type => $definitions) { - foreach ($definitions as $key => $definition) { + foreach ($definitions as $originType => $entries) { + foreach ($entries as $definition) { if (!$definition instanceof AbstractIndexEntity) { - // Pass through unchanged - $result[$type][$key] = $definition; continue; } $name = $definition->getName(); - // Save both the entity and its origin type $indexEntitiesByName[$name][] = [ 'entity' => $definition, - 'originType' => $type, + 'originType' => $originType, ]; } } - // Resolve duplicates by name, with rules + return $indexEntitiesByName; + } + + protected function filterDuplicateIndexesByName(array $indexEntitiesByName): array + { + $filtered = []; + foreach ($indexEntitiesByName as $name => $entries) { - $hasPrimary = false; - $hasForeign = false; - $primaryEntry = null; - $foreignEntry = null; - $fallbackEntry = null; + $primary = null; + $foreign = null; + $fallback = null; foreach ($entries as $entry) { - $entity = $entry['entity']; - $indexType = $entity->getIndexType(); - - if ($indexType === 'primary') { - $hasPrimary = true; - $primaryEntry = $entry; - } elseif ($indexType === 'foreignKey') { - $hasForeign = true; - $foreignEntry = $entry; - } elseif (!$fallbackEntry) { - $fallbackEntry = $entry; + $type = $entry['entity']->getIndexType(); + + if ($type === 'primary') { + $primary = $entry; + } elseif ($type === 'foreignKey') { + $foreign = $entry; + } elseif (!$fallback) { + $fallback = $entry; } } - // Always keep primary - if ($hasPrimary && $primaryEntry !== null) { - $result[$primaryEntry['originType']][$name] = $primaryEntry['entity']; + if ($primary) { + $filtered[$name] = $primary; + } elseif ($foreign) { + $filtered[$name] = $foreign; + } elseif ($fallback) { + $filtered[$name] = $fallback; } + } - // Prefer foreign if present and not already added - if ($hasForeign && $foreignEntry !== null) { - $result[$foreignEntry['originType']][$name] = $foreignEntry['entity']; - } elseif ($fallbackEntry !== null && !$hasForeign && !$hasPrimary) { - $result[$fallbackEntry['originType']][$name] = $fallbackEntry['entity']; + return $filtered; + } + + protected function rebuildDefinitionResult(array $original, array $filteredIndexes): array + { + $result = []; + + // Erstmal alles übernehmen, was kein AbstractIndexEntity ist + foreach ($original as $type => $entries) { + foreach ($entries as $key => $entry) { + if (!$entry instanceof AbstractIndexEntity) { + $result[$type][$key] = $entry; + } } } - return [$table => $result]; + // Jetzt die gefilterten Index-Elemente einfügen, an Ursprungsposition + foreach ($filteredIndexes as $name => $entry) { + $origin = $entry['originType']; + $result[$origin][$name] = $entry['entity']; + } + + return $result; } From d988eb6264eb94acba44d5d0fc4d2f94bfb6ab75 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 02:28:21 +0200 Subject: [PATCH 28/57] fixed generation of indexes. --- .../Service/Generator/Compiler/MigrationCompilerTest.php | 4 +--- .../ExpectedResults/migrationCompilerResultWithPrimary.txt | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php index ed6b56d..b972b2e 100644 --- a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php +++ b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php @@ -61,14 +61,12 @@ public function testGenerateByResultWorksWithPrimaryKey(): void [ 'test_table' => [ 'table' => [$fieldEntity], - 'primary' => $primaryKey, + 'primaryKey' => [$primaryKey], ], ] ); - dd($result->getResults()); $this->compiler->generateByResult($result); $result = $this->compiler->getRenderedTemplate(); - file_put_contents($this->resourceFolder . '/ExpectedResults/migrationCompilerResultWithPrimary.txt', $result); self::assertStringEqualsFile( $this->resourceFolder . '/ExpectedResults/migrationCompilerResultWithPrimary.txt', $result diff --git a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt index d99b849..247c658 100644 --- a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt +++ b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt @@ -18,6 +18,7 @@ return new class extends Migration 'test_table', static function (Blueprint $table) { $table->bigInteger('test', true)->unsigned(); + $table->primary(['test'], 'PRIMARY'); } ); From de1319bf8aab9cc39684d471beb8ded73424d543 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 02:46:28 +0200 Subject: [PATCH 29/57] fixed generation of indexes. --- .../Definition/Entity/PrimaryKeyEntity.php | 2 +- .../Generator/Resolver/DefinitionResolver.php | 85 ++++++------------- .../migrationCompilerResultWithPrimary.txt | 38 --------- 3 files changed, 27 insertions(+), 98 deletions(-) delete mode 100644 tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt diff --git a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php index 9349d32..46979c4 100644 --- a/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php +++ b/src/Service/Generator/Definition/Entity/PrimaryKeyEntity.php @@ -7,7 +7,7 @@ class PrimaryKeyEntity extends AbstractIndexEntity protected array $columns = []; - protected string $indexType = 'primary'; + protected string $indexType = 'index'; public function getColumns(): array { diff --git a/src/Service/Generator/Resolver/DefinitionResolver.php b/src/Service/Generator/Resolver/DefinitionResolver.php index 4867c62..c33bc2d 100644 --- a/src/Service/Generator/Resolver/DefinitionResolver.php +++ b/src/Service/Generator/Resolver/DefinitionResolver.php @@ -100,89 +100,56 @@ protected function buildResultEntity(string $table, array $definitionResult): Re protected function getUniqueIndexes(string $table, array $definitionResult): array { - $flatIndexEntities = $this->extractIndexEntitiesWithOrigin($definitionResult[$table]); - $filteredIndexes = $this->filterDuplicateIndexesByName($flatIndexEntities); - $rebuilt = $this->rebuildDefinitionResult($definitionResult[$table], $filteredIndexes); + // Step 1: Separate index-like definitions + [$indexEntitiesByName, $result] = $this->extractIndexEntities($definitionResult[$table]); - return [$table => $rebuilt]; + // Step 2: Resolve conflicts (e.g. foreignKey vs. index) but retain original group + $this->mergeResolvedIndexes($result, $indexEntitiesByName); + + return [$table => $result]; } - protected function extractIndexEntitiesWithOrigin(array $definitions): array + protected function extractIndexEntities(array $definitionsByType): array { $indexEntitiesByName = []; + $result = []; - foreach ($definitions as $originType => $entries) { - foreach ($entries as $definition) { + foreach ($definitionsByType as $type => $definitions) { + foreach ($definitions as $key => $definition) { if (!$definition instanceof AbstractIndexEntity) { + $result[$type][$key] = $definition; continue; } $name = $definition->getName(); - - $indexEntitiesByName[$name][] = [ - 'entity' => $definition, - 'originType' => $originType, - ]; + $indexEntitiesByName[$name][] = ['entity' => $definition, 'originType' => $type]; } } - return $indexEntitiesByName; + return [$indexEntitiesByName, $result]; } - protected function filterDuplicateIndexesByName(array $indexEntitiesByName): array + + protected function mergeResolvedIndexes(array &$result, array $indexEntitiesByName): void { - $filtered = []; - - foreach ($indexEntitiesByName as $name => $entries) { - $primary = null; - $foreign = null; - $fallback = null; - - foreach ($entries as $entry) { - $type = $entry['entity']->getIndexType(); - - if ($type === 'primary') { - $primary = $entry; - } elseif ($type === 'foreignKey') { - $foreign = $entry; - } elseif (!$fallback) { - $fallback = $entry; + foreach ($indexEntitiesByName as $name => $candidates) { + $preferred = null; + foreach ($candidates as $item) { + if ($item['entity']->getIndexType() === 'foreignKey') { + $preferred = $item; + break; } } - if ($primary) { - $filtered[$name] = $primary; - } elseif ($foreign) { - $filtered[$name] = $foreign; - } elseif ($fallback) { - $filtered[$name] = $fallback; - } - } - - return $filtered; - } - - protected function rebuildDefinitionResult(array $original, array $filteredIndexes): array - { - $result = []; - - // Erstmal alles übernehmen, was kein AbstractIndexEntity ist - foreach ($original as $type => $entries) { - foreach ($entries as $key => $entry) { - if (!$entry instanceof AbstractIndexEntity) { - $result[$type][$key] = $entry; - } + // fallback if no foreignKey + if (!$preferred) { + $preferred = $candidates[0]; } - } - // Jetzt die gefilterten Index-Elemente einfügen, an Ursprungsposition - foreach ($filteredIndexes as $name => $entry) { - $origin = $entry['originType']; - $result[$origin][$name] = $entry['entity']; + $originType = $preferred['originType']; + $result[$originType][$name] = $preferred['entity']; } - - return $result; } diff --git a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt deleted file mode 100644 index 247c658..0000000 --- a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt +++ /dev/null @@ -1,38 +0,0 @@ -bigInteger('test', true)->unsigned(); - $table->primary(['test'], 'PRIMARY'); - - } - ); - } - - - /** - * Reverse the migrations. - * - * @return void - */ - public function down(): void - { - Schema::dropIfExists('test_table'); - } - -}; From 20010d30b9a34d3e9acef8ef5536ac59fa9041ca Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 03:02:24 +0200 Subject: [PATCH 30/57] fixed generation of indexes. --- .../Default/2020_05_05_090000_create_package_test_tables.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php b/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php index a5ab548..79e39f5 100644 --- a/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php +++ b/tests/Resources/Database/Migrations/Default/2020_05_05_090000_create_package_test_tables.php @@ -12,7 +12,7 @@ public function up(): void Schema::create( 'fields_test', static function (Blueprint $table) { - $table->bigInteger('id', true)->unsigned()->primary(); + $table->bigInteger('id', true)->unsigned(); $table->smallInteger('small_int')->nullable(); $table->mediumInteger('medium_int')->unique(); $table->tinyInteger('tiny_int')->default(1)->comment('my tiny int'); From 9a81e2955e77e6b3cbf45237b6186f6507cccd8b Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Mon, 23 Jun 2025 03:04:39 +0200 Subject: [PATCH 31/57] fixed generation of indexes. --- tests/DbTestCase.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/DbTestCase.php b/tests/DbTestCase.php index ea45a04..af92ad8 100644 --- a/tests/DbTestCase.php +++ b/tests/DbTestCase.php @@ -4,13 +4,9 @@ namespace Tests; -use Illuminate\Foundation\Testing\RefreshDatabase; - class DbTestCase extends TestCase { - use RefreshDatabase; - protected array $migrations = [ 'Database/Migrations/Default/', From 28288d7cf311156e26bcc846433fb07710bb0fac Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Thu, 26 Jun 2025 20:07:47 +0200 Subject: [PATCH 32/57] tests fixed. --- .../Service/Generator/Definition/IndexDefinitionTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php b/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php index e1d2c29..714e30d 100644 --- a/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php +++ b/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php @@ -44,7 +44,7 @@ public function testGenerateResultShouldWork(): array } /** - * @param array $result + * @param array $result */ #[Depends('testGenerateResultShouldWork')] public function testIndexWorks(array $result): void @@ -52,7 +52,7 @@ public function testIndexWorks(array $result): void /** * @var IndexEntity $index */ - $index = $result['testi']; + $index = $result[1]; $this->assertEquals('index', $index->getType()); $this->assertEquals('testi', $index->getName()); $this->assertEquals( @@ -64,7 +64,7 @@ public function testIndexWorks(array $result): void } /** - * @param array $result + * @param array $result */ #[Depends('testGenerateResultShouldWork')] public function testUniqueIndexWorks(array $result): void @@ -72,7 +72,7 @@ public function testUniqueIndexWorks(array $result): void /** * @var IndexEntity $index */ - $index = $result['fields_test_medium_int_unique']; + $index = $result[0]; $this->assertEquals('unique', $index->getType()); $this->assertEquals( [ From ffd5019993a46f18b4bad74a5062df0123fbce01 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Thu, 26 Jun 2025 20:10:32 +0200 Subject: [PATCH 33/57] tests fixed. --- .../Compiler/MigrationCompilerTest.php | 1 + .../migrationCompilerResultWithPrimary.txt | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt diff --git a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php index b972b2e..9c3c464 100644 --- a/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php +++ b/tests/Integration/Service/Generator/Compiler/MigrationCompilerTest.php @@ -66,6 +66,7 @@ public function testGenerateByResultWorksWithPrimaryKey(): void ] ); $this->compiler->generateByResult($result); + $result = $this->compiler->getRenderedTemplate(); self::assertStringEqualsFile( $this->resourceFolder . '/ExpectedResults/migrationCompilerResultWithPrimary.txt', diff --git a/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt new file mode 100644 index 0000000..247c658 --- /dev/null +++ b/tests/Resources/ExpectedResults/migrationCompilerResultWithPrimary.txt @@ -0,0 +1,38 @@ +bigInteger('test', true)->unsigned(); + $table->primary(['test'], 'PRIMARY'); + + } + ); + } + + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::dropIfExists('test_table'); + } + +}; From b49ad5f21fdad4439196aaf53fa338aad11180d3 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Thu, 26 Jun 2025 20:17:15 +0200 Subject: [PATCH 34/57] added composer.lock, why the fuck it was not added. --- .gitignore | 1 - composer.lock | 8910 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 8910 insertions(+), 1 deletion(-) create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore index 1644880..97092f7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ /.idea/ /.qlty/ build/ -composer.lock .phpunit.result.cache /coverage/clover.xml .hadolint.yaml diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..3a45a07 --- /dev/null +++ b/composer.lock @@ -0,0 +1,8910 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "ba33551578ed90dbb89834899e4db97f", + "packages": [ + { + "name": "brick/math", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "6.8.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.13.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2025-03-29T13:50:30+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-12-11T17:09:12+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, + { + "name": "doctrine/cache", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2022-05-20T20:07:39+00:00" + }, + { + "name": "doctrine/dbal", + "version": "3.9.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/4a4e2eed3134036ee36a147ee0dac037dfa17868", + "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "13.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.1", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "9.6.23", + "slevomat/coding-standard": "8.16.2", + "squizlabs/php_codesniffer": "3.13.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/console": "^4.4|^5.4|^6.0|^7.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.9.5" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2025-06-15T22:40:05+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + }, + "time": "2025-04-07T20:06:18+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2024-05-22T20:47:39+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-02-03T10:55:03+00:00" + }, + { + "name": "laravel/framework", + "version": "v12.19.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/4e6ec689ef704bb4bd282f29d9dd658dfb4fb262", + "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262", + "shasum": "" + }, + "require": { + "brick/math": "^0.11|^0.12|^0.13", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.7", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.0.0", + "pda/pheanstalk": "^5.0.6|^7.0.0", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "predis/predis": "^2.3|^3.0", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3|^3.0).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "12.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-06-18T12:56:23+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.5" + }, + "time": "2025-02-11T13:34:40+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2025-03-19T13:51:03+00:00" + }, + { + "name": "league/commonmark", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-05-05T12:20:28+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e", + "reference": "2203e3151755d874bb2943649dae1eb8533ac93e", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3|^2", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2|^2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.30.0" + }, + "time": "2025-06-25T13:29:59+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10", + "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0" + }, + "time": "2025-05-21T10:34:19+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, + { + "name": "marcj/topsort", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/marcj/topsort.php.git", + "reference": "387086c2db60ee0a27ac5df588c0f0b30c6bdc4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marcj/topsort.php/zipball/387086c2db60ee0a27ac5df588c0f0b30c6bdc4b", + "reference": "387086c2db60ee0a27ac5df588c0f0b30c6bdc4b", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master", + "phpunit/phpunit": "~4.0", + "symfony/console": "~2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "MJS\\TopSort\\": "src/", + "MJS\\TopSort\\Tests\\": "tests/Tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marc J. Schmidt", + "email": "marc@marcjschmidt.de" + } + ], + "description": "High-Performance TopSort/Dependency resolving algorithm", + "keywords": [ + "dependency resolving", + "topological sort", + "topsort" + ], + "support": { + "issues": "https://github.com/marcj/topsort.php/issues", + "source": "https://github.com/marcj/topsort.php/tree/1.1.0" + }, + "time": "2016-11-19T14:58:11+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.10.1", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1fd1935b2d90aef2f093c5e35f7ae1257c448d00", + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3.12 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.75.0", + "kylekatarnls/multi-tester": "^2.5.3", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpunit/phpunit": "^10.5.46", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-06-21T15:19:35+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.4" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" + }, + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.7", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.4" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.7" + }, + "time": "2025-06-03T04:55:08+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123", + "reference": "dfa08f390e509967a15c22493dc0bac5733d9123", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.2.6" + }, + "require-dev": { + "illuminate/console": "^11.44.7", + "laravel/pint": "^1.22.0", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0 || ^3.8.2", + "phpstan/phpstan": "^1.12.25", + "phpstan/phpstan-strict-rules": "^1.6.2", + "symfony/var-dumper": "^7.2.6", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2025-05-08T08:14:37+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.9.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.25", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.9.0" + }, + "time": "2025-06-25T14:20:11+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^7.2" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T10:34:04+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:19:49+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-22T09:11:45+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-30T19:00:26+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "4236baf01609667d53b20371486228231eb135fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", + "reference": "4236baf01609667d53b20371486228231eb135fd", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-12T14:48:23+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:47:32+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T09:51:09+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-19T08:51:26+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-17T09:11:12+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8e213820c5fea844ecea29203d2a308019007c15" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T20:43:28+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-20T20:19:01+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "nikic/php-parser": "<5.0", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-29T07:19:49+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-27T08:32:26+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-24T14:28:13+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-27T18:39:23+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.3", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "59a123a3d459c5a23055802237cb317f609867e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5", + "reference": "59a123a3d459c5a23055802237cb317f609867e5", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.3" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-06-16T00:02:10+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.12.27", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "dev", + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-06-05T13:55:57+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-04-29T12:36:36+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.5.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" + }, + "time": "2025-05-31T08:24:38+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.2", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "reference": "60207965f9b7b7a4ce15a0f75d57f9dadb105bdb", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", + "php": "^8.2.0", + "symfony/console": "^7.3.0" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-06-25T02:12:12+00:00" + }, + { + "name": "orchestra/canvas", + "version": "v10.0.2", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas.git", + "reference": "94f732350e5c6d7136ff7b0fd05a90079dd77deb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas/zipball/94f732350e5c6d7136ff7b0fd05a90079dd77deb", + "reference": "94f732350e5c6d7136ff7b0fd05a90079dd77deb", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^12.3.0", + "illuminate/database": "^12.3.0", + "illuminate/filesystem": "^12.3.0", + "illuminate/support": "^12.3.0", + "orchestra/canvas-core": "^10.0.1", + "orchestra/sidekick": "^1.1.0", + "orchestra/testbench-core": "^10.1.0", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31", + "symfony/yaml": "^7.2.0" + }, + "require-dev": { + "laravel/framework": "^12.3.0", + "laravel/pint": "^1.21", + "mockery/mockery": "^1.6.12", + "phpstan/phpstan": "^2.1.8", + "phpunit/phpunit": "^11.5.13", + "spatie/laravel-ray": "^1.40.1" + }, + "bin": [ + "canvas" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Orchestra\\Canvas\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas/tree/v10.0.2" + }, + "time": "2025-04-05T16:01:25+00:00" + }, + { + "name": "orchestra/canvas-core", + "version": "v10.0.1", + "source": { + "type": "git", + "url": "https://github.com/orchestral/canvas-core.git", + "reference": "22b6515e7a070e1c45c8a3a9819f8b6cb0234173" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/canvas-core/zipball/22b6515e7a070e1c45c8a3a9819f8b6cb0234173", + "reference": "22b6515e7a070e1c45c8a3a9819f8b6cb0234173", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "composer/semver": "^3.0", + "illuminate/console": "^12.0", + "illuminate/support": "^12.0", + "orchestra/sidekick": "^1.0.2", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31" + }, + "require-dev": { + "laravel/framework": "^12.0", + "laravel/pint": "^1.21", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.0", + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^11.5.7", + "symfony/yaml": "^7.2" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Orchestra\\Canvas\\Core\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Orchestra\\Canvas\\Core\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Code Generators Builder for Laravel Applications and Packages", + "support": { + "issues": "https://github.com/orchestral/canvas/issues", + "source": "https://github.com/orchestral/canvas-core/tree/v10.0.1" + }, + "time": "2025-02-19T04:17:05+00:00" + }, + { + "name": "orchestra/sidekick", + "version": "v1.2.13", + "source": { + "type": "git", + "url": "https://github.com/orchestral/sidekick.git", + "reference": "aa41994f872cc49a420da42f50886605c0d85f15" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/sidekick/zipball/aa41994f872cc49a420da42f50886605c0d85f15", + "reference": "aa41994f872cc49a420da42f50886605c0d85f15", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "php": "^8.1", + "symfony/polyfill-php83": "^1.32" + }, + "require-dev": { + "fakerphp/faker": "^1.21", + "laravel/framework": "^10.48.29|^11.44.7|^12.1.1|^13.0", + "laravel/pint": "^1.4", + "mockery/mockery": "^1.5.1", + "orchestra/testbench-core": "^8.37.0|^9.14.0|^10.0|^11.0", + "phpstan/phpstan": "^2.1.14", + "phpunit/phpunit": "^10.0|^11.0|^12.0", + "symfony/process": "^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Eloquent/functions.php", + "src/Http/functions.php", + "src/functions.php" + ], + "psr-4": { + "Orchestra\\Sidekick\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Packages Toolkit Utilities and Helpers for Laravel", + "support": { + "issues": "https://github.com/orchestral/sidekick/issues", + "source": "https://github.com/orchestral/sidekick/tree/v1.2.13" + }, + "time": "2025-06-23T05:09:50+00:00" + }, + { + "name": "orchestra/testbench", + "version": "v10.4.0", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench.git", + "reference": "36674005fb1b5cddfd953b8c440507394af8695d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/36674005fb1b5cddfd953b8c440507394af8695d", + "reference": "36674005fb1b5cddfd953b8c440507394af8695d", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.23", + "laravel/framework": "^12.8.0", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^10.4.0", + "orchestra/workbench": "^10.0.6", + "php": "^8.2", + "phpunit/phpunit": "^11.5.3|^12.0.1", + "symfony/process": "^7.2", + "symfony/yaml": "^7.2", + "vlucas/phpdotenv": "^5.6.1" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Laravel Testing Helper for Packages Development", + "homepage": "https://packages.tools/testbench/", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench/tree/v10.4.0" + }, + "time": "2025-06-08T23:29:04+00:00" + }, + { + "name": "orchestra/testbench-core", + "version": "v10.4.0", + "source": { + "type": "git", + "url": "https://github.com/orchestral/testbench-core.git", + "reference": "d1c45a7be15c4d99fb7d48685b038dd39acc7b84" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/d1c45a7be15c4d99fb7d48685b038dd39acc7b84", + "reference": "d1c45a7be15c4d99fb7d48685b038dd39acc7b84", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "orchestra/sidekick": "~1.1.16|^1.2.12", + "php": "^8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-php83": "^1.32" + }, + "conflict": { + "brianium/paratest": "<7.3.0|>=8.0.0", + "laravel/framework": "<12.8.0|>=13.0.0", + "laravel/serializable-closure": "<1.3.0|>=2.0.0 <2.0.3|>=3.0.0", + "nunomaduro/collision": "<8.0.0|>=9.0.0", + "phpunit/phpunit": "<10.5.35|>=11.0.0 <11.5.3|12.0.0|>=12.3.0" + }, + "require-dev": { + "fakerphp/faker": "^1.24", + "laravel/framework": "^12.8.0", + "laravel/pint": "^1.22", + "laravel/serializable-closure": "^1.3|^2.0.4", + "mockery/mockery": "^1.6.10", + "phpstan/phpstan": "^2.1.14", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "spatie/laravel-ray": "^1.40.2", + "symfony/process": "^7.2.0", + "symfony/yaml": "^7.2.0", + "vlucas/phpdotenv": "^5.6.1" + }, + "suggest": { + "brianium/paratest": "Allow using parallel testing (^7.3).", + "ext-pcntl": "Required to use all features of the console signal trapping.", + "fakerphp/faker": "Allow using Faker for testing (^1.23).", + "laravel/framework": "Required for testing (^12.8.0).", + "mockery/mockery": "Allow using Mockery for testing (^1.6).", + "nunomaduro/collision": "Allow using Laravel style tests output and parallel testing (^8.0).", + "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^10.0).", + "phpunit/phpunit": "Allow using PHPUnit for testing (^10.5.35|^11.5.3|^12.0.1).", + "symfony/process": "Required to use Orchestra\\Testbench\\remote function (^7.2).", + "symfony/yaml": "Required for Testbench CLI (^7.2).", + "vlucas/phpdotenv": "Required for Testbench CLI (^5.6.1)." + }, + "bin": [ + "testbench" + ], + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Orchestra\\Testbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com", + "homepage": "https://github.com/crynobone" + } + ], + "description": "Testing Helper for Laravel Development", + "homepage": "https://packages.tools/testbench", + "keywords": [ + "BDD", + "TDD", + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/testbench/issues", + "source": "https://github.com/orchestral/testbench-core" + }, + "time": "2025-06-08T04:36:36+00:00" + }, + { + "name": "orchestra/workbench", + "version": "v10.0.6", + "source": { + "type": "git", + "url": "https://github.com/orchestral/workbench.git", + "reference": "4e8a5a68200971ddb9ce4abf26488838bf5c0812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/orchestral/workbench/zipball/4e8a5a68200971ddb9ce4abf26488838bf5c0812", + "reference": "4e8a5a68200971ddb9ce4abf26488838bf5c0812", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "fakerphp/faker": "^1.23", + "laravel/framework": "^12.1.1", + "laravel/pail": "^1.2.2", + "laravel/tinker": "^2.10.1", + "nunomaduro/collision": "^8.6", + "orchestra/canvas": "^10.0.2", + "orchestra/sidekick": "^1.1.0", + "orchestra/testbench-core": "^10.2.1", + "php": "^8.2", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.2", + "symfony/yaml": "^7.2" + }, + "require-dev": { + "laravel/pint": "^1.21.2", + "mockery/mockery": "^1.6.12", + "phpstan/phpstan": "^2.1.8", + "phpunit/phpunit": "^11.5.3|^12.0.1", + "spatie/laravel-ray": "^1.40.1" + }, + "suggest": { + "ext-pcntl": "Required to use all features of the console signal trapping." + }, + "type": "library", + "autoload": { + "psr-4": { + "Orchestra\\Workbench\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mior Muhammad Zaki", + "email": "crynobone@gmail.com" + } + ], + "description": "Workbench Companion for Laravel Packages Development", + "keywords": [ + "dev", + "laravel", + "laravel-packages", + "testing" + ], + "support": { + "issues": "https://github.com/orchestral/workbench/issues", + "source": "https://github.com/orchestral/workbench/tree/v10.0.6" + }, + "time": "2025-04-13T01:07:44+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.2" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" + } + ], + "time": "2025-06-18T08:56:18+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.24", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "6b07ab1047155cf38f82dd691787a277782271dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6b07ab1047155cf38f82dd691787a277782271dd", + "reference": "6b07ab1047155cf38f82dd691787a277782271dd", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.10", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.1", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.2", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.24" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-06-20T11:31:02+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.9", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "1b801844becfe648985372cb4b12ad6840245ace" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1b801844becfe648985372cb4b12ad6840245ace", + "reference": "1b801844becfe648985372cb4b12ad6840245ace", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.9" + }, + "time": "2025-06-23T02:35:06+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-07T06:57:01+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4", + "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/environment", + "type": "tidelift" + } + ], + "time": "2025-05-21T11:55:47+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-05T09:17:50+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-18T13:35:50+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "cea40a48279d58dc3efee8112634cb90141156c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/cea40a48279d58dc3efee8112634cb90141156c2", + "reference": "cea40a48279d58dc3efee8112634cb90141156c2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T10:10:33+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.2", + "ext-pdo_mysql": "*" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} From 485322838225e8ee54b5e8d39a057a10185cefbe Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Fri, 27 Jun 2025 07:17:20 +0200 Subject: [PATCH 35/57] test fixed. --- .../Definition/IndexDefinitionTest.php | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php b/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php index 714e30d..0b1ade5 100644 --- a/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php +++ b/tests/Integration/Service/Generator/Definition/IndexDefinitionTest.php @@ -49,10 +49,7 @@ public function testGenerateResultShouldWork(): array #[Depends('testGenerateResultShouldWork')] public function testIndexWorks(array $result): void { - /** - * @var IndexEntity $index - */ - $index = $result[1]; + $index = $this->getIndexByName('testi', $result); $this->assertEquals('index', $index->getType()); $this->assertEquals('testi', $index->getName()); $this->assertEquals( @@ -69,10 +66,7 @@ public function testIndexWorks(array $result): void #[Depends('testGenerateResultShouldWork')] public function testUniqueIndexWorks(array $result): void { - /** - * @var IndexEntity $index - */ - $index = $result[0]; + $index = $this->getIndexByName('fields_test_medium_int_unique', $result); $this->assertEquals('unique', $index->getType()); $this->assertEquals( [ @@ -82,5 +76,18 @@ public function testUniqueIndexWorks(array $result): void ); } + protected function getIndexByName(string $name, array $result): ?IndexEntity + { + $indexResult = null; + foreach ($result as $index) { + if ($index->getName() === $name) { + $indexResult = $index; + break; + } + } + self::assertInstanceOf(IndexEntity::class, $indexResult); + return $indexResult; + } + } \ No newline at end of file From 06e58ef3b6cf6f60ea6e780f9f507c7f802dbf52 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Fri, 27 Jun 2025 07:24:17 +0200 Subject: [PATCH 36/57] composer updated. --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 3a45a07..97d6ab7 100644 --- a/composer.lock +++ b/composer.lock @@ -7597,16 +7597,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.24", + "version": "11.5.25", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "6b07ab1047155cf38f82dd691787a277782271dd" + "reference": "864ab32b3ff52058f917c5b19b3cef821e4a4f1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6b07ab1047155cf38f82dd691787a277782271dd", - "reference": "6b07ab1047155cf38f82dd691787a277782271dd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/864ab32b3ff52058f917c5b19b3cef821e4a4f1b", + "reference": "864ab32b3ff52058f917c5b19b3cef821e4a4f1b", "shasum": "" }, "require": { @@ -7678,7 +7678,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.24" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.25" }, "funding": [ { @@ -7702,7 +7702,7 @@ "type": "tidelift" } ], - "time": "2025-06-20T11:31:02+00:00" + "time": "2025-06-27T04:36:07+00:00" }, { "name": "psy/psysh", From 610370518afec921f680bd6675b3d2081b660fa8 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 06:24:08 +0200 Subject: [PATCH 37/57] test added. --- .../Facades/SchemaParserFactoryFacadeTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/Unit/Facades/SchemaParserFactoryFacadeTest.php diff --git a/tests/Unit/Facades/SchemaParserFactoryFacadeTest.php b/tests/Unit/Facades/SchemaParserFactoryFacadeTest.php new file mode 100644 index 0000000..ac084a3 --- /dev/null +++ b/tests/Unit/Facades/SchemaParserFactoryFacadeTest.php @@ -0,0 +1,16 @@ + Date: Sun, 29 Jun 2025 06:31:40 +0200 Subject: [PATCH 38/57] tests added --- .../Entity/AbstractIndexEntityTest.php | 34 +++++++++++++++++++ .../Entity/PrimaryKeyDefinitionTest.php | 25 ++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/Unit/Generator/Definition/Entity/AbstractIndexEntityTest.php create mode 100644 tests/Unit/Generator/Definition/Entity/PrimaryKeyDefinitionTest.php diff --git a/tests/Unit/Generator/Definition/Entity/AbstractIndexEntityTest.php b/tests/Unit/Generator/Definition/Entity/AbstractIndexEntityTest.php new file mode 100644 index 0000000..dc8b96c --- /dev/null +++ b/tests/Unit/Generator/Definition/Entity/AbstractIndexEntityTest.php @@ -0,0 +1,34 @@ +entity = new class() extends AbstractIndexEntity { + }; + } + + public function testSetGetNameIsSame(): void + { + $name = uniqid('TEST_', true); + $this->entity->setName($name); + $gotName = $this->entity->getName(); + self::assertSame($name, $gotName); + } + + public function testSetGetIndexTypeIsSame(): void + { + $indexType = uniqid('TEST_', true); + $this->entity->setIndexType($indexType); + $gotIndexType = $this->entity->getIndexType(); + self::assertSame($indexType, $gotIndexType); + } +} \ No newline at end of file diff --git a/tests/Unit/Generator/Definition/Entity/PrimaryKeyDefinitionTest.php b/tests/Unit/Generator/Definition/Entity/PrimaryKeyDefinitionTest.php new file mode 100644 index 0000000..f3dbcb9 --- /dev/null +++ b/tests/Unit/Generator/Definition/Entity/PrimaryKeyDefinitionTest.php @@ -0,0 +1,25 @@ +entity = new PrimaryKeyEntity(); + } + + public function testSetGetColumnsWorks(): void + { + $columns = ['test', 'test2']; + $this->entity->setColumns($columns); + $gotColumns = $this->entity->getColumns(); + $this->assertSame($columns, $gotColumns); + } +} \ No newline at end of file From c9c32aa206af61b348cdd74841c66d797a5b170d Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 06:42:30 +0200 Subject: [PATCH 39/57] tests added --- .../Definition/Entity/ResultEntityTest.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php b/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php index 1892607..440895f 100644 --- a/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php +++ b/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php @@ -23,7 +23,7 @@ public function testSetAndGetResultsAreSame(): void $this->entity->setResults($results); $gotResults = $this->entity->getResults(); - $this->assertSame($results, $gotResults); + self::assertSame($results, $gotResults); } public function testSetAndGetTableNameIsSame(): void @@ -31,7 +31,7 @@ public function testSetAndGetTableNameIsSame(): void $tableName = uniqid('table', true); $this->entity->setTableName($tableName); $gotTableName = $this->entity->getTableName(); - $this->assertSame($tableName, $gotTableName); + self::assertSame($tableName, $gotTableName); } /** @@ -49,7 +49,7 @@ public function testHasResultForTable(string $tableName, bool $expectedResult): } $this->entity->setResults($value); - $this->assertSame($expectedResult, $this->entity->hasResultForTable($tableName)); + self::assertSame($expectedResult, $this->entity->hasResultForTable($tableName)); } /** @@ -69,7 +69,7 @@ public function testHasResultForTableNameAndKey(string $tableName, string $key, } $this->entity->setResults($value); - $this->assertSame($expectedResult, $this->entity->hasResultForTableNameAndKey($tableName, $key)); + self::assertSame($expectedResult, $this->entity->hasResultForTableNameAndKey($tableName, $key)); } public function testGetResultByTableNameAndKeyWorks(): void @@ -78,6 +78,15 @@ public function testGetResultByTableNameAndKeyWorks(): void $this->entity->setResults($results); $result = $this->entity->getResultByTableNameAndKey('testTable', 'testKey'); - $this->assertEquals(['test'], $result); + self::assertEquals(['test'], $result); + } + + public function testGetResultByTableNameAndKeyReturnsEmptyArray(): void + { + $results = ['testTable' => ['testKey' => ['test']]]; + $this->entity->setResults($results); + + $result = $this->entity->getResultByTableNameAndKey('testTable2', 'testKey'); + self::assertCount(0, $result); } } \ No newline at end of file From 6ec35c80e4c04f212b9c7813a16726c0474c772f Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 06:45:10 +0200 Subject: [PATCH 40/57] tests added --- .../Definition/Entity/ResultEntityTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php b/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php index 440895f..31c3640 100644 --- a/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php +++ b/tests/Unit/Generator/Definition/Entity/ResultEntityTest.php @@ -89,4 +89,20 @@ public function testGetResultByTableNameAndKeyReturnsEmptyArray(): void $result = $this->entity->getResultByTableNameAndKey('testTable2', 'testKey'); self::assertCount(0, $result); } + + public function testGetResultByTableWorks(): void + { + $results = ['testTable' => ['testKey' => ['test']]]; + $this->entity->setResults($results); + $result = $this->entity->getResultByTable('testTable'); + self::assertEquals($results['testTable'], $result); + } + + public function testGetResultByTableReturnsEmptyArray(): void + { + $results = ['testTable' => ['testKey' => ['test']]]; + $this->entity->setResults($results); + $result = $this->entity->getResultByTable('testTable2'); + self::assertCount(0, $result); + } } \ No newline at end of file From a82564820ca0c6fab140925d5e6096c6b7a086e4 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 07:42:19 +0200 Subject: [PATCH 41/57] feat: replace composite primary keys in pivot tables with a single 'id' column and remove original PK --- .../Compiler/Mapper/PrimaryKeyMapper.php | 7 ++- .../Processors/PivotProcessor.php | 51 +++++++------------ .../SchemaNormalizationManager.php | 1 + 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php b/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php index 297b09c..c411f22 100644 --- a/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php +++ b/src/Service/Generator/Compiler/Mapper/PrimaryKeyMapper.php @@ -22,10 +22,13 @@ public function generatePrimary(PrimaryKeyEntity $index): string { $columns = $index->getColumns(); $columnList = "['" . implode("', '", $columns) . "']"; - $name = "'" . $index->getName() . "'"; + + $methodCall = !empty($index->getName()) + ? "primary($columnList, '" . $index->getName() . "')" + : "primary($columnList)"; return $this->chainMethodsToString([ - "primary($columnList, $name)" + $methodCall ]); } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index fe08811..2a74d25 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -2,6 +2,8 @@ namespace N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\FieldEntity; +use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\PrimaryKeyEntity; use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; @@ -12,42 +14,27 @@ public function process(NormalizationContext $context): ResultEntity $result = $context->getCurrent(); $results = $result->getResults(); - foreach ($results as $tableName => $definition) { - $primary = $definition['primary'] ?? []; - - if (is_array($primary) && count($primary) > 1) { - $definition['columns'] = [ - 'id' => [ - 'type' => 'int', - 'primary' => true, - 'autoIncrement' => true, - ] - ] + $definition['columns']; - - foreach ($primary as $column) { - if (isset($definition['columns'][$column])) { - unset($definition['columns'][$column]['primary']); - $definition['columns'][$column]['foreign'] = $this->guessForeignTarget($column); - } - } - - // 3. Neue primary definition - $definition['primary'] = ['id']; - - $results[$tableName] = $definition; - dd($results); - $result->setResults($results); + foreach ($results as $tableName => $definitions) { + $primary = current($definitions['primaryKey']); + if ($primary instanceof PrimaryKeyEntity && count($primary->getColumns()) >= 2) { + $idField = new FieldEntity(); + $idField->setTable($tableName); + $idField->setType('bigInteger'); + $idField->setArguments(['autoIncrement' => true]); + $idField->setOptions([ + 'default' => null, + 'unsigned' => true, + 'nullable' => false + ]); + + $idField->setColumnName('id'); + $results[$tableName]['table'] = ['id' => $idField, ...$definitions['table']]; + unset($results[$tableName]['primaryKey']); } } + $result->setResults($results); $context->update($result); return $result; } - - private function guessForeignTarget(string $column): string - { - // z. B. user_id → users.id - $name = rtrim($column, '_id') . 's'; - return "$name.id"; - } } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 24febd7..c71388a 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -42,6 +42,7 @@ public function addProcessor(ProcessorInterface $processor): void /** * Returns all registered processors. + * @return ProcessorInterface[]|iterable */ public function getProcessors(): iterable { From a150b9354183dc88aa87027e518fa205af1c02b5 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 07:44:45 +0200 Subject: [PATCH 42/57] feat: replace composite primary keys in pivot tables with a single 'id' column and remove original PK --- src/Config/migration-generator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 43ed157..925d6f3 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -44,7 +44,7 @@ 'normalizer' => [ 'pivot' => [ 'class' => PivotProcessor::class, - 'requires' => ['primary', 'foreignKey', 'table'], + 'requires' => [], ], ], ]; \ No newline at end of file From 939b0159619061db1610375aacf14f2b84693b06 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 08:07:46 +0200 Subject: [PATCH 43/57] feat(normalization): support enabling specific processors via manager constructor --- src/Config/migration-generator.php | 7 +++ .../MigrationGeneratorServiceProvider.php | 54 ++++++++++++------- .../Processors/PivotProcessor.php | 6 +++ .../Processors/ProcessorInterface.php | 2 + .../SchemaNormalizationManager.php | 27 +++++++++- 5 files changed, 74 insertions(+), 22 deletions(-) diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 925d6f3..4530add 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -5,6 +5,13 @@ use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\PivotProcessor; return [ + 'config' => [ + 'defaults' => [ + 'normalizer' => [ + 'enabled' => ['pivot'], + ], + ], + ], 'definitions' => [ 'table' => [ 'class' => Definition\TableDefinition::class, diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 9aa3c85..bc284b0 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -14,6 +14,8 @@ use N3XT0R\MigrationGenerator\Service\Generator\Compiler\MigrationCompilerInterface; use N3XT0R\MigrationGenerator\Service\Generator\MigrationGenerator; use N3XT0R\MigrationGenerator\Service\Generator\MigrationGeneratorInterface; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManager; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolver; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolverInterface; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserFactory; @@ -52,6 +54,7 @@ public function register(): void $this->registerCompilerEngine(); $this->registerCompiler(); $this->registerDefinitionResolver(); + $this->registerNormalizer(); $this->registerGenerator(); $this->registerCommands(); } @@ -95,23 +98,15 @@ function (Application $app, array $params = []) { ); } - protected function getDefinitions(): array + protected function getConfigSection(string $key): array { - return (array)app('config')->get('migration-generator.definitions'); - } - - protected function getMapper(): array - { - return (array)app('config')->get('migration-generator.mapper'); + return (array)app('config')->get('migration-generator.' . $key); } protected function registerDefinitionResolver(): void { - $definitions = $this->getDefinitions(); - - foreach ($definitions as $definition) { - $this->app->bind($definition['class'], $definition['class']); - } + $definitions = $this->getConfigSection('definitions'); + $this->bindClasses($definitions); $this->app->bind( DefinitionResolverInterface::class, @@ -168,10 +163,6 @@ static function (Application $app, array $params) { ); } - protected function registerNormalizer(): void - { - } - protected function registerCompilerEngine(): void { $this->app->bind(ReplaceEngine::class, ReplaceEngine::class); @@ -193,10 +184,8 @@ static function () use ($app) { protected function registerCompiler(): void { - $mapper = $this->getMapper(); - foreach ($mapper as $map) { - $this->app->bind($map['class'], $map['class']); - } + $mapper = $this->getConfigSection('mapper'); + $this->bindClasses($mapper); $this->app->bind( MigrationCompilerInterface::class, @@ -214,4 +203,29 @@ static function (Application $app) use ($mapper) { } ); } + + protected function bindClasses(array $classes): void + { + foreach ($classes as $map) { + $this->app->bind($map['class'], $map['class']); + } + } + + + protected function registerNormalizer(): void + { + $normalizer = $this->getConfigSection('normalizer'); + $this->bindClasses($normalizer); + + $this->app->bind( + SchemaNormalizationManagerInterface::class, + static function (Application $app, array $params) use ($normalizer) { + $enabledProcessors = null; + if (array_key_exists('enabled', $params)) { + $enabledProcessors = (array)$params['enabled']; + } + return new SchemaNormalizationManager($normalizer, $enabledProcessors); + } + ); + } } diff --git a/src/Service/Generator/Normalization/Processors/PivotProcessor.php b/src/Service/Generator/Normalization/Processors/PivotProcessor.php index 2a74d25..833ebed 100644 --- a/src/Service/Generator/Normalization/Processors/PivotProcessor.php +++ b/src/Service/Generator/Normalization/Processors/PivotProcessor.php @@ -9,6 +9,12 @@ class PivotProcessor implements ProcessorInterface { + + public function getKey(): string + { + return 'pivot'; + } + public function process(NormalizationContext $context): ResultEntity { $result = $context->getCurrent(); diff --git a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php index e01d387..61d75f6 100644 --- a/src/Service/Generator/Normalization/Processors/ProcessorInterface.php +++ b/src/Service/Generator/Normalization/Processors/ProcessorInterface.php @@ -8,4 +8,6 @@ interface ProcessorInterface { public function process(NormalizationContext $context): ResultEntity; + + public function getKey(): string; } \ No newline at end of file diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index c71388a..3b1aceb 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -5,6 +5,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\ProcessorInterface; +use N3XT0R\MigrationGenerator\Service\Generator\Sort\TopSort; /** * Coordinates the execution of schema normalization processors. @@ -22,10 +23,15 @@ class SchemaNormalizationManager implements SchemaNormalizationManagerInterface */ protected array $processors = []; + /** + * @var string[]|null + */ + protected ?array $enabledProcessors = null; + /** * @param iterable $processors */ - public function __construct(iterable $processors = []) + public function __construct(iterable $processors = [], ?array $enabledProcessors = null) { foreach ($processors as $processor) { $this->addProcessor($processor); @@ -37,6 +43,12 @@ public function __construct(iterable $processors = []) */ public function addProcessor(ProcessorInterface $processor): void { + if (is_array($this->getEnabledProcessors())) { + $key = $processor->getKey(); + if (!in_array($key, $this->getEnabledProcessors(), true)) { + return; + } + } $this->processors[] = $processor; } @@ -60,6 +72,16 @@ public function setProcessors(iterable $processors = []): void } } + public function getEnabledProcessors(): ?array + { + return $this->enabledProcessors; + } + + public function setEnabledProcessors(?array $enabledProcessors): void + { + $this->enabledProcessors = $enabledProcessors; + } + /** * Executes all processors on the given schema result using a shared context. * @@ -70,8 +92,9 @@ public function normalize(ResultEntity $result): ResultEntity { $context = new NormalizationContext($result); $processors = $this->getProcessors(); + $sortedProcessors = TopSort::sort($processors); - foreach ($processors as $processor) { + foreach ($sortedProcessors as $processor) { $updated = $processor->process($context); $context->update($updated); } From 78395812e68d9471ced409c8a2a8c10847b2beb2 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 08:22:20 +0200 Subject: [PATCH 44/57] feat(normalization): support enabling specific processors via manager constructor --- .../Commands/MigrationGeneratorCommand.php | 109 ++++++++++-------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/src/Console/Commands/MigrationGeneratorCommand.php b/src/Console/Commands/MigrationGeneratorCommand.php index 1ef4b1c..4d131b0 100644 --- a/src/Console/Commands/MigrationGeneratorCommand.php +++ b/src/Console/Commands/MigrationGeneratorCommand.php @@ -2,14 +2,18 @@ namespace N3XT0R\MigrationGenerator\Console\Commands; +use Illuminate\Console\Command; use Illuminate\Console\ConfirmableTrait; use Illuminate\Database\Console\Migrations\MigrateMakeCommand; use Illuminate\Database\Migrations\MigrationCreator; use Illuminate\Database\Migrations\Migrator; use Illuminate\Support\Composer; +use Illuminate\Support\Facades\Config; use N3XT0R\MigrationGenerator\Service\Generator\DTO\MigrationTimingDto; use N3XT0R\MigrationGenerator\Service\Generator\MigrationGenerator; use N3XT0R\MigrationGenerator\Service\Generator\MigrationGeneratorInterface; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManager; +use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserInterface; class MigrationGeneratorCommand extends MigrateMakeCommand @@ -22,7 +26,7 @@ class MigrationGeneratorCommand extends MigrateMakeCommand * * @var string */ - protected $signature = 'migrate:regenerate {{--table= : specific table}} + protected $signature = 'migrate:regenerate {{--database= : The database connection to use}} '; //later for 1.1 : {{--force : force re-init in migrations-table}} /** @@ -41,9 +45,9 @@ class MigrationGeneratorCommand extends MigrateMakeCommand /** * MigrationGeneratorCommand constructor. - * @param MigrationCreator $creator - * @param Composer $composer - * @param Migrator|null $migrator + * @param MigrationCreator $creator + * @param Composer $composer + * @param Migrator|null $migrator * @throws \Illuminate\Contracts\Container\BindingResolutionException */ public function __construct(MigrationCreator $creator, Composer $composer, Migrator $migrator = null) @@ -56,6 +60,7 @@ public function __construct(MigrationCreator $creator, Composer $composer, Migra $migrator = app()->make('migrator'); } $this->setMigrator($migrator); + $this->extendSignatureWithNormalizers(); } public function setMigrator(Migrator $migrator): void @@ -68,13 +73,21 @@ public function getMigrator(): Migrator return $this->migrator; } - public function handle(): void + public function handle(): int { if (!$this->confirmToProceed()) { - return; + return Command::FAILURE; + } + + $enabled = $this->resolveEnabledNormalizers(); + if (!$this->validateNormalizers($enabled)) { + return Command::FAILURE; + } + + if (count($enabled) === 0) { + $enabled = null; } - $table = (string) $this->option('table'); $force = false; //$force = (bool)$this->option('force'); $connectionName = $this->option('database') ?? config('database.default'); @@ -90,24 +103,15 @@ public function handle(): void ] ); - if (!empty($table)) { - $this->createMigrationForSingleTable($schemaParser, $connectionName, $table); - } else { - $this->createMigrationsForWholeSchema($schemaParser, $connectionName); - } + $this->createMigrationsForWholeSchema($schemaParser, $connectionName, $enabled); - if (true === $force) { - /** - * @todo reinitialize migrations table - */ - } + return Command::SUCCESS; } - - protected function createMigrationForSingleTable( + protected function createMigrationsForWholeSchema( SchemaParserInterface $schemaParser, string $connectionName, - string $table + ?array $enabledNormalizer ): void { /** * @var MigrationGenerator $generator @@ -117,33 +121,14 @@ protected function createMigrationForSingleTable( ['connectionName' => $connectionName] ); - $database = $this->getMigrator()->resolveConnection($connectionName)->getDatabaseName(); - $tables = $schemaParser->getTablesFromSchema( - $database - ); - if (!in_array($table, $tables, true)) { - $this->error('Table "'.$table.'" not exists in Schema "'.$database.'"'); - } else { - if (true === $generator->generateMigrationForTable($database, $table)) { - /** - * @todo - */ - } else { - $this->error('there occurred an error by creating migration for '.$table); - $this->error(implode(', ', $generator->getErrorMessages())); - } - } - } - - protected function createMigrationsForWholeSchema(SchemaParserInterface $schemaParser, string $connectionName): void - { /** - * @var MigrationGenerator $generator + * @var SchemaNormalizationManager $normalizer */ - $generator = $this->getLaravel()->make( - MigrationGeneratorInterface::class, - ['connectionName' => $connectionName] + $normalizer = $this->getLaravel()->make( + SchemaNormalizationManagerInterface::class, + ['enabled' => $enabledNormalizer] ); + $generator->setNormalizationManager($normalizer); $database = $this->getMigrator()->resolveConnection($connectionName)->getDatabaseName(); $tables = $schemaParser->getSortedTablesFromSchema( @@ -162,7 +147,7 @@ protected function createMigrationsForWholeSchema(SchemaParserInterface $schemaP if (true === $generator->generateMigrationForTable($database, $table, $migrationTimingDto)) { $bar->advance(); } else { - $this->error('there occurred an error by creating migration for '.$table); + $this->error('there occurred an error by creating migration for ' . $table); $this->error(implode(', ', $generator->getErrorMessages())); break; } @@ -176,7 +161,7 @@ protected function createMigrationsForWholeSchema(SchemaParserInterface $schemaP /** * Prepare the migration database for running. * - * @param string|null $database + * @param string|null $database * @return void */ protected function prepareDatabase(string $database = null): void @@ -191,4 +176,36 @@ protected function prepareDatabase(string $database = null): void ); } } + + protected function extendSignatureWithNormalizers(): void + { + $normalizers = array_keys(Config::get('migration-generator.normalizer', [])); + + if (!empty($normalizers)) { + $choices = implode(',', $normalizers); + $this->signature .= ' {--normalizer=* : Enabled normalizers (available: ' . $choices . ')}'; + } + } + + protected function resolveEnabledNormalizers(): array + { + $input = $this->option('normalizer'); + $config = config('migration-generator.config.defaults.normalizer', []); + + return !empty($input) ? (array)$input : (array)$config; + } + + protected function validateNormalizers(array $enabled): bool + { + $result = true; + $available = array_keys(config('migration-generator.normalizer', [])); + $invalid = array_diff($enabled, $available); + + if (!empty($invalid)) { + $this->error('Invalid normalizer(s): ' . implode(', ', $invalid)); + $result = false; + } + + return $result; + } } \ No newline at end of file From 640a0e97e9504a20d105015aa856811b499d9564 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 08:22:51 +0200 Subject: [PATCH 45/57] feat(normalization): support enabling specific processors via manager constructor --- src/Console/Commands/MigrationGeneratorCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Console/Commands/MigrationGeneratorCommand.php b/src/Console/Commands/MigrationGeneratorCommand.php index 4d131b0..af8f85e 100644 --- a/src/Console/Commands/MigrationGeneratorCommand.php +++ b/src/Console/Commands/MigrationGeneratorCommand.php @@ -113,10 +113,11 @@ protected function createMigrationsForWholeSchema( string $connectionName, ?array $enabledNormalizer ): void { + $laravel = $this->getLaravel(); /** * @var MigrationGenerator $generator */ - $generator = $this->getLaravel()->make( + $generator = $laravel->make( MigrationGeneratorInterface::class, ['connectionName' => $connectionName] ); @@ -124,7 +125,7 @@ protected function createMigrationsForWholeSchema( /** * @var SchemaNormalizationManager $normalizer */ - $normalizer = $this->getLaravel()->make( + $normalizer = $laravel->make( SchemaNormalizationManagerInterface::class, ['enabled' => $enabledNormalizer] ); From f2bcba7fcd03de1f5958666829673807f6dca537 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 08:23:50 +0200 Subject: [PATCH 46/57] feat(normalization): support enabling specific processors via manager constructor --- .../Generator/Normalization/SchemaNormalizationManager.php | 1 + .../Normalization/SchemaNormalizationManagerInterface.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 3b1aceb..5e90a84 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -33,6 +33,7 @@ class SchemaNormalizationManager implements SchemaNormalizationManagerInterface */ public function __construct(iterable $processors = [], ?array $enabledProcessors = null) { + $this->setEnabledProcessors($enabledProcessors); foreach ($processors as $processor) { $this->addProcessor($processor); } diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php index 5cfe857..02a461c 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManagerInterface.php @@ -17,4 +17,8 @@ public function normalize(ResultEntity $result): ResultEntity; public function getProcessors(): iterable; public function setProcessors(iterable $processors = []): void; + + public function setEnabledProcessors(?array $enabledProcessors): void; + + public function getEnabledProcessors(): ?array; } \ No newline at end of file From 8c3369a7685013886cfd6d8ca68caf02ce713970 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 08:26:37 +0200 Subject: [PATCH 47/57] feat(normalization): support enabling specific processors via manager constructor --- src/Console/Commands/MigrationGeneratorCommand.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Console/Commands/MigrationGeneratorCommand.php b/src/Console/Commands/MigrationGeneratorCommand.php index af8f85e..2f2a068 100644 --- a/src/Console/Commands/MigrationGeneratorCommand.php +++ b/src/Console/Commands/MigrationGeneratorCommand.php @@ -53,13 +53,7 @@ class MigrationGeneratorCommand extends MigrateMakeCommand public function __construct(MigrationCreator $creator, Composer $composer, Migrator $migrator = null) { parent::__construct($creator, $composer); - if (null === $migrator) { - /** - * @var Migrator $migrator - */ - $migrator = app()->make('migrator'); - } - $this->setMigrator($migrator); + $this->setMigrator($migrator ?? app()->make('migrator')); $this->extendSignatureWithNormalizers(); } From 790d04e052b9a8ac9875344bd52512fbf1613fac Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 10:28:36 +0200 Subject: [PATCH 48/57] added run directory. --- src/Config/migration-generator.php | 1 + tests/Resources/ExpectedMigrations/run/.gitkeep | 0 2 files changed, 1 insertion(+) create mode 100644 tests/Resources/ExpectedMigrations/run/.gitkeep diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 4530add..74fcb10 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -11,6 +11,7 @@ 'enabled' => ['pivot'], ], ], + 'migration_dir' => database_path() . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR, ], 'definitions' => [ 'table' => [ diff --git a/tests/Resources/ExpectedMigrations/run/.gitkeep b/tests/Resources/ExpectedMigrations/run/.gitkeep new file mode 100644 index 0000000..e69de29 From 5ac6db33f5d18aa262aa374f63d489c939dfa907 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 10:40:47 +0200 Subject: [PATCH 49/57] added run directory. --- src/Providers/MigrationGeneratorServiceProvider.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index bc284b0..73f64f3 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -67,6 +67,10 @@ protected function registerCommands(): void $app['composer'] ); }); + + $this->commands([ + Commands\MigrationGeneratorCommand::class, + ]); } protected function registerParserFactory(): void @@ -123,9 +127,10 @@ static function (Application $app, array $params) use ($definitions) { protected function registerGenerator(): void { + $config = $this->getConfigSection('config'); $this->app->bind( MigrationGeneratorInterface::class, - static function (Application $app, array $params) { + static function (Application $app, array $params) use ($config) { $dbMap = [ 'mysql' => 'pdo_mysql', 'sqlite' => 'pdo_sqlite', @@ -157,7 +162,8 @@ static function (Application $app, array $params) { return new MigrationGenerator( $app->make(DefinitionResolverInterface::class, ['connection' => $connection]), - $app->make(MigrationCompilerInterface::class) + $app->make(MigrationCompilerInterface::class), + (string)$config['migration_dir'] ); } ); From 7e0f9ceafb0c4696e76658f78d9aee9102212294 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 10:45:49 +0200 Subject: [PATCH 50/57] fixed registerCommands --- src/Providers/MigrationGeneratorServiceProvider.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 73f64f3..112bfda 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -6,6 +6,8 @@ use Illuminate\Contracts\Container\Container as Application; use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Database\DatabaseManager; +use Illuminate\Database\Migrations\Migrator; +use Illuminate\Support\Composer; use Illuminate\Support\ServiceProvider; use Illuminate\View\Engines\EngineResolver; use N3XT0R\MigrationGenerator\Console\Commands; @@ -61,10 +63,11 @@ public function register(): void protected function registerCommands(): void { - $this->app->singleton('command.migrate.regenerate', function ($app) { + $this->app->singleton(Commands\MigrationGeneratorCommand::class, function ($app) { return new Commands\MigrationGeneratorCommand( - $app['migrator'], - $app['composer'] + $app->make('migration.creator'), + $app->make(Composer::class), + $app->make(Migrator::class) ); }); From 05f48cde2c23ea63d228e1ecd21795a77f3d1787 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:03:12 +0200 Subject: [PATCH 51/57] typo fixed. --- .../Generator/Normalization/SchemaNormalizationManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 5e90a84..6204f8b 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -35,7 +35,7 @@ public function __construct(iterable $processors = [], ?array $enabledProcessors { $this->setEnabledProcessors($enabledProcessors); foreach ($processors as $processor) { - $this->addProcessor($processor); + $this->setProcessors($processor); } } From 4ffd89e6548039755e47655cb48adba412476889 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:38:23 +0200 Subject: [PATCH 52/57] bugf fixed. --- .../Commands/MigrationGeneratorCommand.php | 6 +-- .../MigrationGeneratorServiceProvider.php | 13 ++++++- .../Generator/Compiler/MigrationCompiler.php | 1 + src/Service/Generator/MigrationGenerator.php | 12 ++++-- .../SchemaNormalizationManager.php | 6 +-- .../MigrationGeneratorCommandTest.php | 38 +++++++++++++++++++ .../Resources/ExpectedMigrations/run/.gitkeep | 0 tests/TestCase.php | 2 + 8 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php delete mode 100644 tests/Resources/ExpectedMigrations/run/.gitkeep diff --git a/src/Console/Commands/MigrationGeneratorCommand.php b/src/Console/Commands/MigrationGeneratorCommand.php index 2f2a068..0f05f48 100644 --- a/src/Console/Commands/MigrationGeneratorCommand.php +++ b/src/Console/Commands/MigrationGeneratorCommand.php @@ -27,7 +27,7 @@ class MigrationGeneratorCommand extends MigrateMakeCommand * @var string */ protected $signature = 'migrate:regenerate - {{--database= : The database connection to use}} '; //later for 1.1 : {{--force : force re-init in migrations-table}} + {--database= : The database connection to use} '; //later for 1.1 : {{--force : force re-init in migrations-table}} /** * The console command description. @@ -52,9 +52,9 @@ class MigrationGeneratorCommand extends MigrateMakeCommand */ public function __construct(MigrationCreator $creator, Composer $composer, Migrator $migrator = null) { + $this->extendSignatureWithNormalizers(); parent::__construct($creator, $composer); $this->setMigrator($migrator ?? app()->make('migrator')); - $this->extendSignatureWithNormalizers(); } public function setMigrator(Migrator $migrator): void @@ -185,7 +185,7 @@ protected function extendSignatureWithNormalizers(): void protected function resolveEnabledNormalizers(): array { $input = $this->option('normalizer'); - $config = config('migration-generator.config.defaults.normalizer', []); + $config = config('migration-generator.config.defaults.normalizer.enabled', []); return !empty($input) ? (array)$input : (array)$config; } diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 112bfda..0671b5f 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -20,6 +20,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolver; use N3XT0R\MigrationGenerator\Service\Generator\Resolver\DefinitionResolverInterface; +use N3XT0R\MigrationGenerator\Service\Generator\Sort\TopSort; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserFactory; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserFactoryInterface; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserInterface; @@ -107,7 +108,7 @@ function (Application $app, array $params = []) { protected function getConfigSection(string $key): array { - return (array)app('config')->get('migration-generator.' . $key); + return (array)$this->app['config']->get('migration-generator.' . $key); } protected function registerDefinitionResolver(): void @@ -131,6 +132,7 @@ static function (Application $app, array $params) use ($definitions) { protected function registerGenerator(): void { $config = $this->getConfigSection('config'); + dd($config); $this->app->bind( MigrationGeneratorInterface::class, static function (Application $app, array $params) use ($config) { @@ -162,6 +164,7 @@ static function (Application $app, array $params) use ($config) { 'driver' => $dbConfig['driver'], ]; $connection = DriverManager::getConnection($connectionParams); + dd($config['migration_dir']); return new MigrationGenerator( $app->make(DefinitionResolverInterface::class, ['connection' => $connection]), @@ -229,11 +232,17 @@ protected function registerNormalizer(): void $this->app->bind( SchemaNormalizationManagerInterface::class, static function (Application $app, array $params) use ($normalizer) { + $sortedProcessors = TopSort::sort($normalizer); $enabledProcessors = null; if (array_key_exists('enabled', $params)) { $enabledProcessors = (array)$params['enabled']; } - return new SchemaNormalizationManager($normalizer, $enabledProcessors); + $normalizerClasses = []; + foreach ($sortedProcessors as $key) { + $normalizerClasses[] = $app->get($normalizer[$key]['class']); + } + + return new SchemaNormalizationManager($normalizerClasses, $enabledProcessors); } ); } diff --git a/src/Service/Generator/Compiler/MigrationCompiler.php b/src/Service/Generator/Compiler/MigrationCompiler.php index a679fd1..f43bfa8 100644 --- a/src/Service/Generator/Compiler/MigrationCompiler.php +++ b/src/Service/Generator/Compiler/MigrationCompiler.php @@ -205,6 +205,7 @@ private function generateFilename(string $name, int $currentAmount, int $maxAmou private function writeTemplateToFile(string $path, string $fileName, string $content): bool { + dump($path); $filesystem = $this->getFilesystem(); $filePath = $path . DIRECTORY_SEPARATOR . $fileName; $success = false; diff --git a/src/Service/Generator/MigrationGenerator.php b/src/Service/Generator/MigrationGenerator.php index 134f249..1ad30d3 100644 --- a/src/Service/Generator/MigrationGenerator.php +++ b/src/Service/Generator/MigrationGenerator.php @@ -19,9 +19,15 @@ class MigrationGenerator implements MigrationGeneratorInterface protected array $errorMessages = []; protected array $migrationFiles = []; - public function __construct(DefinitionResolverInterface $resolver, MigrationCompilerInterface $compiler) - { - $this->setMigrationDir(database_path() . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR); + public function __construct( + DefinitionResolverInterface $resolver, + MigrationCompilerInterface $compiler, + string $migrationDir = '' + ) { + if (empty($migrationDir)) { + $migrationDir = database_path() . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR; + } + $this->setMigrationDir($migrationDir); $this->setResolver($resolver); $this->setCompiler($compiler); } diff --git a/src/Service/Generator/Normalization/SchemaNormalizationManager.php b/src/Service/Generator/Normalization/SchemaNormalizationManager.php index 6204f8b..8fa7d2f 100644 --- a/src/Service/Generator/Normalization/SchemaNormalizationManager.php +++ b/src/Service/Generator/Normalization/SchemaNormalizationManager.php @@ -5,7 +5,6 @@ use N3XT0R\MigrationGenerator\Service\Generator\Definition\Entity\ResultEntity; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Context\NormalizationContext; use N3XT0R\MigrationGenerator\Service\Generator\Normalization\Processors\ProcessorInterface; -use N3XT0R\MigrationGenerator\Service\Generator\Sort\TopSort; /** * Coordinates the execution of schema normalization processors. @@ -35,7 +34,7 @@ public function __construct(iterable $processors = [], ?array $enabledProcessors { $this->setEnabledProcessors($enabledProcessors); foreach ($processors as $processor) { - $this->setProcessors($processor); + $this->addProcessor($processor); } } @@ -93,9 +92,8 @@ public function normalize(ResultEntity $result): ResultEntity { $context = new NormalizationContext($result); $processors = $this->getProcessors(); - $sortedProcessors = TopSort::sort($processors); - foreach ($sortedProcessors as $processor) { + foreach ($processors as $processor) { $updated = $processor->process($context); $context->update($updated); } diff --git a/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php b/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php new file mode 100644 index 0000000..d54b6eb --- /dev/null +++ b/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php @@ -0,0 +1,38 @@ +set('migration-generator.config.migration_dir', $this->migrationPath); + + if (!File::exists($this->migrationPath)) { + File::makeDirectory($this->migrationPath); + } + + File::cleanDirectory($this->migrationPath); + } + + public function testCommandGeneratesMigrationFiles(): void + { + config()->set('migration-generator.normalizer.enabled', []); + config()->set('migration-generator.defaults.normalizer', []); + $this->artisan('migrate:regenerate', ['--database' => $this->getDatabaseFromEnv()]) + ->assertExitCode(0); + $files = File::files($this->migrationPath); + self::assertNotEmpty($files, 'No Migrations generated'); + } + + protected function tearDown(): void + { + parent::tearDown(); + //File::cleanDirectory($this->migrationPath); + } +} \ No newline at end of file diff --git a/tests/Resources/ExpectedMigrations/run/.gitkeep b/tests/Resources/ExpectedMigrations/run/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/TestCase.php b/tests/TestCase.php index b669f65..25f5c83 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -12,11 +12,13 @@ abstract class TestCase extends OrchestraTestCase { protected $resourceFolder = ''; + protected string $migrationPath = ''; protected function setUp(): void { parent::setUp(); $this->resourceFolder = __DIR__ . '/Resources/'; + $this->migrationPath = $this->resourceFolder . '/ExpectedMigrations/run/'; } /** From 536c946d48a4d8cac1855b42701ba696dacb0434 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:38:56 +0200 Subject: [PATCH 53/57] bugf fixed. --- src/Providers/MigrationGeneratorServiceProvider.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 0671b5f..36e6af6 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -132,7 +132,6 @@ static function (Application $app, array $params) use ($definitions) { protected function registerGenerator(): void { $config = $this->getConfigSection('config'); - dd($config); $this->app->bind( MigrationGeneratorInterface::class, static function (Application $app, array $params) use ($config) { @@ -164,7 +163,6 @@ static function (Application $app, array $params) use ($config) { 'driver' => $dbConfig['driver'], ]; $connection = DriverManager::getConnection($connectionParams); - dd($config['migration_dir']); return new MigrationGenerator( $app->make(DefinitionResolverInterface::class, ['connection' => $connection]), From 13cf45262d1a5f70c19f31f3b1b67aa9b9361659 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:39:35 +0200 Subject: [PATCH 54/57] bugf fixed. --- src/Service/Generator/Compiler/MigrationCompiler.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Service/Generator/Compiler/MigrationCompiler.php b/src/Service/Generator/Compiler/MigrationCompiler.php index f43bfa8..a679fd1 100644 --- a/src/Service/Generator/Compiler/MigrationCompiler.php +++ b/src/Service/Generator/Compiler/MigrationCompiler.php @@ -205,7 +205,6 @@ private function generateFilename(string $name, int $currentAmount, int $maxAmou private function writeTemplateToFile(string $path, string $fileName, string $content): bool { - dump($path); $filesystem = $this->getFilesystem(); $filePath = $path . DIRECTORY_SEPARATOR . $fileName; $success = false; From e4003fac24ca95ec7953476661e58a9b0448f0d1 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:40:49 +0200 Subject: [PATCH 55/57] bugf fixed. --- src/Config/migration-generator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config/migration-generator.php b/src/Config/migration-generator.php index 74fcb10..eccc0e6 100644 --- a/src/Config/migration-generator.php +++ b/src/Config/migration-generator.php @@ -11,7 +11,7 @@ 'enabled' => ['pivot'], ], ], - 'migration_dir' => database_path() . DIRECTORY_SEPARATOR . 'migrations' . DIRECTORY_SEPARATOR, + 'migration_dir' => database_path('migrations'), ], 'definitions' => [ 'table' => [ From 80676a25a0df54f85ff00e065b84e132656243dc Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 11:47:47 +0200 Subject: [PATCH 56/57] bugs fixed. --- src/Providers/MigrationGeneratorServiceProvider.php | 1 - .../Console/Commands/MigrationGeneratorCommandTest.php | 6 ++++-- tests/TestCase.php | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index 36e6af6..b5c3128 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -163,7 +163,6 @@ static function (Application $app, array $params) use ($config) { 'driver' => $dbConfig['driver'], ]; $connection = DriverManager::getConnection($connectionParams); - return new MigrationGenerator( $app->make(DefinitionResolverInterface::class, ['connection' => $connection]), $app->make(MigrationCompilerInterface::class), diff --git a/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php b/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php index d54b6eb..881f151 100644 --- a/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php +++ b/tests/Integration/Console/Commands/MigrationGeneratorCommandTest.php @@ -8,10 +8,12 @@ class MigrationGeneratorCommandTest extends DbTestCase { + protected string $migrationPath = ''; + protected function setUp(): void { parent::setUp(); - config()->set('migration-generator.config.migration_dir', $this->migrationPath); + $this->migrationPath = (string)config()->get('migration-generator.config.migration_dir'); if (!File::exists($this->migrationPath)) { File::makeDirectory($this->migrationPath); @@ -33,6 +35,6 @@ public function testCommandGeneratesMigrationFiles(): void protected function tearDown(): void { parent::tearDown(); - //File::cleanDirectory($this->migrationPath); + File::cleanDirectory($this->migrationPath); } } \ No newline at end of file diff --git a/tests/TestCase.php b/tests/TestCase.php index 25f5c83..b669f65 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -12,13 +12,11 @@ abstract class TestCase extends OrchestraTestCase { protected $resourceFolder = ''; - protected string $migrationPath = ''; protected function setUp(): void { parent::setUp(); $this->resourceFolder = __DIR__ . '/Resources/'; - $this->migrationPath = $this->resourceFolder . '/ExpectedMigrations/run/'; } /** From aa3814f1db13c1b911d6e6a9c959c399af149ce4 Mon Sep 17 00:00:00 2001 From: Ilya Beliaev Date: Sun, 29 Jun 2025 12:04:06 +0200 Subject: [PATCH 57/57] bugs fixed. --- .../Commands/MigrationGeneratorCommand.php | 18 ++++-------------- .../MigrationGeneratorServiceProvider.php | 10 ---------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/Console/Commands/MigrationGeneratorCommand.php b/src/Console/Commands/MigrationGeneratorCommand.php index 0f05f48..d69c9e3 100644 --- a/src/Console/Commands/MigrationGeneratorCommand.php +++ b/src/Console/Commands/MigrationGeneratorCommand.php @@ -4,10 +4,7 @@ use Illuminate\Console\Command; use Illuminate\Console\ConfirmableTrait; -use Illuminate\Database\Console\Migrations\MigrateMakeCommand; -use Illuminate\Database\Migrations\MigrationCreator; use Illuminate\Database\Migrations\Migrator; -use Illuminate\Support\Composer; use Illuminate\Support\Facades\Config; use N3XT0R\MigrationGenerator\Service\Generator\DTO\MigrationTimingDto; use N3XT0R\MigrationGenerator\Service\Generator\MigrationGenerator; @@ -16,7 +13,7 @@ use N3XT0R\MigrationGenerator\Service\Generator\Normalization\SchemaNormalizationManagerInterface; use N3XT0R\MigrationGenerator\Service\Parser\SchemaParserInterface; -class MigrationGeneratorCommand extends MigrateMakeCommand +class MigrationGeneratorCommand extends Command { use ConfirmableTrait; @@ -43,18 +40,11 @@ class MigrationGeneratorCommand extends MigrateMakeCommand */ protected $migrator; - /** - * MigrationGeneratorCommand constructor. - * @param MigrationCreator $creator - * @param Composer $composer - * @param Migrator|null $migrator - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - public function __construct(MigrationCreator $creator, Composer $composer, Migrator $migrator = null) + public function __construct() { $this->extendSignatureWithNormalizers(); - parent::__construct($creator, $composer); - $this->setMigrator($migrator ?? app()->make('migrator')); + parent::__construct(); + $this->setMigrator(app()->make('migrator')); } public function setMigrator(Migrator $migrator): void diff --git a/src/Providers/MigrationGeneratorServiceProvider.php b/src/Providers/MigrationGeneratorServiceProvider.php index b5c3128..c8e3ca0 100644 --- a/src/Providers/MigrationGeneratorServiceProvider.php +++ b/src/Providers/MigrationGeneratorServiceProvider.php @@ -6,8 +6,6 @@ use Illuminate\Contracts\Container\Container as Application; use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Database\DatabaseManager; -use Illuminate\Database\Migrations\Migrator; -use Illuminate\Support\Composer; use Illuminate\Support\ServiceProvider; use Illuminate\View\Engines\EngineResolver; use N3XT0R\MigrationGenerator\Console\Commands; @@ -64,14 +62,6 @@ public function register(): void protected function registerCommands(): void { - $this->app->singleton(Commands\MigrationGeneratorCommand::class, function ($app) { - return new Commands\MigrationGeneratorCommand( - $app->make('migration.creator'), - $app->make(Composer::class), - $app->make(Migrator::class) - ); - }); - $this->commands([ Commands\MigrationGeneratorCommand::class, ]);