diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 827b78af..9f5ef26c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,10 +26,10 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, fileinfo + extensions: mbstring, fileinfo, pdo_mysql, pdo ini-values: error_reporting=E_ALL - tools: composer:v2 - coverage: none + tools: composer:v2, pecl + coverage: xdebug - name: โ™ป๏ธ Load cached dependencies id: cached-composer-dependencies @@ -48,17 +48,12 @@ jobs: PHP_CS_FIXER_IGNORE_ENV: true - name: ๐Ÿงช Execute phpunit tests - uses: php-actions/phpunit@v3 env: XDEBUG_MODE: coverage - with: - bootstrap: vendor/autoload.php - configuration: phpunit.xml.dist - php_extensions: xdebug - args: tests --coverage-clover ./coverage.xml + run: vendor/bin/phpunit --coverage-clover=coverage.xml - - name: ๐Ÿ“ Run static analysis using phpstan - run: make stan +# - name: ๐Ÿ“ Run static analysis using phpstan +# run: make stan - name: ๐Ÿ“ค Upload coverage report to Codecov uses: codecov/codecov-action@v3 diff --git a/composer.json b/composer.json index f0462520..5372abac 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,9 @@ "cycle/orm": "^2.3", "cycle/schema-migrations-generator": "^2.1", "cycle/schema-renderer": "^1.2", - "laravel/framework": "*", + "illuminate/console": "^10.9", + "illuminate/contracts": "^10.9", + "illuminate/support": "^10.9", "spiral/attributes": "^3.1", "symfony/console": "^6.2" }, @@ -51,8 +53,8 @@ "src/helpers.php" ], "psr-4": { - "WayOfDev\\Cycle\\": "src", - "WayOfDev\\Cycle\\Database\\Factories\\": "database/factories" + "WayOfDev\\Cycle\\": "src/", + "WayOfDev\\Cycle\\Database\\Factories\\": "database/factories/" } }, "autoload-dev": { @@ -66,7 +68,7 @@ "cs-diff": "php vendor/bin/php-cs-fixer fix --dry-run -v --diff", "test": "php vendor/bin/pest", "test-cc": "php vendor/bin/pest --coverage", - "stan": "php vendor/bin/phpstan analyse", + "stan": "php vendor/bin/phpstan analyse --memory-limit=256M", "stan-ci": "php vendor/bin/phpstan analyse --error-format=github", "post-autoload-dump": [ "@php vendor/bin/testbench package:discover --ansi" @@ -93,5 +95,7 @@ "indent-size": 4, "indent-style": "space" } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/composer.lock b/composer.lock index 2d25ba99..2eccc9ab 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1532eda2ae6431c968c01d33e118e495", + "content-hash": "fcf7269e374b1aa62b46f8f20594d23f", "packages": [ { "name": "brick/math", @@ -3184,16 +3184,16 @@ }, { "name": "symfony/console", - "version": "v6.2.8", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3582d68a64a86ec25240aaa521ec8bc2342b369b" + "reference": "12288d9f4500f84a4d02254d4aa968b15488476f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3582d68a64a86ec25240aaa521ec8bc2342b369b", - "reference": "3582d68a64a86ec25240aaa521ec8bc2342b369b", + "url": "https://api.github.com/repos/symfony/console/zipball/12288d9f4500f84a4d02254d4aa968b15488476f", + "reference": "12288d9f4500f84a4d02254d4aa968b15488476f", "shasum": "" }, "require": { @@ -3260,7 +3260,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.8" + "source": "https://github.com/symfony/console/tree/v6.2.10" }, "funding": [ { @@ -3276,7 +3276,7 @@ "type": "tidelift" } ], - "time": "2023-03-29T21:42:15+00:00" + "time": "2023-04-28T13:37:43+00:00" }, { "name": "symfony/css-selector", @@ -3412,16 +3412,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.2.9", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "e95f1273b3953c3b5e5341172dae838bacee11ee" + "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/e95f1273b3953c3b5e5341172dae838bacee11ee", - "reference": "e95f1273b3953c3b5e5341172dae838bacee11ee", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b7e9f124640cb0611624a9383176c3e5f7d8cfb", + "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb", "shasum": "" }, "require": { @@ -3463,7 +3463,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.2.9" + "source": "https://github.com/symfony/error-handler/tree/v6.2.10" }, "funding": [ { @@ -3479,7 +3479,7 @@ "type": "tidelift" } ], - "time": "2023-04-11T16:03:19+00:00" + "time": "2023-04-18T13:46:08+00:00" }, { "name": "symfony/event-dispatcher", @@ -3709,16 +3709,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.2.8", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "511a524affeefc191939348823ac75e9921c2112" + "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/511a524affeefc191939348823ac75e9921c2112", - "reference": "511a524affeefc191939348823ac75e9921c2112", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49adbb92bcb4e3c2943719d2756271e8b9602acc", + "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc", "shasum": "" }, "require": { @@ -3767,7 +3767,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.2.8" + "source": "https://github.com/symfony/http-foundation/tree/v6.2.10" }, "funding": [ { @@ -3783,20 +3783,20 @@ "type": "tidelift" } ], - "time": "2023-03-29T21:42:15+00:00" + "time": "2023-04-18T13:46:08+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.2.9", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "02246510cf7031726f7237138d61b796b95799b3" + "reference": "81064a65a5496f17d2b6984f6519406f98864215" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/02246510cf7031726f7237138d61b796b95799b3", - "reference": "02246510cf7031726f7237138d61b796b95799b3", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/81064a65a5496f17d2b6984f6519406f98864215", + "reference": "81064a65a5496f17d2b6984f6519406f98864215", "shasum": "" }, "require": { @@ -3878,7 +3878,7 @@ "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/v6.2.9" + "source": "https://github.com/symfony/http-kernel/tree/v6.2.10" }, "funding": [ { @@ -3894,7 +3894,7 @@ "type": "tidelift" } ], - "time": "2023-04-13T16:41:43+00:00" + "time": "2023-04-28T13:50:28+00:00" }, { "name": "symfony/mailer", @@ -3977,16 +3977,16 @@ }, { "name": "symfony/mime", - "version": "v6.2.7", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "62e341f80699badb0ad70b31149c8df89a2d778e" + "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/62e341f80699badb0ad70b31149c8df89a2d778e", - "reference": "62e341f80699badb0ad70b31149c8df89a2d778e", + "url": "https://api.github.com/repos/symfony/mime/zipball/b6c137fc53a9f7c4c951cd3f362b3734c7a97723", + "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723", "shasum": "" }, "require": { @@ -4040,7 +4040,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.2.7" + "source": "https://github.com/symfony/mime/tree/v6.2.10" }, "funding": [ { @@ -4056,7 +4056,7 @@ "type": "tidelift" } ], - "time": "2023-02-24T10:42:00+00:00" + "time": "2023-04-19T09:54:16+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4718,16 +4718,16 @@ }, { "name": "symfony/process", - "version": "v6.2.8", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "75ed64103df4f6615e15a7fe38b8111099f47416" + "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/75ed64103df4f6615e15a7fe38b8111099f47416", - "reference": "75ed64103df4f6615e15a7fe38b8111099f47416", + "url": "https://api.github.com/repos/symfony/process/zipball/b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", + "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", "shasum": "" }, "require": { @@ -4759,7 +4759,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.2.8" + "source": "https://github.com/symfony/process/tree/v6.2.10" }, "funding": [ { @@ -4775,7 +4775,7 @@ "type": "tidelift" } ], - "time": "2023-03-09T16:20:02+00:00" + "time": "2023-04-18T13:56:57+00:00" }, { "name": "symfony/routing", @@ -5291,16 +5291,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.2.8", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "d37ab6787be2db993747b6218fcc96e8e3bb4bd0" + "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d37ab6787be2db993747b6218fcc96e8e3bb4bd0", - "reference": "d37ab6787be2db993747b6218fcc96e8e3bb4bd0", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41a750a23412ca76fdbbf5096943b4134272c1ab", + "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab", "shasum": "" }, "require": { @@ -5359,7 +5359,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.2.8" + "source": "https://github.com/symfony/var-dumper/tree/v6.2.10" }, "funding": [ { @@ -5375,7 +5375,7 @@ "type": "tidelift" } ], - "time": "2023-03-29T21:42:15+00:00" + "time": "2023-04-18T13:46:08+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -9272,12 +9272,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "d6028f338053ae05b3c526fffe475bb45b8d676d" + "reference": "a31b8b0ce0409fca4e8fcdda046e8d4b603dc739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/d6028f338053ae05b3c526fffe475bb45b8d676d", - "reference": "d6028f338053ae05b3c526fffe475bb45b8d676d", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a31b8b0ce0409fca4e8fcdda046e8d4b603dc739", + "reference": "a31b8b0ce0409fca4e8fcdda046e8d4b603dc739", "shasum": "" }, "conflict": { @@ -9345,7 +9345,7 @@ "codeigniter4/shield": "<1-beta.4|= 1.0.0-beta", "codiad/codiad": "<=2.8.4", "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", - "concrete5/concrete5": "<=9.1.3|>= 9.0.0RC1, < 9.1.3", + "concrete5/concrete5": "<9.2|>= 9.0.0RC1, < 9.1.3", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.40|>=4.10,<4.11.7|>=4.13,<4.13.21|>=5.1,<5.1.4", @@ -9375,7 +9375,7 @@ "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", "dolibarr/dolibarr": "<16|>=16.0.1,<16.0.3|= 12.0.5|>= 3.3.beta1, < 13.0.2", "dompdf/dompdf": "<2.0.2|= 2.0.2", - "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "drupal/core": ">=7,<7.96|>=8,<9.4.14|>=9.5,<9.5.8|>=10,<10.0.8", "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", "dweeves/magmi": "<=0.7.24", "ecodev/newsletter": "<=4", @@ -9604,7 +9604,7 @@ "phpxmlrpc/phpxmlrpc": "<4.9.2", "pimcore/data-hub": "<1.2.4", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<10.5.20", + "pimcore/pimcore": "<10.5.21", "pixelfed/pixelfed": "<=0.11.4", "pocketmine/bedrock-protocol": "<8.0.2", "pocketmine/pocketmine-mp": "<4.12.5|>= 4.0.0-BETA5, < 4.4.2", @@ -9735,6 +9735,7 @@ "t3/dce": ">=2.2,<2.6.2", "t3g/svg-sanitizer": "<1.0.3", "tastyigniter/tastyigniter": "<3.3", + "tcg/voyager": "<=1.4", "tecnickcom/tcpdf": "<6.2.22", "terminal42/contao-tablelookupwizard": "<3.3.5", "thelia/backoffice-default-template": ">=2.1,<2.1.2", @@ -9869,7 +9870,7 @@ "type": "tidelift" } ], - "time": "2023-04-26T20:04:23+00:00" + "time": "2023-04-28T21:04:09+00:00" }, { "name": "sebastian/cli-parser", @@ -11056,16 +11057,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.2.7", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "82b6c62b959f642d000456f08c6d219d749215b3" + "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/82b6c62b959f642d000456f08c6d219d749215b3", - "reference": "82b6c62b959f642d000456f08c6d219d749215b3", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894", + "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894", "shasum": "" }, "require": { @@ -11099,7 +11100,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.2.7" + "source": "https://github.com/symfony/filesystem/tree/v6.2.10" }, "funding": [ { @@ -11115,7 +11116,7 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:44:56+00:00" + "time": "2023-04-18T13:46:08+00:00" }, { "name": "symfony/options-resolver", @@ -11410,16 +11411,16 @@ }, { "name": "symfony/yaml", - "version": "v6.2.7", + "version": "v6.2.10", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e8e6a1d59e050525f27a1f530aa9703423cb7f57" + "reference": "61916f3861b1e9705b18cfde723921a71dd1559d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e8e6a1d59e050525f27a1f530aa9703423cb7f57", - "reference": "e8e6a1d59e050525f27a1f530aa9703423cb7f57", + "url": "https://api.github.com/repos/symfony/yaml/zipball/61916f3861b1e9705b18cfde723921a71dd1559d", + "reference": "61916f3861b1e9705b18cfde723921a71dd1559d", "shasum": "" }, "require": { @@ -11464,7 +11465,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.2.7" + "source": "https://github.com/symfony/yaml/tree/v6.2.10" }, "funding": [ { @@ -11480,7 +11481,7 @@ "type": "tidelift" } ], - "time": "2023-02-16T09:57:23+00:00" + "time": "2023-04-28T13:25:36+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", diff --git a/config/cycle.php b/config/cycle.php index 2dab7055..878a2450 100644 --- a/config/cycle.php +++ b/config/cycle.php @@ -4,6 +4,7 @@ use Cycle\Annotated; use Cycle\Database\Config; +use Cycle\Database\Driver; use Cycle\ORM\Collection; use Cycle\ORM\SchemaInterface; use Cycle\Schema; @@ -70,7 +71,7 @@ */ 'databases' => [ 'default' => [ - 'driver' => 'sqlite', + 'driver' => env('DB_CONNECTION', 'sqlite'), ], ], @@ -94,13 +95,14 @@ 'pgsql' => new Config\PostgresDriverConfig( connection: new Config\Postgres\TcpConnectionConfig( - database: env('DB_NAME', 'wod'), + database: env('DB_DATABASE', 'wod'), host: env('DB_HOST', '127.0.0.1'), port: (int) env('DB_PORT', 5432), - user: env('DB_USER', 'wod'), - password: env('DB_PASSWORD') + user: env('DB_USERNAME', 'wod'), + password: env('DB_PASSWORD', '') ), schema: Config\PostgresDriverConfig::DEFAULT_SCHEMA, + driver: Driver\Postgres\PostgresDriver::class, reconnect: true, timezone: 'UTC', queryCache: true @@ -108,23 +110,29 @@ 'mysql' => new Config\MySQLDriverConfig( connection: new Config\MySQL\TcpConnectionConfig( - database: env('DB_NAME', 'wod'), + database: env('DB_DATABASE', 'wod'), host: env('DB_HOST', '127.0.0.1'), port: (int) env('DB_PORT', 3306), - user: env('DB_USER', 'wod'), - password: env('DB_PASSWORD') + user: env('DB_USERNAME', 'wod'), + password: env('DB_PASSWORD', '') ), + driver: Driver\MySQL\MySQLDriver::class, + reconnect: true, + timezone: 'UTC', queryCache: true, ), 'sqlserver' => new Config\SQLServerDriverConfig( connection: new Config\SQLServer\TcpConnectionConfig( - database: env('DB_NAME', 'wod'), + database: env('DB_DATABASE', 'wod'), host: env('DB_HOST', '127.0.0.1'), port: (int) env('DB_PORT', 1433), - user: env('DB_USER', 'wod'), - password: env('DB_PASSWORD') + user: env('DB_USERNAME', 'wod'), + password: env('DB_PASSWORD', '') ), + driver: Driver\SQLServer\SQLServerDriver::class, + reconnect: true, + timezone: 'UTC', queryCache: true, ), ], @@ -138,7 +146,10 @@ * false - Schema won't be stored in a cache after compilation. * It will be automatically changed after entity modification. (Development mode) */ - 'cache' => env('CYCLE_SCHEMA_CACHE', true), + 'cache' => [ + 'enabled' => env('CYCLE_SCHEMA_CACHE', true), + 'store' => env('CACHE_DRIVER', 'file'), + ], /* * The CycleORM provides the ability to manage default settings for @@ -167,45 +178,45 @@ * null (default) - Will be used schema generators defined in bootloaders */ 'generators' => [ -// GeneratorLoader::GROUP_INDEX => [ -// // Register embeddable entities -// Annotated\Embeddings::class, -// // Register annotated entities -// Annotated\Entities::class, -// // Register STI/JTI -// Annotated\TableInheritance::class, -// // Add @Table column declarations -// Annotated\MergeColumns::class, -// ], -// GeneratorLoader::GROUP_RENDER => [ -// // Re-declared table schemas (remove columns) -// Schema\Generator\ResetTables::class, -// // Generate entity relations -// Schema\Generator\GenerateRelations::class, -// // Generate changes from schema modifiers -// Schema\Generator\GenerateModifiers::class, -// // Make sure all entity schemas are correct -// Schema\Generator\ValidateEntities::class, -// // Declare table schemas -// Schema\Generator\RenderTables::class, -// // Declare relation keys and indexes -// Schema\Generator\RenderRelations::class, -// // Render all schema modifiers -// Schema\Generator\RenderModifiers::class, -// // Add @Table column declarations -// Annotated\MergeIndexes::class, -// ], -// GeneratorLoader::GROUP_POSTPROCESS => [ -// // Typecast non string columns -// Schema\Generator\GenerateTypecast::class, -// ], + GeneratorLoader::GROUP_INDEX => [ + // Register embeddable entities + Annotated\Embeddings::class, + // Register annotated entities + Annotated\Entities::class, + // Register STI/JTI + Annotated\TableInheritance::class, + // Add @Table column declarations + Annotated\MergeColumns::class, + ], + GeneratorLoader::GROUP_RENDER => [ + // Re-declared table schemas (remove columns) + Schema\Generator\ResetTables::class, + // Generate entity relations + Schema\Generator\GenerateRelations::class, + // Generate changes from schema modifiers + Schema\Generator\GenerateModifiers::class, + // Make sure all entity schemas are correct + Schema\Generator\ValidateEntities::class, + // Declare table schemas + Schema\Generator\RenderTables::class, + // Declare relation keys and indexes + Schema\Generator\RenderRelations::class, + // Render all schema modifiers + Schema\Generator\RenderModifiers::class, + // Add @Table column declarations + Annotated\MergeIndexes::class, + ], + GeneratorLoader::GROUP_POSTPROCESS => [ + // Typecast non string columns + Schema\Generator\GenerateTypecast::class, + ], ], ], 'migrations' => [ - 'directory' => database_path('migrations'), + 'directory' => database_path('migrations/cycle'), - 'table' => env('DB_MIGRATIONS_TABLE', 'migrations'), + 'table' => env('DB_MIGRATIONS_TABLE', 'cycle_migrations'), 'safe' => env('APP_ENV') !== 'production', ], diff --git a/src/Bridge/Laravel/Console/Commands/Migrations/AbstractCommand.php b/src/Bridge/Laravel/Console/Commands/Migrations/AbstractCommand.php index 9ec08700..e23f9e73 100644 --- a/src/Bridge/Laravel/Console/Commands/Migrations/AbstractCommand.php +++ b/src/Bridge/Laravel/Console/Commands/Migrations/AbstractCommand.php @@ -4,6 +4,7 @@ namespace WayOfDev\Cycle\Bridge\Laravel\Console\Commands\Migrations; +use Cycle\Migrations\Config\MigrationConfig; use Cycle\Migrations\Migrator; use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; @@ -17,7 +18,7 @@ abstract class AbstractCommand extends Command private const DEFAULT_CONFIRMATION = 'Confirmation is required to run migrations!'; - public function __construct(protected Migrator $migrator) + public function __construct(protected Migrator $migrator, protected MigrationConfig $config) { parent::__construct(); } @@ -39,7 +40,7 @@ protected function verifyEnvironment(string $confirmationQuestion = null): bool { $confirmationQuestion = $confirmationQuestion ?? self::DEFAULT_CONFIRMATION; - if ($this->option('force')) { + if ($this->option('force') || $this->config->isSafe()) { return true; } diff --git a/src/Bridge/Laravel/Console/Commands/ORM/MigrateCommand.php b/src/Bridge/Laravel/Console/Commands/ORM/MigrateCommand.php index 9dc05ba2..4b95cb97 100644 --- a/src/Bridge/Laravel/Console/Commands/ORM/MigrateCommand.php +++ b/src/Bridge/Laravel/Console/Commands/ORM/MigrateCommand.php @@ -5,21 +5,17 @@ namespace WayOfDev\Cycle\Bridge\Laravel\Console\Commands\ORM; use Cycle\Migrations\State; +use Cycle\Schema\Compiler as CycleSchemaCompiler; use Cycle\Schema\Generator\Migrations\GenerateMigrations; use Cycle\Schema\Registry; -use Illuminate\Container\Container; -use Illuminate\Contracts\Container\BindingResolutionException; use Symfony\Component\Console\Command\Command; use WayOfDev\Cycle\Bridge\Laravel\Console\Commands\Migrations\AbstractCommand; use WayOfDev\Cycle\Bridge\Laravel\Console\Commands\Migrations\MigrateCommand as DatabaseMigrateCommand; use WayOfDev\Cycle\Bridge\Laravel\Console\Commands\ORM\Generators\ShowChanges; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrators\RegisterSchema; use WayOfDev\Cycle\Contracts\CacheManager as CacheManagerContract; -use WayOfDev\Cycle\Contracts\Config\Repository as Config; +use WayOfDev\Cycle\Contracts\GeneratorLoader; use WayOfDev\Cycle\Schema\Compiler; -use function array_merge; - /** * See original spiral framework commands. * @@ -32,14 +28,9 @@ final class MigrateCommand extends AbstractCommand protected $description = 'Generate ORM schema migrations.'; - /** - * @throws BindingResolutionException - */ public function handle( - Container $app, - RegisterSchema $bootloader, + GeneratorLoader $generators, Registry $registry, - Config $config, GenerateMigrations $migrations, CacheManagerContract $cache ): int { @@ -49,23 +40,21 @@ public function handle( foreach ($this->migrator->getMigrations() as $migration) { if ($migration->getState()->getStatus() !== State::STATUS_EXECUTED) { - $this->warn('Outstanding migrations found, run `cycle:migrate` first!'); + $this->warn('Outstanding migrations found, run `cycle:orm:migrate` first!'); return self::FAILURE; } } - $schemaCompiler = Compiler::compile( - $registry, - array_merge($bootloader->getGenerators($app, $config), [ - $diff = new ShowChanges($this->output), - ]) - ); + $diff = new ShowChanges($this->output); + $queue = $generators->add(GeneratorLoader::GROUP_RENDER, $diff); + $schemaCompiler = Compiler::compile($registry, $queue); $schemaCompiler->toMemory($cache); if ($diff->hasChanges()) { - (new \Cycle\Schema\Compiler())->compile($registry, [$migrations]); + // Creates migration files in database/migrations directory. + (new CycleSchemaCompiler())->compile($registry, [$migrations]); if ($this->option('run')) { $this->call(DatabaseMigrateCommand::class, ['--force' => true]); diff --git a/src/Bridge/Laravel/Console/Commands/ORM/SyncCommand.php b/src/Bridge/Laravel/Console/Commands/ORM/SyncCommand.php index cfd0f4ba..382a0202 100644 --- a/src/Bridge/Laravel/Console/Commands/ORM/SyncCommand.php +++ b/src/Bridge/Laravel/Console/Commands/ORM/SyncCommand.php @@ -7,16 +7,11 @@ use Cycle\Schema\Generator\SyncTables; use Cycle\Schema\Registry; use Illuminate\Console\Command; -use Illuminate\Container\Container; -use Illuminate\Contracts\Container\BindingResolutionException; use WayOfDev\Cycle\Bridge\Laravel\Console\Commands\ORM\Generators\ShowChanges; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrators\RegisterSchema; use WayOfDev\Cycle\Contracts\CacheManager as CacheManagerContract; -use WayOfDev\Cycle\Contracts\Config\Repository as Config; +use WayOfDev\Cycle\Contracts\GeneratorLoader; use WayOfDev\Cycle\Schema\Compiler; -use function array_merge; - /** * See original spiral framework commands. * @@ -28,25 +23,17 @@ final class SyncCommand extends Command protected $description = 'Sync Cycle ORM schema with database without intermediate migration (risk operation).'; - /** - * @throws BindingResolutionException - */ public function handle( - Container $app, - RegisterSchema $bootloader, + GeneratorLoader $generators, Registry $registry, - Config $config, CacheManagerContract $cache ): int { $diff = new ShowChanges($this->output); + $queue = $generators + ->add(GeneratorLoader::GROUP_RENDER, $diff) + ->add(GeneratorLoader::GROUP_POSTPROCESS, new SyncTables()); - $schemaCompiler = Compiler::compile( - $registry, - array_merge( - $bootloader->getGenerators($app, $config), - [$diff, new SyncTables()] - ) - ); + $schemaCompiler = Compiler::compile($registry, $queue); $schemaCompiler->toMemory($cache); if ($diff->hasChanges()) { diff --git a/src/Bridge/Laravel/Console/Commands/ORM/UpdateCommand.php b/src/Bridge/Laravel/Console/Commands/ORM/UpdateCommand.php index a50fecab..c1091726 100644 --- a/src/Bridge/Laravel/Console/Commands/ORM/UpdateCommand.php +++ b/src/Bridge/Laravel/Console/Commands/ORM/UpdateCommand.php @@ -6,11 +6,8 @@ use Cycle\Schema\Registry; use Illuminate\Console\Command; -use Illuminate\Container\Container; -use Illuminate\Contracts\Container\BindingResolutionException; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrators\RegisterSchema; use WayOfDev\Cycle\Contracts\CacheManager as CacheManagerContract; -use WayOfDev\Cycle\Contracts\Config\Repository as Config; +use WayOfDev\Cycle\Contracts\GeneratorLoader; use WayOfDev\Cycle\Schema\Compiler; /** @@ -24,22 +21,14 @@ final class UpdateCommand extends Command protected $description = 'Update (init) cycle schema from database and annotated classes'; - /** - * @throws BindingResolutionException - */ public function handle( - Container $app, - RegisterSchema $bootloader, + GeneratorLoader $generators, Registry $registry, - Config $config, CacheManagerContract $cache ): int { $this->info('Updating ORM schema...'); - Compiler::compile( - $registry, - $bootloader->getGenerators($app, $config) - )->toMemory($cache); + Compiler::compile($registry, $generators)->toMemory($cache); $this->info('Done'); diff --git a/src/Bridge/Laravel/Providers/CycleServiceProvider.php b/src/Bridge/Laravel/Providers/CycleServiceProvider.php index b2c1c538..bcf6676b 100644 --- a/src/Bridge/Laravel/Providers/CycleServiceProvider.php +++ b/src/Bridge/Laravel/Providers/CycleServiceProvider.php @@ -30,7 +30,7 @@ public function register(): void ); $registrators = [ - Registrators\RegisterAdapterConfig::class, + Registrators\RegisterConfigs::class, Registrators\RegisterClassesInterface::class, Registrators\RegisterAnnotated::class, Registrators\RegisterORM::class, diff --git a/src/Bridge/Laravel/Providers/Registrator.php b/src/Bridge/Laravel/Providers/Registrator.php index be486a98..247bc502 100644 --- a/src/Bridge/Laravel/Providers/Registrator.php +++ b/src/Bridge/Laravel/Providers/Registrator.php @@ -10,4 +10,7 @@ interface Registrator public const CFG_KEY_DATABASE = 'cycle.database'; public const CFG_KEY_TOKENIZER = 'cycle.tokenizer'; public const CFG_KEY_MIGRATIONS = 'cycle.migrations'; + public const CFG_KEY_SCHEMA = 'cycle.schema'; + public const CFG_KEY_WARMUP = 'cycle.warmup'; + public const CFG_KEY_RELATIONS = 'cycle.customRelations'; } diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterAdapterConfig.php b/src/Bridge/Laravel/Providers/Registrators/RegisterAdapterConfig.php deleted file mode 100644 index 292982a3..00000000 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterAdapterConfig.php +++ /dev/null @@ -1,24 +0,0 @@ -singleton(ConfigRepository::class, static function (Container $app): ConfigRepository { - /** @var IlluminateConfig $config */ - $config = $app[IlluminateConfig::class]; - - return Config::fromArray($config->get(Registrator::CFG_KEY)); - }); - } -} diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotated.php b/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotated.php index a91e2fee..35e354d8 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotated.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotated.php @@ -10,6 +10,9 @@ use Spiral\Attributes\ReaderInterface; use Spiral\Tokenizer\ClassesInterface; +/** + * @see https://github.com/spiral/cycle-bridge/blob/2.0/src/Bootloader/AnnotatedBootloader.php + */ final class RegisterAnnotated { public function __invoke(Container $app): void @@ -20,33 +23,33 @@ public function __invoke(Container $app): void $app->bind(Annotated\Embeddings::class, function ($app) { return new Annotated\Embeddings( - $app[ClassesInterface::class], - $app[ReaderInterface::class] + $app->get(ClassesInterface::class), + $app->get(ReaderInterface::class) ); }); $app->bind(Annotated\Entities::class, function ($app) { return new Annotated\Entities( - $app[ClassesInterface::class], - $app[ReaderInterface::class] + $app->get(ClassesInterface::class), + $app->get(ReaderInterface::class) ); }); $app->bind(Annotated\MergeColumns::class, function ($app) { return new Annotated\MergeColumns( - $app[ReaderInterface::class] + $app->get(ReaderInterface::class) ); }); $app->bind(Annotated\TableInheritance::class, function ($app) { return new Annotated\TableInheritance( - $app[ReaderInterface::class] + $app->get(ReaderInterface::class) ); }); $app->bind(Annotated\MergeIndexes::class, function ($app) { return new Annotated\MergeIndexes( - $app[ReaderInterface::class] + $app->get(ReaderInterface::class) ); }); } diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterface.php b/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterface.php index 9351106c..9754975e 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterface.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterface.php @@ -5,41 +5,47 @@ namespace WayOfDev\Cycle\Bridge\Laravel\Providers\Registrators; use Illuminate\Container\Container; -use Illuminate\Contracts\Config\Repository as IlluminateConfig; use Spiral\Tokenizer\ClassesInterface; +use Spiral\Tokenizer\ClassLocator; use Spiral\Tokenizer\Config\TokenizerConfig; use Spiral\Tokenizer\InvocationLocator; use Spiral\Tokenizer\InvocationsInterface; use Spiral\Tokenizer\ScopedClassesInterface; use Spiral\Tokenizer\ScopedClassLocator; use Spiral\Tokenizer\Tokenizer; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrator; +/** + * @see https://github.com/spiral/tokenizer/blob/master/src/Bootloader/TokenizerBootloader.php + */ final class RegisterClassesInterface { public function __invoke(Container $app): void { - $app->singleton(TokenizerConfig::class, static function (Container $app): TokenizerConfig { - /** @var IlluminateConfig $config */ - $config = $app[IlluminateConfig::class]; - - return new TokenizerConfig($config->get(Registrator::CFG_KEY_TOKENIZER)); - }); - $app->singleton(Tokenizer::class, static function (Container $app): Tokenizer { return new Tokenizer($app[TokenizerConfig::class]); }); - $app->singleton(ScopedClassesInterface::class, static function ($app): ScopedClassesInterface { - return new ScopedClassLocator($app[TokenizerConfig::class]); + $app->bind(ScopedClassesInterface::class, static function ($app): ScopedClassesInterface { + /** @var Tokenizer $tokenizer */ + $tokenizer = $app->get(Tokenizer::class); + + return new ScopedClassLocator($tokenizer); }); - $app->singleton(ClassesInterface::class, static function ($app): ClassesInterface { - return (new Tokenizer($app[TokenizerConfig::class]))->classLocator(); + $app->bind(ClassesInterface::class, static function ($app): ClassesInterface { + /** @var Tokenizer $tokenizer */ + $tokenizer = $app->get(Tokenizer::class); + + return $tokenizer->classLocator(); }); - $app->singleton(InvocationsInterface::class, static function ($app): InvocationLocator { - return new InvocationLocator($app[TokenizerConfig::class]); + $app->bind(InvocationsInterface::class, static function ($app): InvocationLocator { + /** @var Tokenizer $tokenizer */ + $tokenizer = $app->get(Tokenizer::class); + + return $tokenizer->invocationLocator(); }); + + $app->alias(ClassesInterface::class, ClassLocator::class); } } diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterConfigs.php b/src/Bridge/Laravel/Providers/Registrators/RegisterConfigs.php new file mode 100644 index 00000000..79b94faf --- /dev/null +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterConfigs.php @@ -0,0 +1,79 @@ +registerDatabaseConfig($app); + $this->registerMigrationConfig($app); + $this->registerTokenizerConfig($app); + $this->registerSchemaConfig($app); + $this->registerRelationConfig($app); + } + + private function registerDatabaseConfig(Container $app): void + { + $app->singleton(DatabaseConfig::class, static function (Container $app): DatabaseConfig { + /** @var IlluminateConfig $config */ + $config = $app->get(IlluminateConfig::class); + + return new DatabaseConfig( + config: $config->get(Registrator::CFG_KEY_DATABASE) + ); + }); + } + + private function registerMigrationConfig(Container $app): void + { + $app->singleton(MigrationConfig::class, static function (Container $app): MigrationConfig { + /** @var IlluminateConfig $config */ + $config = $app->get(IlluminateConfig::class); + + return new MigrationConfig($config->get(Registrator::CFG_KEY_MIGRATIONS)); + }); + } + + private function registerTokenizerConfig(Container $app): void + { + $app->singleton(TokenizerConfig::class, static function (Container $app): TokenizerConfig { + /** @var IlluminateConfig $config */ + $config = $app->get(IlluminateConfig::class); + + return new TokenizerConfig($config->get(Registrator::CFG_KEY_TOKENIZER)); + }); + } + + private function registerSchemaConfig(Container $app): void + { + $app->singleton(SchemaConfig::class, static function (Container $app): SchemaConfig { + /** @var IlluminateConfig $config */ + $config = $app->get(IlluminateConfig::class); + + return new SchemaConfig($config->get(Registrator::CFG_KEY_SCHEMA)); + }); + } + + private function registerRelationConfig(Container $app): void + { + $app->singleton(RelationConfig::class, static function (Container $app): RelationConfig { + /** @var IlluminateConfig $config */ + $config = $app->get(IlluminateConfig::class); + $relations = RelationConfig::getDefault()->toArray() + $config->get(Registrator::CFG_KEY_RELATIONS); + + return new RelationConfig($relations); + }); + } +} diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterDatabase.php b/src/Bridge/Laravel/Providers/Registrators/RegisterDatabase.php index defe92bb..ad4b31cf 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterDatabase.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterDatabase.php @@ -9,30 +9,23 @@ use Cycle\Database\DatabaseManager; use Cycle\Database\DatabaseProviderInterface; use Illuminate\Container\Container; -use Illuminate\Contracts\Config\Repository as IlluminateConfig; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrator; +/** + * @see https://github.com/spiral/cycle-bridge/blob/2.0/src/Bootloader/DatabaseBootloader.php + */ final class RegisterDatabase { public function __invoke(Container $app): void { - $app->singleton(DatabaseConfig::class, static function (Container $app): DatabaseConfig { - /** @var IlluminateConfig $config */ - $config = $app[IlluminateConfig::class]; - - return new DatabaseConfig( - config: $config->get(Registrator::CFG_KEY_DATABASE) - ); - }); - $app->singleton(DatabaseProviderInterface::class, static function (Container $app): DatabaseProviderInterface { return new DatabaseManager( - config: $app[DatabaseConfig::class] + config: $app->get(DatabaseConfig::class), + loggerFactory: null ); }); $app->bind(DatabaseInterface::class, static function (Container $app): DatabaseInterface { - return $app[DatabaseProviderInterface::class]->database(); + return $app->get(DatabaseProviderInterface::class)->database(); }); $app->alias(DatabaseProviderInterface::class, DatabaseManager::class); diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterMigrations.php b/src/Bridge/Laravel/Providers/Registrators/RegisterMigrations.php index 556db56d..8d670e3b 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterMigrations.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterMigrations.php @@ -10,22 +10,16 @@ use Cycle\Migrations\Migrator; use Cycle\Migrations\RepositoryInterface; use Illuminate\Container\Container; -use Illuminate\Contracts\Config\Repository as IlluminateConfig; -use WayOfDev\Cycle\Bridge\Laravel\Providers\Registrator; +/** + * @see https://github.com/spiral/cycle-bridge/blob/2.0/src/Bootloader/MigrationsBootloader.php + */ final class RegisterMigrations { public function __invoke(Container $app): void { - $app->singleton(MigrationConfig::class, static function (Container $app): MigrationConfig { - /** @var IlluminateConfig $config */ - $config = $app[IlluminateConfig::class]; - - return new MigrationConfig($config->get(Registrator::CFG_KEY_MIGRATIONS)); - }); - $app->singleton(RepositoryInterface::class, static function (Container $app): RepositoryInterface { - $config = $app[MigrationConfig::class]; + $config = $app->get(MigrationConfig::class); return new FileRepository( config: $config @@ -34,9 +28,9 @@ public function __invoke(Container $app): void $app->singleton(Migrator::class, static function (Container $app): Migrator { return new Migrator( - config: $app[MigrationConfig::class], - dbal: $app[DatabaseProviderInterface::class], - repository: $app[RepositoryInterface::class] + config: $app->get(MigrationConfig::class), + dbal: $app->get(DatabaseProviderInterface::class), + repository: $app->get(RepositoryInterface::class) ); }); } diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterORM.php b/src/Bridge/Laravel/Providers/Registrators/RegisterORM.php index db240b22..ec665bd6 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterORM.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterORM.php @@ -14,37 +14,39 @@ use Cycle\ORM\ORMInterface; use Cycle\ORM\SchemaInterface; use Illuminate\Container\Container; -use WayOfDev\Cycle\Contracts\Config\Repository as Config; +use WayOfDev\Cycle\Schema\Config\SchemaConfig; +/** + * @see https://github.com/spiral/cycle-bridge/blob/2.0/src/Bootloader/CycleOrmBootloader.php + */ final class RegisterORM { public function __invoke(Container $app): void { $app->singleton(FactoryInterface::class, static function (Container $app): FactoryInterface { - $config = $app->make(Config::class); - - $collectionFactoryClass = $config->defaultCollectionFactory(); - - $relationConfig = new RelationConfig( - RelationConfig::getDefault()->toArray() + $config->customRelations() - ); + /** @var SchemaConfig $config */ + $config = $app->get(SchemaConfig::class); + $factoryFQCN = $config->defaultCollectionFQCN(); + $factory = $app->make($factoryFQCN); return new Factory( - dbal: $app[DatabaseProviderInterface::class], - config: $relationConfig, - defaultCollectionFactory: new $collectionFactoryClass() + dbal: $app->get(DatabaseProviderInterface::class), + config: $app->get(RelationConfig::class), + defaultCollectionFactory: $factory ); }); $app->singleton(ORMInterface::class, function (Container $app): ORMInterface { return new ORM( - factory: $app[FactoryInterface::class], - schema: $app[SchemaInterface::class] + factory: $app->get(FactoryInterface::class), + schema: $app->get(SchemaInterface::class) ); }); $app->singleton(EntityManagerInterface::class, function (Container $app): EntityManagerInterface { - return new EntityManager($app[ORMInterface::class]); + return new EntityManager( + $app->get(ORMInterface::class) + ); }); } } diff --git a/src/Bridge/Laravel/Providers/Registrators/RegisterSchema.php b/src/Bridge/Laravel/Providers/Registrators/RegisterSchema.php index 4652e868..c05209fd 100644 --- a/src/Bridge/Laravel/Providers/Registrators/RegisterSchema.php +++ b/src/Bridge/Laravel/Providers/Registrators/RegisterSchema.php @@ -4,103 +4,59 @@ namespace WayOfDev\Cycle\Bridge\Laravel\Providers\Registrators; -use Cycle\Annotated; use Cycle\ORM\SchemaInterface; -use Cycle\Schema\Generator; -use Cycle\Schema\GeneratorInterface; use Cycle\Schema\Registry; use Illuminate\Container\Container; use Illuminate\Contracts\Cache\Factory as CacheFactory; -use Illuminate\Contracts\Container\BindingResolutionException; use WayOfDev\Cycle\Contracts\CacheManager as CacheManagerContract; -use WayOfDev\Cycle\Contracts\Config\Repository as Config; +use WayOfDev\Cycle\Contracts\GeneratorLoader; use WayOfDev\Cycle\Schema\Cache\Manager as CacheManager; use WayOfDev\Cycle\Schema\Compiler; +use WayOfDev\Cycle\Schema\Config\SchemaConfig; +use WayOfDev\Cycle\Schema\Generators\GeneratorQueue; -use function array_merge; -use function is_array; -use function is_object; - +/** + * @see https://github.com/spiral/cycle-bridge/blob/2.0/src/Bootloader/SchemaBootloader.php + */ final class RegisterSchema { - public const GROUP_INDEX = 'index'; - public const GROUP_RENDER = 'render'; - public const GROUP_POSTPROCESS = 'postprocess'; - - /** @var string[][]|GeneratorInterface[][] */ - private array $defaultGenerators; - public function __invoke(Container $app): void { - $this->defaultGenerators = [ - self::GROUP_INDEX => [ - Annotated\Embeddings::class, - Annotated\Entities::class, - Annotated\MergeColumns::class, - ], - self::GROUP_RENDER => [ - Generator\ResetTables::class, - Generator\GenerateRelations::class, - Generator\GenerateModifiers::class, - Generator\ValidateEntities::class, - Generator\RenderTables::class, - Generator\RenderRelations::class, - Generator\RenderModifiers::class, - Annotated\TableInheritance::class, - Annotated\MergeIndexes::class, - ], - self::GROUP_POSTPROCESS => [ - Generator\GenerateTypecast::class, - ], - ]; - $app->singleton(CacheManagerContract::class, static function (Container $app): CacheManagerContract { return new CacheManager( - config: $app[Config::class], - cacheFactory: $app[CacheFactory::class] + config: $app->get(SchemaConfig::class), + cacheFactory: $app->get(CacheFactory::class) ); }); - $app->bind(SchemaInterface::class, function (Container $app): SchemaInterface { - $config = $app->make(Config::class); + $app->singleton(GeneratorLoader::class, static function (Container $app): GeneratorLoader { + return new GeneratorQueue( + app: $app, + config: $app->get(SchemaConfig::class), + ); + }); + + $app->bind(SchemaInterface::class, static function (Container $app): SchemaInterface { + /** @var SchemaConfig $config */ + $config = $app->get(SchemaConfig::class); + + /** @var CacheManagerContract $cache */ + $cache = $app->get(CacheManagerContract::class); - $schemaCompiler = Compiler::fromMemory($app[CacheManagerContract::class]); + $schemaCompiler = Compiler::fromMemory( + cache: $cache + ); - if ($schemaCompiler->isEmpty() || ! $config->schemaCache()) { + if ($schemaCompiler->isEmpty() || ! $config->cacheSchema()) { $schemaCompiler = Compiler::compile( - $app->get(Registry::class), - $this->getGenerators($app, $config), - $config->schemaDefaults(), + registry: $app->get(Registry::class), + queue: $app->get(GeneratorLoader::class), ); + + $schemaCompiler->toMemory($cache); } return $schemaCompiler->toSchema(); }); } - - /** - * @throws BindingResolutionException - */ - public function getGenerators(Container $app, Config $config): array - { - $generators = $config->schemaGenerators(); - if (is_array($generators)) { - $generators = array_merge([self::GROUP_INDEX => $generators], $generators); - } else { - $generators = $this->defaultGenerators; - } - - $result = []; - foreach ($generators as $group) { - foreach ($group as $generator) { - if (is_object($generator)) { - $result[] = $generator; - } else { - $result[] = $app->make($generator); - } - } - } - - return $result; - } } diff --git a/src/Config.php b/src/Config.php deleted file mode 100644 index 128bfa3e..00000000 --- a/src/Config.php +++ /dev/null @@ -1,139 +0,0 @@ -tokenizer; - } - - public function database(): array - { - return $this->database; - } - - public function schema(): array - { - return $this->schema; - } - - public function schemaGenerators(): ?array - { - return Arr::get($this->schema, 'generators'); - } - - public function schemaDefaults(): array - { - return Arr::get($this->schema, 'defaults', []); - } - - public function schemaCache(): bool - { - return (bool) Arr::get($this->schema, 'cache', true); - } - - public function manuallyDefinedSchema(): array - { - return Arr::get($this->schema, 'map', []); - } - - public function migrationsDirectory(): string - { - return Arr::get($this->migrations, 'directory'); - } - - public function migrationsTable(): string - { - return Arr::get($this->migrations, 'table'); - } - - public function safeToMigrate(): bool - { - return Arr::get($this->migrations, 'safe'); - } - - public function warmup(): bool - { - return $this->warmup; - } - - public function customRelations(): array - { - return $this->customRelations; - } - - public function defaultCollectionName(): string - { - return Arr::get($this->schema, 'collections.default', 'illuminate'); - } - - /** - * @return class-string - */ - public function defaultCollectionFactory(): string - { - return Arr::get( - $this->schema, - "collections.factories.{$this->defaultCollectionName()}", - IlluminateCollectionFactory::class - ); - } - - public function collectionFactories(): array - { - return Arr::get($this->schema, 'collections.factories', []); - } - - private function __construct( - private readonly array $tokenizer, - private readonly array $database, - private readonly array $schema, - private readonly array $migrations, - private readonly bool $warmup, - private readonly array $customRelations - ) { - } -} diff --git a/src/Contracts/CacheManager.php b/src/Contracts/CacheManager.php index 8f992f21..4a0e17e1 100644 --- a/src/Contracts/CacheManager.php +++ b/src/Contracts/CacheManager.php @@ -6,7 +6,7 @@ interface CacheManager { - public function get(): ?array; + public function get(): mixed; public function set(string|array $schema): bool; diff --git a/src/Contracts/Config/Repository.php b/src/Contracts/Config/Repository.php deleted file mode 100644 index 8ecedb3f..00000000 --- a/src/Contracts/Config/Repository.php +++ /dev/null @@ -1,36 +0,0 @@ -|GeneratorInterface $generator + * + * @return $this + */ + public function add(string $group, GeneratorInterface|string $generator): self; + + /** + * @param class-string $removableGenerator + * + * @return $this + */ + public function remove(string $removableGenerator): self; + + /** + * @return array + */ + public function get(): array; + + public function without(): self; +} diff --git a/src/Contracts/SchemaManager.php b/src/Contracts/SchemaManager.php deleted file mode 100644 index a130b158..00000000 --- a/src/Contracts/SchemaManager.php +++ /dev/null @@ -1,16 +0,0 @@ -cacheStore()->get(self::SCHEMA_CACHE_KEY); } @@ -55,8 +55,11 @@ public function isCached(): bool private function cacheStore(): CacheRepository { - return $this->cacheFactory->store( - Arr::get($this->config->schema(), 'cache.storage') + $store = Arr::get( + $this->config->toArray(), + 'cache.store', ); + + return $this->cacheFactory->store($store); } } diff --git a/src/Schema/Compiler.php b/src/Schema/Compiler.php index 5b25ca74..1466389b 100644 --- a/src/Schema/Compiler.php +++ b/src/Schema/Compiler.php @@ -6,22 +6,23 @@ use Cycle\ORM\Schema; use Cycle\ORM\SchemaInterface; -use Cycle\Schema\Compiler as CycleCompiler; +use Cycle\Schema\Compiler as CycleSchemaCompiler; use Cycle\Schema\Registry; -use WayOfDev\Cycle\Contracts\CacheManager as CacheManagerContract; +use WayOfDev\Cycle\Contracts\CacheManager; +use WayOfDev\Cycle\Contracts\GeneratorLoader; use function is_array; -class Compiler +final class Compiler { private const EMPTY_SCHEMA = ':empty:'; - public static function compile(Registry $registry, array $generators, array $defaults = []): self + public static function compile(Registry $registry, GeneratorLoader $queue): self { - return new self((new CycleCompiler())->compile($registry, $generators, $defaults)); + return new self((new CycleSchemaCompiler())->compile($registry, $queue->get())); } - public static function fromMemory(CacheManagerContract $cache): self + public static function fromMemory(CacheManager $cache): self { return new self($cache->get()); } @@ -41,7 +42,7 @@ public function toSchema(): SchemaInterface return new Schema($this->isWriteableSchema() ? $this->schema : []); } - public function toMemory(CacheManagerContract $cache): void + public function toMemory(CacheManager $cache): void { $cache->set($this->isEmpty() ? self::EMPTY_SCHEMA : $this->schema); } diff --git a/src/Schema/Config/SchemaConfig.php b/src/Schema/Config/SchemaConfig.php new file mode 100644 index 00000000..d29c184e --- /dev/null +++ b/src/Schema/Config/SchemaConfig.php @@ -0,0 +1,48 @@ + [ + 'enabled' => false, + 'store' => 'file', + ], + 'defaults' => [], + 'collections' => [ + 'default' => 'array', + 'factories' => [], + ], + 'generators' => [], + ], $config)); + } + + public function generators(): array + { + return $this->config['generators']; + } + + public function defaultCollectionFQCN(): string + { + $default = $this->config['collections']['default']; + $factories = $this->config['collections']['factories']; + + return $factories[$default]; + } + + public function cacheSchema(): bool + { + return $this->config['cache']['enabled']; + } +} diff --git a/src/Schema/Generators/GeneratorQueue.php b/src/Schema/Generators/GeneratorQueue.php new file mode 100644 index 00000000..ac4c8376 --- /dev/null +++ b/src/Schema/Generators/GeneratorQueue.php @@ -0,0 +1,88 @@ +>> */ + private array $generators; + + public function __construct( + private readonly Container $app, + private readonly SchemaConfig $config + ) { + $this->generators = $this->config->generators(); + } + + public function add(string $group, GeneratorInterface|string $generator): GeneratorLoader + { + $queue = clone $this; + + $queue->generators[$group][] = $generator; + + return $queue; + } + + public function remove(string $removableGenerator): GeneratorLoader + { + $queue = clone $this; + + foreach ($queue->generators as $groupKey => $groupName) { + foreach ($groupName as $generatorKey => $generatorDefinition) { + if (is_a($generatorDefinition, $removableGenerator, true)) { + unset($queue->generators[$groupKey][$generatorKey]); + } + } + } + + return $queue; + } + + /** + * @throws BindingResolutionException + */ + public function get(): array + { + $result = []; + + foreach ($this->generators as $group) { + foreach ($group as $generator) { + $result[] = $this->make($generator); + } + } + + return $result; + } + + public function without(): GeneratorLoader + { + $queue = clone $this; + + $queue->generators = []; + + return $queue; + } + + /** + * @throws BindingResolutionException + */ + private function make(GeneratorInterface|string $generator): GeneratorInterface + { + if (is_string($generator)) { + return $this->app->make($generator); + } + + return $generator; + } +} diff --git a/src/Schema/Manager.php b/src/Schema/Manager.php deleted file mode 100644 index d69f4184..00000000 --- a/src/Schema/Manager.php +++ /dev/null @@ -1,49 +0,0 @@ -schema()); - } - - public function flush(): void - { - $this->cache->flush(); - } - - public function schema(array $generators = []): array - { - if ($this->cache->isCached()) { - return $this->cache->get() ?? []; - } - - $manuallyDefinedSchema = $this->config->manuallyDefinedSchema(); - - if (count($manuallyDefinedSchema) > 0) { - return $manuallyDefinedSchema; - } - - return $this->compiler->compile($this->generatorsFactory->get()); - } -} diff --git a/tests/app/database/migrations/cycle/.gitkeep b/tests/app/database/migrations/cycle/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/src/Bridge/Laravel/Console/Commands/Migrations/InitCommandTest.php b/tests/src/Bridge/Laravel/Console/Commands/Migrations/InitCommandTest.php index fa8eaa55..625e49db 100644 --- a/tests/src/Bridge/Laravel/Console/Commands/Migrations/InitCommandTest.php +++ b/tests/src/Bridge/Laravel/Console/Commands/Migrations/InitCommandTest.php @@ -25,6 +25,6 @@ public function it_runs_handle(): void $this::assertSame(0, $status); $this::assertCount(1, $database->getTables()); - $this::assertSame('migrations', $database->getTables()[0]->getName()); + $this::assertSame('cycle_migrations', $database->getTables()[0]->getName()); } } diff --git a/tests/src/Bridge/Laravel/Providers/CycleServiceProviderTest.php b/tests/src/Bridge/Laravel/Providers/CycleServiceProviderTest.php index eac541a0..135d3904 100644 --- a/tests/src/Bridge/Laravel/Providers/CycleServiceProviderTest.php +++ b/tests/src/Bridge/Laravel/Providers/CycleServiceProviderTest.php @@ -4,94 +4,13 @@ namespace WayOfDev\Tests\Bridge\Laravel\Providers; -use Cycle\Annotated; use Cycle\Database\Config\DatabaseConfig; -use Cycle\Database\DatabaseInterface; -use Cycle\Database\DatabaseManager; -use Cycle\Database\DatabaseProviderInterface; -use Cycle\Migrations\Config\MigrationConfig; -use Cycle\Migrations\Migrator; -use Cycle\ORM\EntityManagerInterface; -use Cycle\ORM\ORM; -use Cycle\ORM\ORMInterface; -use Cycle\ORM\Schema; -use Cycle\ORM\SchemaInterface; -use Cycle\Schema\GeneratorInterface; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; -use Spiral\Tokenizer\ClassesInterface; -use Spiral\Tokenizer\ClassLocator; -use Spiral\Tokenizer\Config\TokenizerConfig; -use Spiral\Tokenizer\Tokenizer; -use WayOfDev\Cycle\Contracts\Config\Repository as ConfigRepository; use WayOfDev\Tests\TestCase; class CycleServiceProviderTest extends TestCase { - /** - * @test - * - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function it_gets_adapter_config_instance_from_container(): void - { - $config = $this->app->get(ConfigRepository::class); - - self::assertInstanceOf(ConfigRepository::class, $config); - self::assertEquals(app_path(), $config->tokenizer()['directories'][0]); - } - - /** - * @test - */ - public function it_gets_annotated_embeddings(): void - { - $class = $this->app->make(Annotated\Embeddings::class); - - $this::assertInstanceOf(GeneratorInterface::class, $class); - } - - /** - * @test - */ - public function it_gets_annotated_entities(): void - { - $class = $this->app->make(Annotated\Entities::class); - - $this::assertInstanceOf(GeneratorInterface::class, $class); - } - - /** - * @test - */ - public function it_gets_annotated_merge_columns(): void - { - $class = $this->app->make(Annotated\MergeColumns::class); - - $this::assertInstanceOf(GeneratorInterface::class, $class); - } - - /** - * @test - */ - public function it_gets_annotated_table_inheritance(): void - { - $class = $this->app->make(Annotated\TableInheritance::class); - - $this::assertInstanceOf(GeneratorInterface::class, $class); - } - - /** - * @test - */ - public function it_gets_annotated_merge_indexes(): void - { - $class = $this->app->make(Annotated\MergeIndexes::class); - - $this::assertInstanceOf(GeneratorInterface::class, $class); - } - /** * @test * @@ -107,6 +26,7 @@ public function it_gets_database_config_from_container(): void self::assertArrayHasKey('databases', $config->toArray()); self::assertArrayHasKey('drivers', $config->toArray()); } + // // /** // * @test diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotatedTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotatedTest.php new file mode 100644 index 00000000..40268166 --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterAnnotatedTest.php @@ -0,0 +1,91 @@ +app->get(ReaderInterface::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } + + /** + * @test + */ + public function it_binds_embeddings(): void + { + try { + $this::assertInstanceOf(GeneratorInterface::class, $this->app->get(Embeddings::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } + + /** + * @test + */ + public function it_binds_entities(): void + { + try { + $this::assertInstanceOf(GeneratorInterface::class, $this->app->get(Entities::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } + + /** + * @test + */ + public function it_binds_merge_columns(): void + { + try { + $this::assertInstanceOf(GeneratorInterface::class, $this->app->get(MergeColumns::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } + + /** + * @test + */ + public function it_binds_table_inheritance(): void + { + try { + $this::assertInstanceOf(GeneratorInterface::class, $this->app->get(TableInheritance::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } + + /** + * @test + */ + public function it_binds_merge_indexes(): void + { + try { + $this::assertInstanceOf(GeneratorInterface::class, $this->app->get(MergeIndexes::class)); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterfaceTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterfaceTest.php new file mode 100644 index 00000000..6f70808d --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterClassesInterfaceTest.php @@ -0,0 +1,93 @@ +app->get(Tokenizer::class); + $tokenizer2 = $this->app->get(Tokenizer::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf( + Tokenizer::class, + $tokenizer1 + ); + + $this::assertSame($tokenizer1, $tokenizer2); + } + + /** + * @test + */ + public function it_binds_scoped_classes_interface(): void + { + try { + $class = $this->app->get(ScopedClassesInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(ScopedClassesInterface::class, $class); + } + + /** + * @test + */ + public function it_binds_classes_interface(): void + { + try { + $class = $this->app->get(ClassesInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(ClassesInterface::class, $class); + } + + /** + * @test + */ + public function it_binds_invocations_interface(): void + { + try { + $class = $this->app->get(InvocationsInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(InvocationsInterface::class, $class); + } + + /** + * @test + */ + public function it_aliases_classes_interface_to_class_locator(): void + { + try { + $class = $this->app->get(ClassesInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(ClassLocator::class, $class); + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterConfigsTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterConfigsTest.php new file mode 100644 index 00000000..b1e791ea --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterConfigsTest.php @@ -0,0 +1,104 @@ +app->get(DatabaseConfig::class); + + $this::assertInstanceOf( + DatabaseConfig::class, + $config + ); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + self::assertArrayHasKey('default', $config->toArray()); + self::assertArrayHasKey('databases', $config->toArray()); + self::assertArrayHasKey('drivers', $config->toArray()); + } + + /** + * @test + */ + public function it_registers_migration_config(): void + { + try { + $config = $this->app->get(MigrationConfig::class); + + $this::assertInstanceOf( + MigrationConfig::class, + $config + ); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + self::assertArrayHasKey('directory', $config->toArray()); + self::assertArrayHasKey('table', $config->toArray()); + self::assertArrayHasKey('safe', $config->toArray()); + } + + /** + * @test + */ + public function it_registers_tokenizer_config(): void + { + try { + $config = $this->app->get(TokenizerConfig::class); + + $this::assertInstanceOf( + TokenizerConfig::class, + $config + ); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + self::assertArrayHasKey('directories', $config->toArray()); + self::assertArrayHasKey('exclude', $config->toArray()); + self::assertArrayHasKey('scopes', $config->toArray()); + self::assertArrayHasKey('debug', $config->toArray()); + self::assertArrayHasKey('cache', $config->toArray()); + } + + /** + * @test + */ + public function it_registers_schema_config(): void + { + try { + $config = $this->app->get(SchemaConfig::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + try { + $generators = config()->get('cycle.schema.generators'); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(SchemaConfig::class, $config); + $this::assertEquals($generators, $config->generators()); + $this::assertEquals(IlluminateCollectionFactory::class, $config->defaultCollectionFQCN()); + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterDatabaseTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterDatabaseTest.php new file mode 100644 index 00000000..e2d81c44 --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterDatabaseTest.php @@ -0,0 +1,62 @@ +app->get(DatabaseProviderInterface::class); + $class2 = $this->app->get(DatabaseProviderInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(DatabaseProviderInterface::class, $class1); + $this::assertInstanceOf(DatabaseManager::class, $class1); + + $this::assertSame($class1, $class2); + } + + /** + * @test + */ + public function it_binds_database_interface(): void + { + try { + $class = $this->app->get(DatabaseInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(DatabaseInterface::class, $class); + } + + /** + * @test + */ + public function it_aliases_database_provider_interface_to_database_manager(): void + { + try { + $provider = $this->app->get(DatabaseProviderInterface::class); + $manager = $this->app->get(DatabaseManager::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertSame($provider, $manager); + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterMigrationsTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterMigrationsTest.php new file mode 100644 index 00000000..8f65af59 --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterMigrationsTest.php @@ -0,0 +1,48 @@ +app->get(RepositoryInterface::class); + $class2 = $this->app->get(RepositoryInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(RepositoryInterface::class, $class1); + + $this::assertSame($class1, $class2); + } + + /** + * @test + */ + public function it_registers_migrator_as_singleton(): void + { + try { + $class1 = $this->app->get(Migrator::class); + $class2 = $this->app->get(Migrator::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(Migrator::class, $class1); + + $this::assertSame($class1, $class2); + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterORMTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterORMTest.php new file mode 100644 index 00000000..8f4ee24f --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterORMTest.php @@ -0,0 +1,49 @@ +app->get(FactoryInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(FactoryInterface::class, $class); + $this::assertInstanceOf(Factory::class, $class); + } + + /** + * @test + */ + public function it_registers_orm_as_singleton(): void + { + try { + $class1 = $this->app->get(ORMInterface::class); + $class2 = $this->app->get(ORMInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(ORMInterface::class, $class1); + $this::assertInstanceOf(ORM::class, $class1); + + $this::assertSame($class1, $class2); + } +} diff --git a/tests/src/Bridge/Laravel/Providers/Registrators/RegisterSchemaTest.php b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterSchemaTest.php new file mode 100644 index 00000000..b87e357f --- /dev/null +++ b/tests/src/Bridge/Laravel/Providers/Registrators/RegisterSchemaTest.php @@ -0,0 +1,80 @@ +app->get(CacheManagerContract::class); + $class2 = $this->app->get(CacheManagerContract::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(CacheManagerContract::class, $class1); + $this::assertInstanceOf(CacheManager::class, $class1); + + $this::assertSame($class1, $class2); + } + + /** + * @test + * + * @throws BindingResolutionException + */ + public function it_registers_generator_loader_as_singleton(): void + { + try { + $class1 = $this->app->get(GeneratorLoader::class); + $class2 = $this->app->get(GeneratorLoader::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(GeneratorLoader::class, $class1); + $this::assertInstanceOf(GeneratorQueue::class, $class1); + + $this::assertCount(13, $class1->get()); + } + + /** + * @test + */ + public function it_registers_schema_interface(): void + { + try { + $class1 = $this->app->get(SchemaInterface::class); + // $class2 = $this->app->get(SchemaInterface::class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) { + $this::fail($e->getMessage()); + } + + $this::assertInstanceOf(SchemaInterface::class, $class1); + $this::assertInstanceOf(Schema::class, $class1); + + // $this::assertSame($class1, $class2); + + $schema = $class1->toArray(); + + $this::assertArrayHasKey('user', $schema); + $this::assertArrayHasKey('role', $schema); + } +} diff --git a/tests/src/ConfigTest.php b/tests/src/ConfigTest.php deleted file mode 100644 index 80104cee..00000000 --- a/tests/src/ConfigTest.php +++ /dev/null @@ -1,114 +0,0 @@ - [ - [ - 'tokenizer' => [ - 'directories' => [ - '/foo/bar', - '/boo/bar/baz', - ], - 'exclude' => [], - 'scopes' => [], - ], - 'database' => [ - 'default' => 'default', - 'aliases' => [], - 'databases' => [ - 'default' => [ - 'connection' => 'sqlite', - ], - ], - 'connections' => [ - 'sqlite' => new SQLiteDriverConfig( - connection: new MemoryConnectionConfig(), - queryCache: true - ), - ], - ], - 'schema' => [ - 'cache' => true, - 'defaults' => [ - SchemaInterface::MAPPER => null, - SchemaInterface::REPOSITORY => null, - SchemaInterface::SOURCE => null, - ], - 'collections' => [ - 'default' => 'illuminate', - 'factories' => [ - 'array' => ArrayCollectionFactory::class, - 'illuminate' => IlluminateCollectionFactory::class, - ], - ], - 'generators' => [], - ], - 'migrations' => [ - 'directory' => '/app/vendor/orchestra/testbench-core/laravel/database/migrations', - 'table' => 'migrations', - 'safe' => true, - ], - 'warmup' => true, - 'customRelations' => [], - ], - false, - ], - ]; - } - - /** - * @test - * - * @dataProvider dataProviderForConfig - */ - public function it_creates_config(array $config, bool $throwMissingException): void - { - if ($throwMissingException) { - $this->expectException(MissingRequiredAttributes::class); - } else { - $configToTest = Config::fromArray($config); - - self::assertEquals($config['tokenizer'], $configToTest->tokenizer()); - self::assertEquals($config['database'], $configToTest->database()); - - self::assertEquals($config['schema'], $configToTest->schema()); - self::assertEquals($config['schema']['cache'], $configToTest->schemaCache()); - self::assertEquals($config['schema']['defaults'], $configToTest->schemaDefaults()); - self::assertEquals($config['schema']['collections']['factories'], $configToTest->collectionFactories()); - self::assertEquals($config['schema']['generators'], $configToTest->schemaGenerators()); - - self::assertEquals($config['migrations']['directory'], $configToTest->migrationsDirectory()); - self::assertEquals($config['migrations']['table'], $configToTest->migrationsTable()); - self::assertEquals($config['migrations']['safe'], $configToTest->safeToMigrate()); - - self::assertEquals($config['customRelations'], $configToTest->customRelations()); - } - } - - /** - * @test - */ - public function it_gets_default_collection_class_fqdn(): void - { - /** @var Config $config */ - $config = app(Repository::class); - - self::assertEquals(IlluminateCollectionFactory::class, $config->defaultCollectionFactory()); - } -} diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php index 1edf2cb2..ca2d3501 100644 --- a/tests/src/TestCase.php +++ b/tests/src/TestCase.php @@ -48,6 +48,7 @@ protected function setUp(): void config('cycle.tokenizer.directories'), [__DIR__ . '/../app/Entities'] ), + 'cycle.migrations.directory' => __DIR__ . '/../app/database/migrations/cycle', ]); } } @@ -92,7 +93,9 @@ protected function getPackageProviders($app): array protected function cleanupMigrations(): void { - $files = File::glob(database_path('migrations/*.php')); + $path = __DIR__ . '/../app/database/migrations/cycle/*.php'; + + $files = File::glob($path); foreach ($files as $file) { File::delete($file); }