diff --git a/.travis.yml b/.travis.yml index 883da78..49767e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,117 @@ language: php +sudo: false +dist: trusty -php: - - 7.2 +cache: + directories: + - vendor + - $HOME/.composer/cache -services: - - postgresql - -matrix: - fast_finish: true +before_install: + - phpenv config-rm xdebug.ini || true + - | + if [ "x$COVERAGE" == "xyes" ]; then + pecl install pcov-1.0.0 + fi install: - - composer install - -before_script: - - psql -c 'create database testing;' -U postgres + - rm composer.lock + - travis_retry composer -n update --prefer-dist script: - vendor/bin/ecs check --config=ecs.yml . - - phpdbg -qrr vendor/bin/phpunit --coverage-clover build/logs/clover.xml + - | + if [ "x$DOCKER_POSTGRES" == "xyes" ]; then + sudo docker exec -ti postgres11 psql postgres -U postgres -c "CREATE DATABASE testing" + else + psql -c 'CREATE DATABASE testing;' -U postgres + fi + - | + if [ "x$COVERAGE" == "xyes" ]; then + ./vendor/bin/phpunit --configuration phpunit.travis.xml --coverage-clover build/logs/clover.xml + else + ./vendor/bin/phpunit --configuration phpunit.travis.xml + fi after_success: - - travis_retry vendor/bin/php-coveralls -v + - | + if [ "x$COVERAGE" == "xyes" ]; then + travis_retry vendor/bin/php-coveralls -v + fi + +matrix: + fast_finish: true + allow_failures: + - php: "7.4snapshot" + include: + - stage: Test + php: "7.2" + env: DB=pgsql POSTGRESQL_VERSION=11.0 + sudo: required + services: + - docker + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=9.2 COVERAGE=yes + services: + - postgresql + addons: + postgresql: "9.2" + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=9.3 COVERAGE=yes + services: + - postgresql + addons: + postgresql: "9.3" + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=9.4 COVERAGE=yes + services: + - postgresql + addons: + postgresql: "9.4" + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=9.5 COVERAGE=yes + services: + - postgresql + addons: + postgresql: "9.5" + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=9.6 COVERAGE=yes + services: + - postgresql + addons: + postgresql: "9.6" + - stage: Test + php: "7.3" + env: DB=pgsql POSTGRESQL_VERSION=10.0 COVERAGE=yes + sudo: required + services: + - postgresql + addons: + postgresql: "9.6" + before_script: + - bash ./tests/travis/install-postgres-10.sh + - stage: Test + php: "7.3" + env: DB=pgsql DOCKER_POSTGRES=yes POSTGRESQL_VERSION=11.0 COVERAGE=yes + sudo: required + services: + - docker + - postgresql + addons: + postgresql: "9.6" + before_script: + - bash ./tests/travis/install-postgres-11.sh + - stage: Test + php: "7.4snapshot" + env: DB=pgsql DOCKER_POSTGRES=yes POSTGRESQL_VERSION=11.0 + sudo: required + services: + - docker + - postgresql + before_script: + - bash ./tests/travis/install-postgres-11.sh diff --git a/README.md b/README.md index f974a6e..de52dbf 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ php composer.phar require umbrellio/laravel-pg-extensions ## Features - [Extended `Schema::create()`](#extended-table-creation) - - [Extended `Schema` with GIST/GIN indexes](#create-gist/gin-indexes) + - [Added Support Numeric Type](#numeric-column-type) + - [Extended `Schema` with USING](#extended-schema-using) - [Extended `Schema` for views](#create-views) - [Working with unique indexes](#extended-unique-indexes-creation) - [Working with partitions](#partitions) @@ -31,12 +32,21 @@ Schema::create('table', function (Blueprint $table) { }); ``` -### Create gist/gin indexes +### Extended Schema USING +Example: ```php Schema::create('table', function (Blueprint $table) { - $table->gist(['column1', 'column2']); - $table->gin('column1'); + $table->integer('number'); +}); + +//modifications with data... + +Schema::table('table', function (Blueprint $table) { + $table + ->string('number') + ->using("('[' || number || ']')::character varyiing") + ->change(); }); ``` diff --git a/composer.json b/composer.json index dce9b12..6ab341d 100644 --- a/composer.json +++ b/composer.json @@ -10,10 +10,12 @@ ], "require": { "php": "^7.2", + "doctrine/dbal": "^2.9", "laravel/framework": "^5.8" }, "require-dev": { "umbrellio/code-style-php": "^1.0", + "codeception/codeception": "^3.0", "orchestra/testbench": "^3.5", "php-coveralls/php-coveralls": "^2.1" }, diff --git a/composer.lock b/composer.lock index f8b1d94..57e0594 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": "806be43cfecda6994cd0335061c2ad39", + "content-hash": "98cde3c0428143e26c3295002c4d0968", "packages": [ { "name": "doctrine/cache", @@ -83,31 +83,31 @@ }, { "name": "doctrine/dbal", - "version": "v2.9.2", + "version": "v2.10.4", "source": { "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9" + "url": "https://github.com/pvsaintpe/dbal.git", + "reference": "59aedf521cca50af294bdbbc14337ea3a0293d86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9", - "reference": "22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9", + "url": "https://api.github.com/repos/pvsaintpe/dbal/zipball/59aedf521cca50af294bdbbc14337ea3a0293d86", + "reference": "59aedf521cca50af294bdbbc14337ea3a0293d86", "shasum": "" }, "require": { "doctrine/cache": "^1.0", "doctrine/event-manager": "^1.0", "ext-pdo": "*", - "php": "^7.1" + "php": "^7.2" }, "require-dev": { - "doctrine/coding-standard": "^5.0", - "jetbrains/phpstorm-stubs": "^2018.1.2", - "phpstan/phpstan": "^0.10.1", - "phpunit/phpunit": "^7.4", - "symfony/console": "^2.0.5|^3.0|^4.0", - "symfony/phpunit-bridge": "^3.4.5|^4.0.5" + "doctrine/coding-standard": "^6.0", + "jetbrains/phpstorm-stubs": "^2019.1", + "phpstan/phpstan": "^0.11.3", + "phpunit/phpunit": "^8.2.1", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5|^5.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -118,7 +118,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.9.x-dev", + "dev-master": "2.10.x-dev", "dev-develop": "3.0.x-dev" } }, @@ -127,11 +127,19 @@ "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" } }, - "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, "license": [ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -140,10 +148,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -154,14 +158,28 @@ "keywords": [ "abstraction", "database", + "db2", "dbal", + "mariadb", + "mssql", "mysql", - "persistence", + "oci8", + "oracle", + "pdo", "pgsql", - "php", - "queryobject" - ], - "time": "2018-12-31T03:27:51+00:00" + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlanywhere", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "source": "https://github.com/pvsaintpe/dbal/tree/bug/default-expression" + }, + "time": "2019-07-11T16:39:36+00:00" }, { "name": "doctrine/event-manager", @@ -420,16 +438,16 @@ }, { "name": "egulias/email-validator", - "version": "2.1.9", + "version": "2.1.10", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "128cc721d771ec2c46ce59698f4ca42b73f71b25" + "reference": "a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/128cc721d771ec2c46ce59698f4ca42b73f71b25", - "reference": "128cc721d771ec2c46ce59698f4ca42b73f71b25", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec", + "reference": "a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec", "shasum": "" }, "require": { @@ -439,7 +457,8 @@ "require-dev": { "dominicsayers/isemail": "dev-master", "phpunit/phpunit": "^4.8.35||^5.7||^6.0", - "satooshi/php-coveralls": "^1.0.1" + "satooshi/php-coveralls": "^1.0.1", + "symfony/phpunit-bridge": "^4.4@dev" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -473,7 +492,7 @@ "validation", "validator" ], - "time": "2019-06-23T10:14:27+00:00" + "time": "2019-07-19T20:52:08+00:00" }, { "name": "erusev/parsedown", @@ -523,16 +542,16 @@ }, { "name": "laravel/framework", - "version": "v5.8.27", + "version": "v5.8.29", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "f1dccffb96f614895393e27e4667105a05407af5" + "reference": "489ae2218c7eb138caac780de584d8df9fe8160b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/f1dccffb96f614895393e27e4667105a05407af5", - "reference": "f1dccffb96f614895393e27e4667105a05407af5", + "url": "https://api.github.com/repos/laravel/framework/zipball/489ae2218c7eb138caac780de584d8df9fe8160b", + "reference": "489ae2218c7eb138caac780de584d8df9fe8160b", "shasum": "" }, "require": { @@ -666,7 +685,7 @@ "framework", "laravel" ], - "time": "2019-07-02T13:43:47+00:00" + "time": "2019-07-16T14:05:28+00:00" }, { "name": "league/flysystem", @@ -832,16 +851,16 @@ }, { "name": "nesbot/carbon", - "version": "2.20.0", + "version": "2.21.3", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "bc671b896c276795fad8426b0aa24e8ade0f2498" + "reference": "58bdbbfab17ccd2ec7347b99e997f18232def4dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bc671b896c276795fad8426b0aa24e8ade0f2498", - "reference": "bc671b896c276795fad8426b0aa24e8ade0f2498", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/58bdbbfab17ccd2ec7347b99e997f18232def4dc", + "reference": "58bdbbfab17ccd2ec7347b99e997f18232def4dc", "shasum": "" }, "require": { @@ -857,6 +876,9 @@ "phpunit/phpunit": "^7.5 || ^8.0", "squizlabs/php_codesniffer": "^3.4" }, + "bin": [ + "bin/carbon" + ], "type": "library", "extra": { "laravel": { @@ -879,6 +901,10 @@ "name": "Brian Nesbitt", "email": "brian@nesbot.com", "homepage": "http://nesbot.com" + }, + { + "name": "kylekatarnls", + "homepage": "http://github.com/kylekatarnls" } ], "description": "A simple API extension for DateTime.", @@ -888,20 +914,20 @@ "datetime", "time" ], - "time": "2019-06-25T10:00:57+00:00" + "time": "2019-07-18T18:47:28+00:00" }, { "name": "opis/closure", - "version": "3.3.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/opis/closure.git", - "reference": "f846725591203098246276b2e7b9e8b7814c4965" + "reference": "92927e26d7fc3f271efe1f55bdbb073fbb2f0722" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/f846725591203098246276b2e7b9e8b7814c4965", - "reference": "f846725591203098246276b2e7b9e8b7814c4965", + "url": "https://api.github.com/repos/opis/closure/zipball/92927e26d7fc3f271efe1f55bdbb073fbb2f0722", + "reference": "92927e26d7fc3f271efe1f55bdbb073fbb2f0722", "shasum": "" }, "require": { @@ -949,7 +975,7 @@ "serialization", "serialize" ], - "time": "2019-05-31T20:04:32+00:00" + "time": "2019-07-09T21:58:11+00:00" }, { "name": "paragonie/random_compat", @@ -2745,6 +2771,233 @@ } ], "packages-dev": [ + { + "name": "behat/gherkin", + "version": "v4.6.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/ab0a02ea14893860bca00f225f5621d351a3ad07", + "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3|~4", + "symfony/yaml": "~2.3|~3|~4" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Gherkin DSL parser for PHP 5.3", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "time": "2019-01-16T14:22:17+00:00" + }, + { + "name": "codeception/codeception", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Codeception.git", + "reference": "feb566a9dc26993611602011ae3834d8e3c1dd7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/feb566a9dc26993611602011ae3834d8e3c1dd7f", + "reference": "feb566a9dc26993611602011ae3834d8e3c1dd7f", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.4.0", + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3", + "codeception/stub": "^2.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "facebook/webdriver": "^1.6.0", + "guzzlehttp/guzzle": "^6.3.0", + "guzzlehttp/psr7": "~1.4", + "hoa/console": "~3.0", + "php": ">=5.6.0 <8.0", + "symfony/browser-kit": ">=2.7 <5.0", + "symfony/console": ">=2.7 <5.0", + "symfony/css-selector": ">=2.7 <5.0", + "symfony/dom-crawler": ">=2.7 <5.0", + "symfony/event-dispatcher": ">=2.7 <5.0", + "symfony/finder": ">=2.7 <5.0", + "symfony/yaml": ">=2.7 <5.0" + }, + "require-dev": { + "codeception/specify": "~0.3", + "doctrine/annotations": "^1", + "doctrine/orm": "^2", + "flow/jsonpath": "~0.2", + "monolog/monolog": "~1.8", + "pda/pheanstalk": "~3.0", + "php-amqplib/php-amqplib": "~2.4", + "predis/predis": "^1.0", + "squizlabs/php_codesniffer": "~2.0", + "symfony/process": ">=2.7 <5.0", + "vlucas/phpdotenv": "^3.0" + }, + "suggest": { + "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "flow/jsonpath": "For using JSONPath in REST module", + "league/factory-muffin": "For DataFactory module", + "league/factory-muffin-faker": "For Faker support in DataFactory module", + "phpseclib/phpseclib": "for SFTP option in FTP Module", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/phpunit-bridge": "For phpunit-bridge support" + }, + "bin": [ + "codecept" + ], + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-4": { + "Codeception\\": "src/Codeception", + "Codeception\\Extension\\": "ext" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + } + ], + "description": "BDD-style testing framework", + "homepage": "http://codeception.com/", + "keywords": [ + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "time": "2019-07-18T16:21:08+00:00" + }, + { + "name": "codeception/phpunit-wrapper", + "version": "8.0.4", + "source": { + "type": "git", + "url": "https://github.com/Codeception/phpunit-wrapper.git", + "reference": "7090736f36b4398cae6ef838b9a2bdfe8d8d104b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/7090736f36b4398cae6ef838b9a2bdfe8d8d104b", + "reference": "7090736f36b4398cae6ef838b9a2bdfe8d8d104b", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "phpunit/php-code-coverage": "^7.0", + "phpunit/phpunit": "^8.0", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0" + }, + "require-dev": { + "codeception/specify": "*", + "vlucas/phpdotenv": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\PHPUnit\\": "src\\" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Davert", + "email": "davert.php@resend.cc" + } + ], + "description": "PHPUnit classes used by Codeception", + "time": "2019-02-27T12:58:57+00:00" + }, + { + "name": "codeception/stub", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Stub.git", + "reference": "853657f988942f7afb69becf3fd0059f192c705a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/853657f988942f7afb69becf3fd0059f192c705a", + "reference": "853657f988942f7afb69becf3fd0059f192c705a", + "shasum": "" + }, + "require": { + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "time": "2019-03-02T15:35:10+00:00" + }, { "name": "composer/semver", "version": "1.5.0", @@ -2975,6 +3228,66 @@ ], "time": "2019-03-17T17:37:11+00:00" }, + { + "name": "facebook/webdriver", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "e43de70f3c7166169d0f14a374505392734160e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/e43de70f3c7166169d0f14a374505392734160e5", + "reference": "e43de70f3c7166169d0f14a374505392734160e5", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-zip": "*", + "php": "^5.6 || ~7.0", + "symfony/process": "^2.8 || ^3.1 || ^4.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "php-coveralls/php-coveralls": "^2.0", + "php-mock/php-mock-phpunit": "^1.1", + "phpunit/phpunit": "^5.7", + "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", + "squizlabs/php_codesniffer": "^2.6", + "symfony/var-dumper": "^3.3 || ^4.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-community": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "A PHP client for Selenium WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", + "keywords": [ + "facebook", + "php", + "selenium", + "webdriver" + ], + "time": "2019-06-13T08:02:18+00:00" + }, { "name": "friendsofphp/php-cs-fixer", "version": "v2.15.1", @@ -3349,25 +3662,26 @@ "time": "2016-01-20T08:20:44+00:00" }, { - "name": "jean85/pretty-package-versions", - "version": "1.2", + "name": "hoa/consistency", + "version": "1.17.05.02", "source": { "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" + "url": "https://github.com/hoaproject/Consistency.git", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f", + "reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f", "shasum": "" }, "require": { - "ocramius/package-versions": "^1.2.0", - "php": "^7.0" + "hoa/exception": "~1.0", + "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "hoa/stream": "~1.0", + "hoa/test": "~2.0" }, "type": "library", "extra": { @@ -3377,59 +3691,79 @@ }, "autoload": { "psr-4": { - "Jean85\\": "src/" - } + "Hoa\\Consistency\\": "." + }, + "files": [ + "Prelude.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" } ], - "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "description": "The Hoa\\Consistency library.", + "homepage": "https://hoa-project.net/", "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "time": "2018-06-13T13:22:40+00:00" + "autoloader", + "callable", + "consistency", + "entity", + "flex", + "keyword", + "library" + ], + "time": "2017-05-02T12:18:12+00:00" }, { - "name": "mockery/mockery", - "version": "1.2.2", + "name": "hoa/console", + "version": "3.17.05.02", "source": { "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2" + "url": "https://github.com/hoaproject/Console.git", + "reference": "e231fd3ea70e6d773576ae78de0bdc1daf331a66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", - "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", + "url": "https://api.github.com/repos/hoaproject/Console/zipball/e231fd3ea70e6d773576ae78de0bdc1daf331a66", + "reference": "e231fd3ea70e6d773576ae78de0bdc1daf331a66", "shasum": "" }, "require": { - "hamcrest/hamcrest-php": "~2.0", - "lib-pcre": ">=7.0", - "php": ">=5.6.0" + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/file": "~1.0", + "hoa/protocol": "~1.0", + "hoa/stream": "~1.0", + "hoa/ustring": "~4.0" }, "require-dev": { - "phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0" + "hoa/test": "~2.0" + }, + "suggest": { + "ext-pcntl": "To enable hoa://Event/Console/Window:resize.", + "hoa/dispatcher": "To use the console kit.", + "hoa/router": "To use the console kit." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { - "psr-0": { - "Mockery": "library/" + "psr-4": { + "Hoa\\Console\\": "." } }, "notification-url": "https://packagist.org/downloads/", @@ -3438,51 +3772,579 @@ ], "authors": [ { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" }, { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "name": "Hoa community", + "homepage": "https://hoa-project.net/" } ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", + "description": "The Hoa\\Console library.", + "homepage": "https://hoa-project.net/", "keywords": [ - "BDD", - "TDD", + "autocompletion", + "chrome", + "cli", + "console", + "cursor", + "getoption", "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" + "option", + "parser", + "processus", + "readline", + "terminfo", + "tput", + "window" ], - "time": "2019-02-13T09:37:52+00:00" + "time": "2017-05-02T12:26:19+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.9.1", + "name": "hoa/event", + "version": "1.17.01.13", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "url": "https://github.com/hoaproject/Event.git", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54", + "reference": "6c0060dced212ffa3af0e34bb46624f990b29c54", "shasum": "" }, "require": { - "php": "^7.1" + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" }, - "replace": { - "myclabs/deep-copy": "self.version" + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Event\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Event library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "event", + "library", + "listener", + "observer" + ], + "time": "2017-01-13T15:30:50+00:00" + }, + { + "name": "hoa/exception", + "version": "1.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Exception.git", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f", + "reference": "091727d46420a3d7468ef0595651488bfc3a458f", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Exception\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Exception library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "exception", + "library" + ], + "time": "2017-01-16T07:53:27+00:00" + }, + { + "name": "hoa/file", + "version": "1.17.07.11", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/File.git", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/File/zipball/35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "reference": "35cb979b779bc54918d2f9a4e02ed6c7a1fa67ca", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/iterator": "~2.0", + "hoa/stream": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\File\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\File library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Socket", + "directory", + "file", + "finder", + "library", + "link", + "temporary" + ], + "time": "2017-07-11T07:42:15+00:00" + }, + { + "name": "hoa/iterator", + "version": "2.17.01.10", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Iterator.git", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Iterator/zipball/d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "reference": "d1120ba09cb4ccd049c86d10058ab94af245f0cc", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Iterator\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Iterator library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "iterator", + "library" + ], + "time": "2017-01-10T10:34:47+00:00" + }, + { + "name": "hoa/protocol", + "version": "1.17.01.14", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Protocol.git", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Protocol/zipball/5c2cf972151c45f373230da170ea015deecf19e2", + "reference": "5c2cf972151c45f373230da170ea015deecf19e2", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Protocol\\": "." + }, + "files": [ + "Wrapper.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Protocol library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "protocol", + "resource", + "stream", + "wrapper" + ], + "time": "2017-01-14T12:26:10+00:00" + }, + { + "name": "hoa/stream", + "version": "1.17.02.21", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Stream.git", + "reference": "3293cfffca2de10525df51436adf88a559151d82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Stream/zipball/3293cfffca2de10525df51436adf88a559151d82", + "reference": "3293cfffca2de10525df51436adf88a559151d82", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/event": "~1.0", + "hoa/exception": "~1.0", + "hoa/protocol": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Stream\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Stream library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "Context", + "bucket", + "composite", + "filter", + "in", + "library", + "out", + "protocol", + "stream", + "wrapper" + ], + "time": "2017-02-21T16:01:06+00:00" + }, + { + "name": "hoa/ustring", + "version": "4.17.01.16", + "source": { + "type": "git", + "url": "https://github.com/hoaproject/Ustring.git", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hoaproject/Ustring/zipball/e6326e2739178799b1fe3fdd92029f9517fa17a0", + "reference": "e6326e2739178799b1fe3fdd92029f9517fa17a0", + "shasum": "" + }, + "require": { + "hoa/consistency": "~1.0", + "hoa/exception": "~1.0" + }, + "require-dev": { + "hoa/test": "~2.0" + }, + "suggest": { + "ext-iconv": "ext/iconv must be present (or a third implementation) to use Hoa\\Ustring::transcode().", + "ext-intl": "To get a better Hoa\\Ustring::toAscii() and Hoa\\Ustring::compareTo()." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Hoa\\Ustring\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Ivan Enderlin", + "email": "ivan.enderlin@hoa-project.net" + }, + { + "name": "Hoa community", + "homepage": "https://hoa-project.net/" + } + ], + "description": "The Hoa\\Ustring library.", + "homepage": "https://hoa-project.net/", + "keywords": [ + "library", + "search", + "string", + "unicode" + ], + "time": "2017-01-16T07:08:25+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.2.0", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "time": "2018-06-13T13:22:40+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", + "reference": "0eb0b48c3f07b3b89f5169ce005b7d05b18cf1d2", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~2.0", + "lib-pcre": ">=7.0", + "php": ">=5.6.0" + }, + "require-dev": { + "phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "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" + ], + "time": "2019-02-13T09:37:52+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", @@ -3576,26 +4438,23 @@ }, { "name": "nette/robot-loader", - "version": "v3.1.1", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/nette/robot-loader.git", - "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2" + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/3e8d75d6d976e191bdf46752ca40a286671219d2", - "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", "shasum": "" }, "require": { "ext-tokenizer": "*", - "nette/finder": "^2.3 || ^3.0", - "nette/utils": "^2.4 || ^3.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" + "nette/finder": "^2.5", + "nette/utils": "^3.0", + "php": ">=7.1" }, "require-dev": { "nette/tester": "^2.0", @@ -3604,7 +4463,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3637,27 +4496,24 @@ "nette", "trait" ], - "time": "2019-03-01T20:23:02+00:00" + "time": "2019-03-08T21:57:24+00:00" }, { "name": "nette/utils", - "version": "v2.5.3", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce" + "reference": "bd961f49b211997202bda1d0fbc410905be370d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/17b9f76f2abd0c943adfb556e56f2165460b15ce", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce", + "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4", "shasum": "" }, "require": { - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" + "php": ">=7.1" }, "require-dev": { "nette/tester": "~2.0", @@ -3666,7 +4522,7 @@ "suggest": { "ext-gd": "to use Image", "ext-iconv": "to use Strings::webalize() and toAscii()", - "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", + "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-xml": "to use Strings::length() etc. when mbstring is not available" @@ -3674,15 +4530,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" - ], - "files": [ - "src/loader.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3701,7 +4554,7 @@ "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.", + "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", @@ -3719,38 +4572,39 @@ "utility", "validation" ], - "time": "2018-09-18T10:22:16+00:00" + "time": "2019-03-22T01:00:30+00:00" }, { "name": "ocramius/package-versions", - "version": "1.4.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + "reference": "1d32342b8c1eb27353c8887c366147b4c2da673c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/1d32342b8c1eb27353c8887c366147b4c2da673c", + "reference": "1d32342b8c1eb27353c8887c366147b4c2da673c", "shasum": "" }, "require": { "composer-plugin-api": "^1.0.0", - "php": "^7.1.0" + "php": "^7.3.0" }, "require-dev": { - "composer/composer": "^1.6.3", - "doctrine/coding-standard": "^5.0.1", + "composer/composer": "^1.8.6", + "doctrine/coding-standard": "^6.0.0", "ext-zip": "*", - "infection/infection": "^0.7.1", - "phpunit/phpunit": "^7.0.0" + "infection/infection": "^0.13.4", + "phpunit/phpunit": "^8.2.5", + "vimeo/psalm": "^3.4.9" }, "type": "composer-plugin", "extra": { "class": "PackageVersions\\Installer", "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -3769,7 +4623,7 @@ } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2019-02-21T12:16:21+00:00" + "time": "2019-07-17T15:49:50+00:00" }, { "name": "orchestra/testbench", @@ -4386,16 +5240,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "7.0.5", + "version": "7.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "aed67b57d459dcab93e84a5c9703d3deb5025dff" + "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aed67b57d459dcab93e84a5c9703d3deb5025dff", - "reference": "aed67b57d459dcab93e84a5c9703d3deb5025dff", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", + "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", "shasum": "" }, "require": { @@ -4404,17 +5258,17 @@ "php": "^7.2", "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0.1", + "phpunit/php-token-stream": "^3.1.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.1", + "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-xdebug": "^2.6.1" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { @@ -4434,8 +5288,8 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "role": "lead", + "email": "sebastian@phpunit.de" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", @@ -4445,7 +5299,7 @@ "testing", "xunit" ], - "time": "2019-06-06T12:28:18+00:00" + "time": "2019-07-25T05:31:54+00:00" }, { "name": "phpunit/php-file-iterator", @@ -4589,16 +5443,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", "shasum": "" }, "require": { @@ -4611,7 +5465,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4634,20 +5488,20 @@ "keywords": [ "tokenizer" ], - "time": "2018-10-30T05:52:18+00:00" + "time": "2019-07-25T05:29:42+00:00" }, { "name": "phpunit/phpunit", - "version": "8.2.3", + "version": "8.2.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f67ca36860ebca7224d4573f107f79bd8ed0ba03" + "reference": "c1b8534b3730f20f58600124129197bf1183dc92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f67ca36860ebca7224d4573f107f79bd8ed0ba03", - "reference": "f67ca36860ebca7224d4573f107f79bd8ed0ba03", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1b8534b3730f20f58600124129197bf1183dc92", + "reference": "c1b8534b3730f20f58600124129197bf1183dc92", "shasum": "" }, "require": { @@ -4674,7 +5528,7 @@ "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.0", + "sebastian/type": "^1.1.3", "sebastian/version": "^2.0.1" }, "require-dev": { @@ -4717,7 +5571,7 @@ "testing", "xunit" ], - "time": "2019-06-19T12:03:56+00:00" + "time": "2019-07-15T06:26:24+00:00" }, { "name": "psr/cache", @@ -5470,53 +6324,6 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, - { - "name": "slam/php-cs-fixer-extensions", - "version": "v1.19.1", - "source": { - "type": "git", - "url": "https://github.com/Slamdunk/php-cs-fixer-extensions.git", - "reference": "ff457bef86539cb4ed7b7eb44eb85f3edddf53e1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Slamdunk/php-cs-fixer-extensions/zipball/ff457bef86539cb4ed7b7eb44eb85f3edddf53e1", - "reference": "ff457bef86539cb4ed7b7eb44eb85f3edddf53e1", - "shasum": "" - }, - "require": { - "friendsofphp/php-cs-fixer": "^2.15", - "php": "^7.2" - }, - "require-dev": { - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.5", - "roave/security-advisories": "dev-master", - "slam/php-debug-r": "^1.4", - "slam/phpstan-extensions": "^3.0", - "thecodingmachine/phpstan-strict-rules": "^0.11" - }, - "type": "library", - "autoload": { - "psr-4": { - "SlamCsFixer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Filippo Tessarotto", - "email": "zoeslam@gmail.com", - "role": "Developer" - } - ], - "description": "Slam extension of friendsofphp/php-cs-fixer", - "time": "2019-05-28T14:18:12+00:00" - }, { "name": "slevomat/coding-standard", "version": "5.0.4", @@ -5608,6 +6415,65 @@ ], "time": "2019-04-10T23:49:02+00:00" }, + { + "name": "symfony/browser-kit", + "version": "v4.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/dom-crawler": "~3.4|~4.0" + }, + "require-dev": { + "symfony/css-selector": "~3.4|~4.0", + "symfony/http-client": "^4.3", + "symfony/mime": "^4.3", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "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": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2019-06-11T15:41:59+00:00" + }, { "name": "symfony/cache", "version": "v4.3.2", @@ -5881,6 +6747,67 @@ "homepage": "https://symfony.com", "time": "2019-06-15T04:08:07+00:00" }, + { + "name": "symfony/dom-crawler", + "version": "v4.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "291397232a2eefb3347eaab9170409981eaad0e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/291397232a2eefb3347eaab9170409981eaad0e2", + "reference": "291397232a2eefb3347eaab9170409981eaad0e2", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "masterminds/html5": "<2.6" + }, + "require-dev": { + "masterminds/html5": "^2.6", + "symfony/css-selector": "~3.4|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2019-06-13T11:03:18+00:00" + }, { "name": "symfony/filesystem", "version": "v4.3.2", @@ -6213,82 +7140,39 @@ "homepage": "https://symfony.com", "time": "2019-04-06T14:04:46+00:00" }, - { - "name": "symplify/better-phpdoc-parser", - "version": "v5.4.16", - "source": { - "type": "git", - "url": "https://github.com/Symplify/BetterPhpDocParser.git", - "reference": "a730f69c4b19c741f13b4d05116da7bb64e3db26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Symplify/BetterPhpDocParser/zipball/a730f69c4b19c741f13b4d05116da7bb64e3db26", - "reference": "a730f69c4b19c741f13b4d05116da7bb64e3db26", - "shasum": "" - }, - "require": { - "nette/utils": "^2.5", - "php": "^7.1", - "phpstan/phpdoc-parser": "^0.3.1", - "symplify/package-builder": "^5.4.16" - }, - "require-dev": { - "phpunit/phpunit": "^7.5|^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.5-dev" - } - }, - "autoload": { - "psr-4": { - "Symplify\\BetterPhpDocParser\\": "src", - "Symplify\\BetterPhpDocParser\\Attributes\\": "packages/Attributes/src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slim wrapper around phpstan/phpdoc-parser with format preserving printer", - "time": "2019-03-05T23:15:04+00:00" - }, { "name": "symplify/coding-standard", - "version": "v5.4.16", + "version": "v6.0.4", "source": { "type": "git", "url": "https://github.com/Symplify/CodingStandard.git", - "reference": "72a3b03f21be6c978a90ad567a29bd9261df0dfa" + "reference": "adf215f9b2061859aa651dc9e6fd07ec3a3ffe9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Symplify/CodingStandard/zipball/72a3b03f21be6c978a90ad567a29bd9261df0dfa", - "reference": "72a3b03f21be6c978a90ad567a29bd9261df0dfa", + "url": "https://api.github.com/repos/Symplify/CodingStandard/zipball/adf215f9b2061859aa651dc9e6fd07ec3a3ffe9b", + "reference": "adf215f9b2061859aa651dc9e6fd07ec3a3ffe9b", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^2.14", + "friendsofphp/php-cs-fixer": "^2.15", "nette/finder": "^2.4", - "nette/utils": "^2.5", + "nette/utils": "^2.5|^3.0", "php": "^7.1", - "slam/php-cs-fixer-extensions": "^1.17", + "phpstan/phpdoc-parser": "^0.3.4", "squizlabs/php_codesniffer": "^3.4", - "symplify/better-phpdoc-parser": "^5.4.16", - "symplify/package-builder": "^5.4.16" + "symplify/package-builder": "^6.0.4" }, "require-dev": { - "nette/application": "^2.4", + "nette/application": "^2.4|^3.0", "phpunit/phpunit": "^7.5|^8.0", - "symplify/easy-coding-standard-tester": "^5.4.16", - "symplify/package-builder": "^5.4.16" + "symplify/easy-coding-standard-tester": "^6.0.4", + "symplify/package-builder": "^6.0.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -6302,45 +7186,46 @@ "MIT" ], "description": "Set of Symplify rules for PHP_CodeSniffer and PHP CS Fixer.", - "time": "2019-03-05T23:15:04+00:00" + "time": "2019-06-26T20:13:26+00:00" }, { "name": "symplify/easy-coding-standard", - "version": "v5.4.16", + "version": "v6.0.4", "source": { "type": "git", "url": "https://github.com/Symplify/EasyCodingStandard.git", - "reference": "66ed360e0b81881336c7339989dce3b0c14509e9" + "reference": "5fb76e1e4f756ba866e4d94b37c8681bdffadc04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Symplify/EasyCodingStandard/zipball/66ed360e0b81881336c7339989dce3b0c14509e9", - "reference": "66ed360e0b81881336c7339989dce3b0c14509e9", + "url": "https://api.github.com/repos/Symplify/EasyCodingStandard/zipball/5fb76e1e4f756ba866e4d94b37c8681bdffadc04", + "reference": "5fb76e1e4f756ba866e4d94b37c8681bdffadc04", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.3", - "friendsofphp/php-cs-fixer": "^2.14", + "friendsofphp/php-cs-fixer": "^2.15", "jean85/pretty-package-versions": "^1.2", "nette/robot-loader": "^3.1.0", - "nette/utils": "^2.5", + "nette/utils": "^2.5|^3.0", "ocramius/package-versions": "^1.3", "php": "^7.1", + "psr/simple-cache": "^1.0", "slevomat/coding-standard": "^5.0.1", "squizlabs/php_codesniffer": "^3.4", - "symfony/cache": "^3.4|^4.1", - "symfony/config": "^3.4|^4.1", - "symfony/console": "^3.4|^4.1", - "symfony/dependency-injection": "^3.4|^4.1", - "symfony/finder": "^3.4|^4.1", - "symfony/http-kernel": "^3.4|^4.1", - "symfony/yaml": "^3.4|^4.1", - "symplify/coding-standard": "^5.4.16", - "symplify/package-builder": "^5.4.16" + "symfony/cache": "^3.4|^4.2", + "symfony/config": "^3.4|^4.2", + "symfony/console": "^3.4|^4.2", + "symfony/dependency-injection": "^3.4.10|^4.2", + "symfony/finder": "^3.4|^4.2", + "symfony/http-kernel": "^3.4|^4.2", + "symfony/yaml": "^3.4|^4.2", + "symplify/coding-standard": "^6.0.4", + "symplify/package-builder": "^6.0.4" }, "require-dev": { "phpunit/phpunit": "^7.5|^8.0", - "symplify/easy-coding-standard-tester": "^5.4.16" + "symplify/easy-coding-standard-tester": "^6.0.4" }, "bin": [ "bin/ecs" @@ -6348,7 +7233,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -6365,34 +7250,33 @@ "MIT" ], "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.", - "time": "2019-03-05T23:15:04+00:00" + "time": "2019-06-26T20:13:26+00:00" }, { "name": "symplify/package-builder", - "version": "v5.4.16", + "version": "v6.0.4", "source": { "type": "git", "url": "https://github.com/Symplify/PackageBuilder.git", - "reference": "20e04ad9cd15a53527807a62c8b244d8a114f779" + "reference": "14db22e0c9667aeb81873468b4984a490d2183b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Symplify/PackageBuilder/zipball/20e04ad9cd15a53527807a62c8b244d8a114f779", - "reference": "20e04ad9cd15a53527807a62c8b244d8a114f779", + "url": "https://api.github.com/repos/Symplify/PackageBuilder/zipball/14db22e0c9667aeb81873468b4984a490d2183b6", + "reference": "14db22e0c9667aeb81873468b4984a490d2183b6", "shasum": "" }, "require": { - "illuminate/support": "^5.7", "nette/finder": "^2.4", - "nette/utils": "^2.5", + "nette/utils": "^2.5|^3.0", "php": "^7.1", - "symfony/config": "^3.4|^4.1", - "symfony/console": "^3.4|^4.1", - "symfony/debug": "^3.4|^4.1", - "symfony/dependency-injection": "^3.4|^4.1", - "symfony/finder": "^3.4|^4.1", - "symfony/http-kernel": "^3.4|^4.1", - "symfony/yaml": "^3.4|^4.1" + "symfony/config": "^3.4|^4.2", + "symfony/console": "^3.4|^4.2", + "symfony/debug": "^3.4|^4.2", + "symfony/dependency-injection": "^3.4.10|^4.2", + "symfony/finder": "^3.4|^4.2", + "symfony/http-kernel": "^3.4|^4.2", + "symfony/yaml": "^3.4|^4.2" }, "require-dev": { "phpunit/phpunit": "^7.5|^8.0" @@ -6400,7 +7284,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -6413,7 +7297,7 @@ "MIT" ], "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.", - "time": "2019-03-03T15:32:34+00:00" + "time": "2019-06-26T20:10:56+00:00" }, { "name": "theseer/tokenizer", @@ -6457,21 +7341,21 @@ }, { "name": "umbrellio/code-style-php", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/umbrellio/code-style-php.git", - "reference": "be917ff37bde26a32e66cb67a932acd659896106" + "reference": "13ddcdbfa0ec1e6e8527ccb860dec64c2b3cdc81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/umbrellio/code-style-php/zipball/be917ff37bde26a32e66cb67a932acd659896106", - "reference": "be917ff37bde26a32e66cb67a932acd659896106", + "url": "https://api.github.com/repos/umbrellio/code-style-php/zipball/13ddcdbfa0ec1e6e8527ccb860dec64c2b3cdc81", + "reference": "13ddcdbfa0ec1e6e8527ccb860dec64c2b3cdc81", "shasum": "" }, "require": { "php": "^7.2", - "symplify/easy-coding-standard": "^5.0" + "symplify/easy-coding-standard": "^6.0" }, "type": "library", "notification-url": "https://packagist.org/downloads/", @@ -6482,6 +7366,10 @@ { "name": "Vitaliy Lazeev", "email": "vetal@umbrellio.biz" + }, + { + "name": "Umbrellio", + "email": "oss@umbrellio.biz" } ], "description": "Umbrellio php code style.", @@ -6490,7 +7378,7 @@ "code-style", "umbrellio" ], - "time": "2019-05-25T17:13:53+00:00" + "time": "2019-07-22T14:36:34+00:00" }, { "name": "webmozart/assert", @@ -6550,7 +7438,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.1.3" + "php": "^7.2" }, "platform-dev": [] } diff --git a/ecs.yml b/ecs.yml index 768e555..69f949a 100644 --- a/ecs.yml +++ b/ecs.yml @@ -10,7 +10,3 @@ parameters: cache_directory: .ecs_cache exclude_files: - vendor/* - - skip: - Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff: - - src/Schema/Blueprint.php diff --git a/phpunit.travis.xml b/phpunit.travis.xml new file mode 100644 index 0000000..22ab00f --- /dev/null +++ b/phpunit.travis.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + ./tests + + + + + ./src + + ./src/.meta.php + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1dc3aef..1e2c087 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,19 +1,24 @@ - + stopOnFailure="true"> + + + + + + + + ./src ./src/.meta.php - ./src/Commands diff --git a/src/.meta.php b/src/.meta.php index 30942b0..49db8b7 100644 --- a/src/.meta.php +++ b/src/.meta.php @@ -16,11 +16,16 @@ * @method UniqueDefinition uniquePartial($columns, ?string $index = null, ?string $algorithm = null) * @method ViewDefinition createView(string $view, string $select, bool $materialize = false) * @method Fluent dropView(string $view) - * @method Fluent gin($columns, ?string $name = null) - * @method Fluent gist($columns, ?string $name = null) * @method ColumnDefinition numeric(string $column, ?int $precision = null, ?int $scale = null): */ class Blueprint { } + + /** + * @method ColumnDefinition using($expression) + */ + class ColumnDefinition + { + } } diff --git a/src/Extensions/AbstractComponent.php b/src/Extensions/AbstractComponent.php index 3eb63a7..b03f5a4 100644 --- a/src/Extensions/AbstractComponent.php +++ b/src/Extensions/AbstractComponent.php @@ -4,9 +4,6 @@ namespace Umbrellio\Postgres\Extensions; -/** - * @codeCoverageIgnore - */ abstract class AbstractComponent { final public function __construct() diff --git a/src/PostgresConnection.php b/src/PostgresConnection.php index d1818d1..64a0f49 100644 --- a/src/PostgresConnection.php +++ b/src/PostgresConnection.php @@ -4,12 +4,15 @@ namespace Umbrellio\Postgres; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Events; use Illuminate\Database\PostgresConnection as BasePostgresConnection; use Illuminate\Support\Traits\Macroable; use Umbrellio\Postgres\Extensions\AbstractExtension; use Umbrellio\Postgres\Extensions\Exceptions\ExtensionInvalidException; use Umbrellio\Postgres\Schema\Builder; use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar; +use Umbrellio\Postgres\Schema\Subscribers\SchemaAlterTableChangeColumnSubscriber; class PostgresConnection extends BasePostgresConnection { @@ -19,6 +22,7 @@ class PostgresConnection extends BasePostgresConnection /** * @param AbstractExtension|string $extension + * @throws ExtensionInvalidException * @codeCoverageIgnore */ final public static function registerExtension(string $extension): void @@ -41,12 +45,19 @@ public function getSchemaBuilder() return new Builder($this); } - public function useDefaultPostProcessor() + public function useDefaultPostProcessor(): void { parent::useDefaultPostProcessor(); $this->registerExtensions(); } + public function getDoctrineConnection(): Connection + { + $doctrineConnection = parent::getDoctrineConnection(); + $this->overrideDoctrineBehavior($doctrineConnection); + return $doctrineConnection; + } + protected function getDefaultSchemaGrammar() { return $this->withTablePrefix(new PostgresGrammar()); @@ -55,9 +66,9 @@ protected function getDefaultSchemaGrammar() /** * @codeCoverageIgnore */ - final private function registerExtensions(): void + private function registerExtensions(): void { - collect(self::$extensions)->each(function ($extension, $key) { + collect(self::$extensions)->each(function ($extension) { /** @var AbstractExtension $extension */ $extension::register(); foreach ($extension::getTypes() as $type => $typeClass) { @@ -65,4 +76,14 @@ final private function registerExtensions(): void } }); } + + private function overrideDoctrineBehavior(Connection $connection): Connection + { + $eventManager = $connection->getEventManager(); + if (!$eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) { + $eventManager->addEventSubscriber(new SchemaAlterTableChangeColumnSubscriber()); + } + $connection->getDatabasePlatform()->setEventManager($eventManager); + return $connection; + } } diff --git a/src/Schema/Blueprint.php b/src/Schema/Blueprint.php index 774a84a..38f7b22 100644 --- a/src/Schema/Blueprint.php +++ b/src/Schema/Blueprint.php @@ -59,26 +59,6 @@ public function uniquePartial($columns, ?string $index = null, ?string $algorith ); } - /** - * Specify an index for the table. - * @param string|array $columns - * @return Fluent - */ - public function gin($columns, ?string $name = null) - { - return $this->indexCommand('gin', $columns, $name); - } - - /** - * Specify a gist index for the table. - * @param string|array $columns - * @return Fluent - */ - public function gist($columns, ?string $name = null) - { - return $this->indexCommand('gist', $columns, $name); - } - public function hasIndex($index, bool $unique = false): bool { if (is_array($index)) { @@ -109,28 +89,6 @@ public function numeric(string $column, ?int $precision = null, ?int $scale = nu return $this->addColumn('numeric', $column, compact('precision', 'scale')); } - protected function addFluentIndexes(): void - { - foreach ($this->columns as $column) { - foreach (['primary', 'unique', 'index', 'gin', 'gist', 'spatialIndex'] as $index) { - // If the index has been specified on the given column, but is simply - // equal to "true" (boolean), no name has been specified for this - // index, so we will simply call the index methods without one. - if ($column->{$index} === true) { - $this->{$index}($column->name); - continue 2; - } - // If the index has been specified on the column and it is something - // other than boolean true, we will assume a name was provided on - // the index specification, and pass in the name to the method. - elseif (isset($column->{$index})) { - $this->{$index}($column->name, $column->{$index}); - continue 2; - } - } - } - } - protected function getSchemaManager() { return Schema::getConnection()->getDoctrineSchemaManager(); diff --git a/src/Schema/Grammars/PostgresGrammar.php b/src/Schema/Grammars/PostgresGrammar.php index 52f4ce4..59a5ff0 100644 --- a/src/Schema/Grammars/PostgresGrammar.php +++ b/src/Schema/Grammars/PostgresGrammar.php @@ -75,27 +75,6 @@ public function compileUniquePartial(Blueprint $blueprint, UniquePartialBuilder return $this->compileUnique($blueprint, $command); } - public function compileGin(Blueprint $blueprint, Fluent $command): string - { - return sprintf( - 'CREATE INDEX %s ON %s USING GIN(%s)', - $command->index, - $this->wrapTable($blueprint), - $this->columnize($command->columns) - ); - } - - - public function compileGist(Blueprint $blueprint, Fluent $command): string - { - return sprintf( - 'CREATE INDEX %s ON %s USING GIST(%s)', - $command->index, - $this->wrapTable($blueprint), - $this->columnize($command->columns) - ); - } - protected function typeNumeric(Fluent $column): string { $type = 'numeric'; diff --git a/src/Schema/Subscribers/SchemaAlterTableChangeColumnSubscriber.php b/src/Schema/Subscribers/SchemaAlterTableChangeColumnSubscriber.php new file mode 100644 index 0000000..d908cee --- /dev/null +++ b/src/Schema/Subscribers/SchemaAlterTableChangeColumnSubscriber.php @@ -0,0 +1,233 @@ +preventDefault(); + + $sql = $this->getAlterTableChangeColumnSQL( + $event->getPlatform(), + $event->getTableDiff(), + $event->getColumnDiff() + ); + + $event->addSql($sql->unique()->toArray()); + } + + public function getSubscribedEvents(): array + { + return [Events::onSchemaAlterTableChangeColumn]; + } + + public function getAlterTableChangeColumnSQL( + AbstractPlatform $platform, + TableDiff $diff, + ColumnDiff $columnDiff + ): Collection { + $sql = new Collection(); + + $quoteName = $this->quoteName($platform, $diff); + + $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($platform); + $column = $columnDiff->column; + + $this->compileAlterColumnType($platform, $columnDiff, $column, $quoteName, $oldColumnName, $sql); + + $this->compileAlterColumnDefault($platform, $columnDiff, $column, $quoteName, $oldColumnName, $sql); + + $this->compileAlterColumnNull($columnDiff, $column, $quoteName, $oldColumnName, $sql); + + $this->compileAlterColumnSequence($platform, $columnDiff, $diff, $column, $quoteName, $oldColumnName, $sql); + + $this->compileAlterColumnComment($platform, $columnDiff, $column, $quoteName, $sql); + + if (!$columnDiff->hasChanged('length')) { + return $sql; + } + + $sql->add(sprintf( + 'ALTER TABLE %s ALTER %s TYPE %s', + $quoteName, + $oldColumnName, + $column->getType()->getSQLDeclaration($column->toArray(), $platform) + )); + + return $sql; + } + + public function compileAlterColumnComment( + AbstractPlatform $platform, + ColumnDiff $columnDiff, + Column $column, + string $quoteName, + Collection $sql + ): void { + $newComment = $this->getColumnComment($column); + $oldComment = $this->getOldColumnComment($columnDiff); + + if (($columnDiff->fromColumn !== null && $oldComment !== $newComment) + || $columnDiff->hasChanged('comment') + ) { + $sql->add($platform->getCommentOnColumnSQL($quoteName, $column->getQuotedName($platform), $newComment)); + } + } + + public function compileAlterColumnNull( + ColumnDiff $columnDiff, + Column $column, + string $quoteName, + string $oldColumnName, + Collection $sql + ): void { + if ($columnDiff->hasChanged('notnull')) { + $sql->add(sprintf( + 'ALTER TABLE %s ALTER %s %s NOT NULL', + $quoteName, + $oldColumnName, + ($column->getNotnull() ? 'SET' : 'DROP') + )); + } + } + + public function compileAlterColumnDefault( + AbstractPlatform $platform, + ColumnDiff $columnDiff, + Column $column, + string $quoteName, + string $oldColumnName, + Collection $sql + ): void { + if ($columnDiff->hasChanged('default') || $this->typeChangeBreaksDefaultValue($columnDiff)) { + $defaultClause = $column->getDefault() === null + ? ' DROP DEFAULT' + : ' SET' . $this->getDefaultValueDeclarationSQL($platform, $column); + $sql->add(sprintf('ALTER TABLE %s ALTER %s %s', $quoteName, $oldColumnName, trim($defaultClause))); + } + } + + public function compileAlterColumnSequence( + AbstractPlatform $platform, + ColumnDiff $columnDiff, + TableDiff $diff, + Column $column, + string $quoteName, + string $oldColumnName, + Collection $sql + ): void { + if (!$columnDiff->hasChanged('autoincrement')) { + return; + } + + if (!$column->getAutoincrement()) { + $sql->add(sprintf('ALTER TABLE %s ALTER %s DROP DEFAULT', $quoteName, $oldColumnName)); + return; + } + + $seqName = $platform->getIdentitySequenceName($diff->name, $oldColumnName); + + $sql->add(sprintf('CREATE SEQUENCE %s', $seqName)); + $sql->add(sprintf("SELECT setval('%s', (SELECT MAX(%s) FROM %s))", $seqName, $oldColumnName, $quoteName)); + $sql->add(sprintf("ALTER TABLE %s ALTER %s SET DEFAULT nextval('%s')", $quoteName, $oldColumnName, $seqName)); + } + + public function compileAlterColumnType( + AbstractPlatform $platform, + ColumnDiff $columnDiff, + Column $column, + string $quoteName, + string $oldColumnName, + Collection $sql + ): void { + if (!$columnDiff->hasChanged('type') + && !$columnDiff->hasChanged('precision') + && !$columnDiff->hasChanged('scale') + && !$columnDiff->hasChanged('fixed') + ) { + return; + } + + $type = $column->getType(); + + $columnDefinition = $column->toArray(); + $columnDefinition['autoincrement'] = false; + + if ($this->typeChangeBreaksDefaultValue($columnDiff)) { + $sql->add(sprintf('ALTER TABLE %s ALTER %s DROP DEFAULT', $quoteName, $oldColumnName)); + } + + $typeName = $type->getSQLDeclaration($columnDefinition, $platform); + + if ($columnDiff->hasChanged('type')) { + $using = sprintf('USING %s::%s', $oldColumnName, $typeName); + + if ($columnDefinition['using'] ?? false) { + $using = 'USING ' . $columnDefinition['using']; + } + } + + $sql->add(trim(sprintf( + 'ALTER TABLE %s ALTER %s TYPE %s %s', + $quoteName, + $oldColumnName, + $typeName, + $using ?? '' + ))); + } + + public function getDefaultValueDeclarationSQL(AbstractPlatform $platform, Column $column): string + { + if ($column->getDefault() instanceof Expression) { + return ' DEFAULT ' . $column->getDefault(); + } + + return $platform->getDefaultValueDeclarationSQL($column->toArray()); + } + + public function typeChangeBreaksDefaultValue(ColumnDiff $columnDiff): bool + { + $oldTypeIsNumeric = $this->isNumericType($columnDiff->fromColumn->getType()); + $newTypeIsNumeric = $this->isNumericType($columnDiff->column->getType()); + + $isNumeric = !($oldTypeIsNumeric && $newTypeIsNumeric && $columnDiff->column->getAutoincrement()); + + return $columnDiff->hasChanged('type') && $isNumeric; + } + + public function isNumericType(Type $type): bool + { + return $type instanceof IntegerType || $type instanceof BigIntType; + } + + public function quoteName(AbstractPlatform $platform, TableDiff $diff): string + { + return $diff->getName($platform)->getQuotedName($platform); + } + + public function getOldColumnComment(ColumnDiff $columnDiff): ?string + { + return $columnDiff->fromColumn ? $this->getColumnComment($columnDiff->fromColumn) : null; + } + + public function getColumnComment(Column $column): ?string + { + return $column->getComment(); + } +} diff --git a/tests.sh b/tests.sh new file mode 100755 index 0000000..c4ce18c --- /dev/null +++ b/tests.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +psql postgres -U user -tc "SELECT 1 FROM pg_database WHERE datname = 'testing'" | grep -q 1 || psql postgres -U user -c "CREATE DATABASE testing" +composer lint +php -d pcov.directory='.' vendor/bin/phpunit --coverage-html build diff --git a/tests/Functional/FunctionalTestCase.php b/tests/Functional/FunctionalTestCase.php deleted file mode 100644 index af522b6..0000000 --- a/tests/Functional/FunctionalTestCase.php +++ /dev/null @@ -1,31 +0,0 @@ -set('database.default', 'testing'); - $app['config']->set('database.connections.testing', [ - 'driver' => 'pgsql', - 'host' => env('TEST_DB_HOST', 'localhost'), - 'port' => env('TEST_DB_PORT', 5432), - 'database' => env('TEST_DB', 'testing'), - 'username' => env('TEST_DB_USER', 'postgres'), - 'password' => env('TEST_DB_PASSWORD', ''), - 'charset' => 'utf8', - 'prefix' => '', - 'schema' => 'public', - ]); - } -} diff --git a/tests/Functional/HasIndexTest.php b/tests/Functional/HasIndexTest.php deleted file mode 100644 index 811ef37..0000000 --- a/tests/Functional/HasIndexTest.php +++ /dev/null @@ -1,42 +0,0 @@ -increments('id'); - $table->string('name'); - - if (!$table->hasIndex(['name'], true)) { - $table->unique(['name']); - } - }); - - $this->assertTrue(Schema::hasTable('test_table')); - - $indexes = $this->getIndexByName('test_table_name_unique'); - - Schema::table('test_table', function (Blueprint $table) { - if (!$table->hasIndex(['name'], true)) { - $table->unique(['name']); - } - }); - - $this->assertTrue(isset($indexes->indexdef)); - } - - protected function getIndexByName($name) - { - return collect(DB::select("SELECT indexdef FROM pg_indexes WHERE indexname = '{$name}'"))->first(); - } -} diff --git a/tests/Functional/Helpers/ColumnAssertions.php b/tests/Functional/Helpers/ColumnAssertions.php new file mode 100644 index 0000000..dc7e68a --- /dev/null +++ b/tests/Functional/Helpers/ColumnAssertions.php @@ -0,0 +1,72 @@ +getCommentListing($table, $column); + + if ($expected === null) { + $this->assertNull($comment); + } + + $this->assertSame($expected, $comment); + } + + protected function assertDefaultOnColumn(string $table, string $column, ?string $expected = null): void + { + $defaultValue = $this->getDefaultListing($table, $column); + + if ($expected === null) { + $this->assertNull($defaultValue); + } + + $this->assertSame($expected, $defaultValue); + } + + protected function assertTypeColumn(string $table, string $column, string $expected): void + { + $this->assertSame($expected, Schema::getColumnType($table, $column)); + } + private function getCommentListing(string $table, string $column) + { + $definition = DB::selectOne( + ' + SELECT pgd.description + FROM pg_catalog.pg_statio_all_tables AS st + INNER JOIN pg_catalog.pg_description pgd ON (pgd.objoid = st.relid) + INNER JOIN information_schema.columns c ON pgd.objsubid = c.ordinal_position + AND c.table_schema = st.schemaname AND c.table_name = st.relname + WHERE c.table_name = ? AND c.column_name = ? + ', + [$table, $column] + ); + + return $definition ? $definition->description : null; + } + + private function getDefaultListing(string $table, string $column) + { + $definition = DB::selectOne( + ' + SELECT column_default + FROM information_schema.columns c + WHERE c.table_name = ? and c.column_name = ? + ', + [$table, $column] + ); + + return $definition ? $definition->column_default : null; + } +} diff --git a/tests/Functional/Helpers/IndexAssertions.php b/tests/Functional/Helpers/IndexAssertions.php new file mode 100644 index 0000000..07d23d0 --- /dev/null +++ b/tests/Functional/Helpers/IndexAssertions.php @@ -0,0 +1,41 @@ +assertNotNull($this->getIndexListing($index)); + } + + protected function assertSameIndex(string $index, string $expectedDef): void + { + $definition = $this->getIndexListing($index); + + $this->seeIndex($index); + $this->assertSame($expectedDef, $definition); + } + + protected function assertRegExpIndex(string $index, string $expectedDef): void + { + $definition = $this->getIndexListing($index); + + $this->seeIndex($index); + $this->assertRegExp($expectedDef, $definition); + } + private function getIndexListing($index): ?string + { + $definition = DB::selectOne('SELECT indexdef FROM pg_indexes WHERE indexname = ?', [$index]); + + return $definition ? $definition->indexdef : null; + } +} diff --git a/tests/Functional/Helpers/TableAssertions.php b/tests/Functional/Helpers/TableAssertions.php new file mode 100644 index 0000000..c3a2c90 --- /dev/null +++ b/tests/Functional/Helpers/TableAssertions.php @@ -0,0 +1,36 @@ +assertSame($this->getTableDefinition($sourceTable), $this->getTableDefinition($destinationTable)); + } + + protected function assertSameTable(array $expectedDef, string $table): void + { + $definition = $this->getTableDefinition($table); + + $this->assertSame($expectedDef, $definition); + } + + protected function seeTable(string $table): void + { + $this->assertTrue(Schema::hasTable($table)); + } + + private function getTableDefinition(string $table): array + { + return Schema::getColumnListing($table); + } +} diff --git a/tests/Functional/Helpers/ViewAssertions.php b/tests/Functional/Helpers/ViewAssertions.php new file mode 100644 index 0000000..ea0c2d3 --- /dev/null +++ b/tests/Functional/Helpers/ViewAssertions.php @@ -0,0 +1,40 @@ +getViewDefinition($view); + + $this->assertSame($expectedDef, $definition); + } + + protected function seeView(string $view): void + { + $this->assertTrue(Schema::hasView($view)); + } + + protected function notSeeView(string $view): void + { + $this->assertFalse(Schema::hasView($view)); + } + + private function getViewDefinition(string $view): string + { + return preg_replace( + "#\s+#", + ' ', + strtolower(trim(str_replace("\n", ' ', Schema::getViewDefinition($view)))) + ); + } +} diff --git a/tests/Functional/UniqueIndexTest.php b/tests/Functional/Schema/CreateIndexTest.php similarity index 59% rename from tests/Functional/UniqueIndexTest.php rename to tests/Functional/Schema/CreateIndexTest.php index 8de9265..fac3a8f 100644 --- a/tests/Functional/UniqueIndexTest.php +++ b/tests/Functional/Schema/CreateIndexTest.php @@ -2,20 +2,48 @@ declare(strict_types=1); -namespace Umbrellio\Postgres\Tests\Functional; +namespace Umbrellio\Postgres\Tests\Functional\Schema; +use Closure; use Generator; -use Illuminate\Support\Facades\DB; +use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Schema; use Umbrellio\Postgres\Schema\Blueprint; +use Umbrellio\Postgres\Tests\Functional\Helpers\IndexAssertions; +use Umbrellio\Postgres\Tests\FunctionalTestCase; -class UniqueIndexTest extends FunctionalTestCase +class CreateIndexTest extends FunctionalTestCase { + use DatabaseTransactions, IndexAssertions; + + /** @test */ + public function createIndexIfNotExists(): void + { + Schema::create('test_table', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + + if (!$table->hasIndex(['name'], true)) { + $table->unique(['name']); + } + }); + + $this->assertTrue(Schema::hasTable('test_table')); + + Schema::table('test_table', function (Blueprint $table) { + if (!$table->hasIndex(['name'], true)) { + $table->unique(['name']); + } + }); + + $this->seeIndex('test_table_name_unique'); + } + /** * @test * @dataProvider provideIndexes */ - public function createPartialUniqueWithNull($expected, $callback): void + public function createPartialUniqueWithNull(string $expected, Closure $callback): void { Schema::create('test_table', function (Blueprint $table) use ($callback) { $table->increments('id'); @@ -25,15 +53,12 @@ public function createPartialUniqueWithNull($expected, $callback): void $table->boolean('enabled'); $table->integer('icq'); $table->softDeletes(); + $callback($table); }); $this->assertTrue(Schema::hasTable('test_table')); - - $indexes = $this->getIndexByName('test_table_name_unique'); - - $this->assertTrue(isset($indexes->indexdef)); - $this->assertSame($this->getDummyIndex() . $expected, $indexes->indexdef); + $this->assertRegExpIndex('test_table_name_unique', '/' . $this->getDummyIndex() . $expected . '/'); } /** @test */ @@ -45,9 +70,9 @@ public function createSpecifyIndex(): void $this->assertTrue(Schema::hasTable('test_table')); - $this->assertSame( - 'CREATE INDEX specify_index_name ON public.test_table USING btree (name)', - $this->getIndexByName('specify_index_name')->indexdef + $this->assertRegExpIndex( + 'specify_index_name', + '/CREATE INDEX specify_index_name ON (public.)?test_table USING btree \(name\)/' ); } @@ -57,86 +82,81 @@ public function provideIndexes(): Generator $table->uniquePartial('name'); }]; yield [ - ' WHERE (deleted_at IS NULL)', + ' WHERE \(deleted_at IS NULL\)', function (Blueprint $table) { $table->uniquePartial('name')->whereNull('deleted_at'); }, ]; yield [ - ' WHERE (deleted_at IS NOT NULL)', + ' WHERE \(deleted_at IS NOT NULL\)', function (Blueprint $table) { $table->uniquePartial('name')->whereNotNull('deleted_at'); }, ]; yield [ - ' WHERE (phone = 1234)', + ' WHERE \(phone = 1234\)', function (Blueprint $table) { $table->uniquePartial('name')->where('phone', '=', 1234); }, ]; yield [ - " WHERE ((code)::text = 'test'::text)", + " WHERE \(\(code\)::text = 'test'::text\)", function (Blueprint $table) { $table->uniquePartial('name')->where('code', '=', 'test'); }, ]; yield [ - ' WHERE ((phone >= 1) AND (phone <= 2))', + ' WHERE \(\(phone >= 1\) AND \(phone <= 2\)\)', function (Blueprint $table) { $table->uniquePartial('name')->whereBetween('phone', [1, 2]); }, ]; yield [ - ' WHERE ((phone < 1) OR (phone > 2))', + ' WHERE \(\(phone < 1\) OR \(phone > 2\)\)', function (Blueprint $table) { $table->uniquePartial('name')->whereNotBetween('phone', [1, 2]); }, ]; yield [ - ' WHERE (phone <> icq)', + ' WHERE \(phone <> icq\)', function (Blueprint $table) { $table->uniquePartial('name')->whereColumn('phone', '<>', 'icq'); }, ]; yield [ - ' WHERE ((phone = 1) AND (icq < 2))', + ' WHERE \(\(phone = 1\) AND \(icq < 2\)\)', function (Blueprint $table) { $table->uniquePartial('name')->whereRaw('phone = ? and icq < ?', [1, 2]); }, ]; yield [ - ' WHERE (phone = ANY (ARRAY[1, 2, 4]))', + ' WHERE \(phone = ANY \(ARRAY\[1, 2, 4\]\)\)', function (Blueprint $table) { $table->uniquePartial('name')->whereIn('phone', [1, 2, 4]); }, ]; yield [ - ' WHERE (0 = 1)', + ' WHERE \(0 = 1\)', function (Blueprint $table) { $table->uniquePartial('name')->whereIn('phone', []); }, ]; yield [ - ' WHERE (phone <> ALL (ARRAY[1, 2, 4]))', + ' WHERE \(phone <> ALL \(ARRAY\[1, 2, 4\]\)\)', function (Blueprint $table) { $table->uniquePartial('name')->whereNotIn('phone', [1, 2, 4]); }, ]; yield [ - ' WHERE (1 = 1)', + ' WHERE \(1 = 1\)', function (Blueprint $table) { $table->uniquePartial('name')->whereNotIn('phone', []); }, ]; } - protected function getDummyIndex() - { - return 'CREATE UNIQUE INDEX test_table_name_unique ON public.test_table USING btree (name)'; - } - - protected function getIndexByName($name) + protected function getDummyIndex(): string { - return collect(DB::select("SELECT indexdef FROM pg_indexes WHERE indexname = '{$name}'"))->first(); + return 'CREATE UNIQUE INDEX test_table_name_unique ON (public.)?test_table USING btree \(name\)'; } } diff --git a/tests/Functional/SchemaTest.php b/tests/Functional/Schema/CreateTableTest.php similarity index 53% rename from tests/Functional/SchemaTest.php rename to tests/Functional/Schema/CreateTableTest.php index 3e9f825..ce234a0 100644 --- a/tests/Functional/SchemaTest.php +++ b/tests/Functional/Schema/CreateTableTest.php @@ -2,27 +2,32 @@ declare(strict_types=1); -namespace Umbrellio\Postgres\Tests\Functional; +namespace Umbrellio\Postgres\Tests\Functional\Schema; +use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Schema; use Umbrellio\Postgres\Schema\Blueprint; +use Umbrellio\Postgres\Tests\Functional\Helpers\TableAssertions; +use Umbrellio\Postgres\Tests\FunctionalTestCase; -class SchemaTest extends FunctionalTestCase +class CreateTableTest extends FunctionalTestCase { + use DatabaseTransactions, TableAssertions; + /** @test */ - public function create(): void + public function createSimple(): void { Schema::create('test_table', function (Blueprint $table) { $table->increments('id'); $table->string('name'); }); - $this->assertTrue(Schema::hasTable('test_table')); - $this->assertSame(['id', 'name'], Schema::getColumnListing('test_table')); + $this->seeTable('test_table'); + $this->assertSameTable(['id', 'name'], 'test_table'); } /** @test */ - public function createLikeSimple(): void + public function createViaLike(): void { Schema::create('test_table', function (Blueprint $table) { $table->increments('id'); @@ -33,14 +38,13 @@ public function createLikeSimple(): void $table->like('test_table'); }); - $this->assertTrue(Schema::hasTable('test_table')); - $this->assertTrue(Schema::hasTable('test_table2')); - - $this->assertSame(Schema::getColumnListing('test_table'), Schema::getColumnListing('test_table2')); + $this->seeTable('test_table'); + $this->seeTable('test_table2'); + $this->assertCompareTables('test_table', 'test_table2'); } /** @test */ - public function createLikeFull(): void + public function createViaLikeIncludingAll(): void { Schema::create('test_table', function (Blueprint $table) { $table->increments('id'); @@ -52,8 +56,8 @@ public function createLikeFull(): void $table->ifNotExists(); }); - $this->assertTrue(Schema::hasTable('test_table')); - $this->assertTrue(Schema::hasTable('test_table2')); - $this->assertSame(Schema::getColumnListing('test_table'), Schema::getColumnListing('test_table2')); + $this->seeTable('test_table'); + $this->seeTable('test_table2'); + $this->assertCompareTables('test_table', 'test_table2'); } } diff --git a/tests/Functional/ViewTest.php b/tests/Functional/Schema/CreateViewTest.php similarity index 51% rename from tests/Functional/ViewTest.php rename to tests/Functional/Schema/CreateViewTest.php index 755255e..a683af8 100644 --- a/tests/Functional/ViewTest.php +++ b/tests/Functional/Schema/CreateViewTest.php @@ -4,11 +4,16 @@ namespace Umbrellio\Postgres\Tests\Functional; +use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Schema; use Umbrellio\Postgres\Schema\Blueprint; +use Umbrellio\Postgres\Tests\Functional\Helpers\ViewAssertions; +use Umbrellio\Postgres\Tests\FunctionalTestCase; -class ViewTest extends FunctionalTestCase +class CreateViewTest extends FunctionalTestCase { + use DatabaseTransactions, ViewAssertions; + protected function setUp(): void { parent::setUp(); @@ -29,35 +34,33 @@ public function createFacadeView(): void { Schema::createView('test_view', 'select * from test_table where name is not null'); - $this->assertSame( - strtolower( - 'select test_table.id, test_table.name from test_table where (test_table.name is not null);' - ), - trim(strtolower(str_replace("\n", ' ', Schema::getViewDefinition('test_view')))) + $this->seeView('test_view'); + $this->assertSameView( + 'select test_table.id, test_table.name from test_table where (test_table.name is not null);', + 'test_view' ); Schema::dropView('test_view'); - $this->assertFalse(Schema::hasView('test_view')); + $this->notSeeView('test_view'); } /** @test */ public function createBlueprintView(): void { - Schema::create('users', function (Blueprint $table) { - $table->increments('id'); - $table->string('name'); - $table->createView('test_view', 'select * from users where name is not null'); + Schema::table('test_table', function (Blueprint $table) { + $table->createView('test_view', 'select * from test_table where name is not null'); }); - $this->assertSame( - strtolower('select users.id, users.name from users where (users.name is not null);'), - trim(strtolower(str_replace("\n", ' ', Schema::getViewDefinition('test_view')))) + $this->seeView('test_view'); + $this->assertSameView( + 'select test_table.id, test_table.name from test_table where (test_table.name is not null);', + 'test_view' ); Schema::table('users', function (Blueprint $table) { $table->dropView('test_view'); }); - $this->assertFalse(Schema::hasView('test_view')); + $this->notSeeView('test_view'); } } diff --git a/tests/Functional/Subscribers/ChangeColumnSubscriberTest.php b/tests/Functional/Subscribers/ChangeColumnSubscriberTest.php new file mode 100644 index 0000000..6a10072 --- /dev/null +++ b/tests/Functional/Subscribers/ChangeColumnSubscriberTest.php @@ -0,0 +1,346 @@ +blueprint = new Blueprint('some_table'); + $this->postgresGrammar = new PostgresGrammar(); + $this->subscriber = new SchemaAlterTableChangeColumnSubscriber(); + $this->platform = new PostgreSqlPlatform(); + } + + /** @test */ + public function getSubscriberEvents(): void + { + $this->assertSame([Events::onSchemaAlterTableChangeColumn], $this->subscriber->getSubscribedEvents()); + } + + /** + * @test + * @dataProvider provideSchemas + */ + public function changeSchema(string $column, Closure $callback, array $expectedSQL): void + { + $callback($this->blueprint, $column); + $eventArgs = $this->getEventArgsForColumn($column); + $this->subscriber->onSchemaAlterTableChangeColumn($eventArgs); + + $this->assertSame($expectedSQL, $eventArgs->getSql()); + } + + public function provideSchemas(): Generator + { + yield $this->dropCommentCase(); + yield $this->changeCommentCase(); + yield $this->dropNotNullCase(); + yield $this->createSequenceCase(); + yield $this->dropDefaultCase(); + yield $this->setSimpleDefaultCase(); + yield $this->setExpressionDefaultCase(); + yield $this->changeTypeWithUsingCase(); + yield $this->changeLengthCase(); + } + + private function getEventArgsForColumn(string $columnName): SchemaAlterTableChangeColumnEventArgs + { + /** @var PostgresConnection $connection */ + $connection = DB::connection(); + $schemaManager = $connection->getDoctrineSchemaManager(); + + $this->columns = []; + foreach ($this->getListColumns() as $listColumn) { + $this->columns[] = ReflectionHelper::invokePrivateMethod( + $schemaManager, + '_getPortableTableColumnDefinition', + ['tableName' => $listColumn] + ); + } + + $this->table = new Table('some_table', $this->columns); + + $this->tableDiff = (new Comparator())->diffTable( + $this->table, + $this + ->getStaticMethod(ChangeColumn::class, 'getTableWithColumnChanges') + ->invoke(null, $this->blueprint, $this->table) + ); + + foreach ($this->tableDiff->changedColumns as $columnDiff) { + if ($columnDiff->oldColumnName !== $columnName) { + continue; + } + $this->columnDiff = $columnDiff; + } + + return new SchemaAlterTableChangeColumnEventArgs($this->columnDiff, $this->tableDiff, $this->platform); + } + + private function dropCommentCase(): array + { + return [ + 'some_comment', + function (Blueprint $table, string $column) { + $table->string($column)->nullable(false)->change(); + }, + ['ALTER TABLE some_table ALTER some_comment SET NOT NULL'], + ]; + } + + private function changeCommentCase(): array + { + return [ + 'some_comment', + function (Blueprint $table, string $column) { + $table->string($column) + ->comment('new_comment') + ->change(); + }, + ["COMMENT ON COLUMN some_table.some_comment IS 'new_comment'"], + ]; + } + + private function dropNotNullCase(): array + { + return [ + 'some_integer_default', + function (Blueprint $table, string $column) { + $table->integer($column)->nullable()->change(); + }, + ['ALTER TABLE some_table ALTER some_integer_default DROP NOT NULL'], + ]; + } + + private function createSequenceCase(): array + { + return [ + 'some_integer_default', + function (Blueprint $table, string $column) { + $table->increments($column)->change(); + }, + [ + 'CREATE SEQUENCE some_table_some_integer_default_seq', + "SELECT setval('some_table_some_integer_default_seq', (SELECT MAX(some_integer_default) FROM some_table))", + "ALTER TABLE some_table ALTER some_integer_default SET DEFAULT nextval('some_table_some_integer_default_seq')", + ], + ]; + } + + private function dropDefaultCase(): array + { + return [ + 'some_key', + function (Blueprint $table, string $column) { + $table->integer($column)->change(); + }, + [ + 'ALTER TABLE some_table ALTER some_key DROP DEFAULT', + 'ALTER TABLE some_table ALTER some_key TYPE INT USING some_key::INT', + ], + ]; + } + + private function setSimpleDefaultCase(): array + { + return [ + 'some_comment', + function (Blueprint $table, string $column) { + $table->string($column)->default('some_default')->change(); + }, + ["ALTER TABLE some_table ALTER some_comment SET DEFAULT 'some_default'"], + ]; + } + + private function setExpressionDefaultCase(): array + { + return [ + 'some_comment', + function (Blueprint $table, string $column) { + $table->string($column)->default( + new Expression("('some_string:' || some_comment)::character varying") + )->change(); + }, + [ + "ALTER TABLE some_table ALTER some_comment SET DEFAULT ('some_string:' || some_comment)::character varying", + ], + ]; + } + + private function changeTypeWithUsingCase(): array + { + return [ + 'some_integer_default', + function (Blueprint $table, string $column) { + $table + ->text($column) + ->default(null) + ->using(sprintf("('[some_exp:' || %s || ']')::character varying", $column)) + ->change(); + }, + [ + 'ALTER TABLE some_table ALTER some_integer_default DROP DEFAULT', + "ALTER TABLE some_table ALTER some_integer_default TYPE TEXT USING ('[some_exp:' || some_integer_default || ']')::character varying", + ], + ]; + } + + private function changeLengthCase(): array + { + return [ + 'some_comment', + function (Blueprint $table, string $column) { + $table->string($column, 75)->change(); + }, + ['ALTER TABLE some_table ALTER some_comment TYPE VARCHAR(75)'], + ]; + } + + private function getListColumns(): array + { + return [ + $this->getDefinitionSomeKeySequence(), + $this->getDefinitionSomeString(), + $this->getDefinitionSomeStringDefault(), + $this->getDefinitionSomeIntegerDefault(), + $this->getDefinitionSomeComment(), + ]; + } + + private function getStaticMethod($class, $method): ReflectionMethod + { + $method = new ReflectionMethod($class, $method); + $method->setAccessible(true); + + return $method; + } + + private function getDefinitionSomeKeySequence(): array + { + return [ + 'attnum' => 1, + 'field' => 'some_key', + 'type' => 'int8', + 'complete_type' => 'bigint', + 'domain_type' => null, + 'domain_complete_type' => null, + 'isnotnull' => true, + 'pri' => 't', + 'default' => "nextval('some_table_some_key_seq'::regclass)", + 'comment' => null, + ]; + } + + private function getDefinitionSomeString(): array + { + return [ + 'attnum' => 2, + 'field' => 'some_string', + 'type' => 'varchar', + 'complete_type' => 'character varying', + 'domain_type' => null, + 'domain_complete_type' => null, + 'isnotnull' => false, + 'pri' => null, + 'default' => null, + 'comment' => null, + ]; + } + + private function getDefinitionSomeStringDefault(): array + { + return [ + 'attnum' => 3, + 'field' => 'some_string_default', + 'type' => 'varchar', + 'complete_type' => 'character varying', + 'domain_type' => null, + 'domain_complete_type' => null, + 'isnotnull' => true, + 'pri' => null, + 'default' => "'some_default_value'::character varying", + 'comment' => null, + ]; + } + + private function getDefinitionSomeIntegerDefault(): array + { + return [ + 'attnum' => 4, + 'field' => 'some_integer_default', + 'type' => 'int4', + 'complete_type' => 'integer', + 'domain_type' => null, + 'domain_complete_type' => null, + 'isnotnull' => true, + 'pri' => null, + 'default' => 1, + 'comment' => null, + ]; + } + + private function getDefinitionSomeComment(): array + { + return [ + 'attnum' => 5, + 'field' => 'some_comment', + 'type' => 'varchar', + 'complete_type' => 'character varying', + 'domain_type' => null, + 'domain_complete_type' => null, + 'isnotnull' => false, + 'pri' => null, + 'default' => null, + 'comment' => 'some_comment_value', + ]; + } +} diff --git a/tests/FunctionalTestCase.php b/tests/FunctionalTestCase.php new file mode 100644 index 0000000..ecf2691 --- /dev/null +++ b/tests/FunctionalTestCase.php @@ -0,0 +1,49 @@ +getConnectionParams(); + + $app['config']->set('database.default', 'main'); + $app['config']->set('database.connections.main', [ + 'driver' => 'pgsql', + 'host' => $params['host'], + 'port' => (int) $params['port'], + 'database' => $params['database'], + 'username' => $params['user'], + 'password' => $params['password'], + 'charset' => 'utf8', + 'prefix' => '', + 'schema' => 'public', + ]); + } + + private function getConnectionParams(): array + { + return [ + 'driver' => $GLOBALS['db_type'] ?? 'pdo_pgsql', + 'user' => $GLOBALS['db_username'], + 'password' => $GLOBALS['db_password'], + 'host' => $GLOBALS['db_host'], + 'database' => $GLOBALS['db_database'], + 'port' => $GLOBALS['db_port'], + ]; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 2467719..67c8ab0 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,7 +9,7 @@ abstract class TestCase extends BaseTestCase { - protected function getPackageProviders($app) + protected function getPackageProviders($app): array { return [UmbrellioPostgresProvider::class]; } diff --git a/tests/Unit/Extensions/AbstractExtensionTest.php b/tests/Unit/Extensions/AbstractExtensionTest.php new file mode 100644 index 0000000..24c1ee9 --- /dev/null +++ b/tests/Unit/Extensions/AbstractExtensionTest.php @@ -0,0 +1,65 @@ + new class() extends Model { + }, + ]; + } + }; + + $this->expectException(MixinInvalidException::class); + + /** @var AbstractExtension $abstractExtension */ + $abstractExtension::register(); + } + + /** @test */ + public function registerWithInvalidMixin(): void + { + $abstractExtension = new class() extends AbstractExtension { + public static function getName(): string + { + return 'extension'; + } + + public static function getMixins(): array + { + return [ + ServiceProvider::class => new class() extends AbstractComponent { + }, + ]; + } + }; + + $this->expectException(MacroableMissedException::class); + + /** @var AbstractExtension $abstractExtension */ + $abstractExtension::register(); + } +} diff --git a/tests/Unit/Helpers/BlueprintAssertions.php b/tests/Unit/Helpers/BlueprintAssertions.php new file mode 100644 index 0000000..be7de4b --- /dev/null +++ b/tests/Unit/Helpers/BlueprintAssertions.php @@ -0,0 +1,51 @@ +blueprint = new Blueprint($table); + $this->postgresConnection = $this->createMock(PostgresConnection::class); + $this->postgresGrammar = new PostgresGrammar(); + } + + /** + * @param string|array $sql + */ + protected function assertSameSql($sql): void + { + $this->assertSame((array) $sql, $this->runToSql()); + } + + protected function assertRegExpSql(string $regexpExpected): void + { + foreach ($this->runToSql() as $sql) { + $this->assertRegExp($regexpExpected, $sql); + } + } + + private function runToSql(): array + { + return $this->blueprint->toSql($this->postgresConnection, $this->postgresGrammar); + } +} diff --git a/tests/Unit/Schema/BlueprintTest.php b/tests/Unit/Schema/Blueprint/PartitionTest.php similarity index 73% rename from tests/Unit/Schema/BlueprintTest.php rename to tests/Unit/Schema/Blueprint/PartitionTest.php index 8c76c0f..8556790 100644 --- a/tests/Unit/Schema/BlueprintTest.php +++ b/tests/Unit/Schema/Blueprint/PartitionTest.php @@ -2,32 +2,29 @@ declare(strict_types=1); -namespace Umbrellio\Postgres\Unit\Schema; +namespace Umbrellio\Postgres\Unit\Schema\Blueprint; use Illuminate\Support\Carbon; use InvalidArgumentException; -use Umbrellio\Postgres\PostgresConnection; -use Umbrellio\Postgres\Schema\Blueprint; -use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar; use Umbrellio\Postgres\Tests\TestCase; +use Umbrellio\Postgres\Tests\Unit\Helpers\BlueprintAssertions; -class BlueprintTest extends TestCase +class PartitionTest extends TestCase { - /** @var Blueprint */ - private $blueprint; + use BlueprintAssertions; + + private const TABLE = 'test_table'; protected function setUp(): void { parent::setUp(); - - $this->blueprint = new Blueprint('test_table'); + $this->initializeMock(static::TABLE); } /** @test */ public function detachPartition(): void { $this->blueprint->detachPartition('some_partition'); - $this->assertSameSql('alter table "test_table" detach partition some_partition'); } @@ -38,7 +35,6 @@ public function attachPartitionRangeInt(): void 'from' => 10, 'to' => 100, ]); - $this->assertSameSql('alter table "test_table" attach partition some_partition for values from (10) to (100)'); } @@ -46,7 +42,6 @@ public function attachPartitionRangeInt(): void public function attachPartitionFailedWithoutForValuesPart(): void { $this->blueprint->attachPartition('some_partition'); - $this->expectException(InvalidArgumentException::class); $this->runToSql(); } @@ -61,9 +56,11 @@ public function attachPartitionRangeDates(): void 'to' => $tomorrow, ]); - $this->assertSameSql( - 'alter table "test_table" attach partition some_partition ' - . "for values from ('{$today->toDateTimeString()}') to ('{$tomorrow->toDateTimeString()}')"); + $this->assertSameSql(sprintf( + 'alter table "test_table" attach partition some_partition for values from (\'%s\') to (\'%s\')', + $today->toDateTimeString(), + $tomorrow->toDateTimeString() + )); } /** @test */ @@ -86,14 +83,4 @@ public function addingNumericColumnWithDefinedPrecicionAndScope() $this->blueprint->numeric('foo', 8, 2); $this->assertSameSql('alter table "test_table" add column "foo" numeric(8, 2) not null'); } - - private function assertSameSql(string $sql): void - { - $this->assertSame([$sql], $this->runToSql()); - } - - private function runToSql(): array - { - return $this->blueprint->toSql($this->createMock(PostgresConnection::class), new PostgresGrammar()); - } } diff --git a/tests/Unit/Schema/Grammars/GrammarTest.php b/tests/Unit/Schema/Grammars/GrammarTest.php deleted file mode 100644 index 808628b..0000000 --- a/tests/Unit/Schema/Grammars/GrammarTest.php +++ /dev/null @@ -1,46 +0,0 @@ -gin('foo'); - $statements = $blueprint->toSql($this->getConnectionMock(), $this->getGrammar()); - $this->assertCount(1, $statements); - $this->assertStringContainsString('CREATE INDEX', $statements[0]); - $this->assertStringContainsString('GIN("foo")', $statements[0]); - } - - /** @test */ - public function addingGistIndex() - { - $blueprint = new Blueprint('test'); - $blueprint->gist('foo'); - $statements = $blueprint->toSql($this->getConnectionMock(), $this->getGrammar()); - $this->assertCount(1, $statements); - $this->assertStringContainsString('CREATE INDEX', $statements[0]); - $this->assertStringContainsString('GIST("foo")', $statements[0]); - } - - protected function getConnectionMock() - { - return Mockery::mock(PostgresConnection::class); - } - - protected function getGrammar() - { - return new PostgresGrammar(); - } -} diff --git a/tests/Unit/Schema/IndexTest.php b/tests/Unit/Schema/IndexTest.php deleted file mode 100644 index 1b05de6..0000000 --- a/tests/Unit/Schema/IndexTest.php +++ /dev/null @@ -1,42 +0,0 @@ -blueprint = Mockery::mock(Blueprint::class) - ->makePartial() - ->shouldAllowMockingProtectedMethods(); - } - - /** @test */ - public function ginIndex() - { - $this->blueprint - ->shouldReceive('indexCommand') - ->with('gin', 'col', 'myName'); - $this->blueprint->gin('col', 'myName'); - } - - /** @test */ - public function gistIndex() - { - $this->blueprint - ->shouldReceive('indexCommand') - ->with('gist', 'col', 'myName'); - $this->blueprint->gist('col', 'myName'); - } -} diff --git a/tests/travis/install-postgres-10.sh b/tests/travis/install-postgres-10.sh new file mode 100755 index 0000000..8804124 --- /dev/null +++ b/tests/travis/install-postgres-10.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -ex + +echo "Installing Postgres 10" +sudo service postgresql stop +sudo apt-get remove -q 'postgresql-*' +sudo apt-get update -q +sudo apt-get install -q postgresql-10 postgresql-client-10 +sudo cp /etc/postgresql/{9.6,10}/main/pg_hba.conf + +echo "Restarting Postgres 10" +sudo service postgresql restart diff --git a/tests/travis/install-postgres-11.sh b/tests/travis/install-postgres-11.sh new file mode 100755 index 0000000..2ef1aab --- /dev/null +++ b/tests/travis/install-postgres-11.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -ex + +echo "Preparing Postgres 11" + +sudo service postgresql stop || true + +sudo docker run -d --name postgres11 -p 5432:5432 postgres:11.1 +sudo docker exec -i postgres11 bash <<< 'until pg_isready -U postgres > /dev/null 2>&1 ; do sleep 1; done' + +echo "Postgres 11 ready"