diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml new file mode 100644 index 0000000..7e6f333 --- /dev/null +++ b/.github/workflows/ci-checks.yml @@ -0,0 +1,58 @@ +name: CI-CHECKS + +on: [push] + +jobs: + run-phpcs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: php-actions/composer@v6 + - name: PHPCS analyze + run: ./vendor/bin/phpcs -p -s --standard=phpcs.xml src tests + run-php-stan: + needs: run-phpcs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: php-actions/composer@v6 + - name: PHPStan Static Analysis source code + uses: php-actions/phpstan@v3 + with: + version: 1.10.14 + configuration: ./phpstan.neon.dist + run-php-unit-tests: + needs: run-php-stan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: php-actions/composer@v6 + - uses: php-actions/phpunit@v3 + with: + version: 9.5.28 + bootstrap: vendor/autoload.php + configuration: phpunit.xml + args: --coverage-text + run-assemble-php-unit-coverage: + needs: run-php-unit-tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: php-actions/composer@v6 + - name: Run PHPUnit Tests + uses: php-actions/phpunit@v3 + with: + version: 9.5.28 + php_extensions: xdebug + bootstrap: vendor/autoload.php + configuration: phpunit.xml + args: --coverage-text + env: + XDEBUG_MODE: coverage + - name: Generate test coverage badge + uses: timkrase/phpunit-coverage-badge@v1.2.0 + with: + report: ./clover.xml + coverage_badge_path: 'badge.svg' + push_badge: true + repo_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71b4a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +composer.phar +/vendor/ +.idea +.phpunit.result.cache + +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cb1d7c3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM php:7.4-fpm +RUN apt-get update && apt-get install -y \ + zlib1g-dev \ + libzip-dev \ + unzip \ + mc +RUN docker-php-ext-install zip +RUN pecl install xdebug-3.1.5 +RUN docker-php-ext-enable xdebug +RUN mkdir -p /home/app +WORKDIR /home/app +COPY . /home/app +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..081babc --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# vat number format validators config + +![Code Coverage Badge](./badge.svg) + +This package provides a preconfigured configuration class for vat number format validators for country. +Is an extension of the package https://github.com/rocketfellows/specific-country-vat-number-format-validators-config. + +## Installation + +```shell +composer require rocketfellows/-vat-number-format-validators-config +``` + +## Dependencies + +- https://github.com/rocketfellows/specific-country-vat-number-format-validators-config v1.0.0; +- https://github.com/rocketfellows/-vat-format-validator v1.0.0; + +## References + +- https://github.com/rocketfellows/country-vat-format-validator-interface +- https://github.com/arslanim/iso-standard-3166 + +## List of package components + +- **_rocketfellows\VatNumberFormatValidatorsConfig\VatNumberFormatValidatorsConfig_** - preconfigured configuration class for vat number format validators for country; + +## VatNumberFormatValidatorsConfig description + +A configuration class that provides a match for the vat number format validators for the country . + +Class interface: +- **_getCountry_** - returns **_Country_** instance; +- **_getValidators_** - returns validators tuple + +When initializing the default configuration, the **_getValidators_** function returns a tuple with a single validator - an instance of VatFormatValidator. + +```php +$config = new VatNumberFormatValidatorsConfig(); + +$config->getCountry(); // returns Country instance +$config->getValidators(); // returns CountryVatFormatValidators with one item - instance of VatFormatValidator +``` + +You can override the default validator by initializing the configuration class object with a new default validator through the first parameter of the class constructor. +Attention - validator must implement interface **_CountryVatFormatValidatorInterface_**. + +```php +$newDefaultValidator = new NewDefaultValidator(); // instance of CountryVatFormatValidatorInterface +$config = new VatNumberFormatValidatorsConfig($newDefaultValidator); // initialize with new default validator + +$config->getValidators(); // returns CountryVatFormatValidators with one item - $newDefaultValidator +``` + +You can add additional validators to the default validator via the second constructor parameter. + +Attention - additional validators parameter must be instance of tuple **_CountryVatFormatValidators_**. +And each additional validator must implement interface **_CountryVatFormatValidatorInterface_**. + +```php +$firstAdditionalValidator = new FirstAdditionalValidator(); // instance of CountryVatFormatValidatorInterface +$secondAdditionalValidator = new SecondAdditionalValidator(); // instance of CountryVatFormatValidatorInterface + +$config = new VatNumberFormatValidatorsConfig( + null, + ( + new CountryVatFormatValidators( + $firstAdditionalValidator, + $secondAdditionalValidator + ) + ) +); + +// returns CountryVatFormatValidators with three items: +// default preconfigured validator by default - instance of VatFormatValidator +// $firstAdditionalValidator - from additional tuple +// $secondAdditionalValidator - from additional tuple +$config->getValidators(); +``` + +You can also completely rebuild the configuration by passing the default validator and a tuple of additional validators to the config class constructor. + +```php +$defaultValidator = new DefaultValidator(); // instance of CountryVatFormatValidatorInterface +$firstAdditionalValidator = new FirstAdditionalValidator(); // instance of CountryVatFormatValidatorInterface +$secondAdditionalValidator = new SecondAdditionalValidator(); // instance of CountryVatFormatValidatorInterface + +$config = new VatNumberFormatValidatorsConfig( + $defaultValidator, + ( + new CountryVatFormatValidators( + $firstAdditionalValidator, + $secondAdditionalValidator + ) + ) +); + +// returns CountryVatFormatValidators with three items: +// $defaultValidator from constructor first parameter +// $firstAdditionalValidator - from additional tuple +// $secondAdditionalValidator - from additional tuple +$config->getValidators(); +``` + +More use case examples can be found in the package's unit tests. + +## Contributing + +Welcome to pull requests. If there is a major changes, first please open an issue for discussion. + +Please make sure to update tests as appropriate. diff --git a/badge.svg b/badge.svg new file mode 100644 index 0000000..e8c81e7 --- /dev/null +++ b/badge.svg @@ -0,0 +1,16 @@ + + + + + + + + + coverage + coverage + + + 0 % + 0 % + + \ No newline at end of file diff --git a/clover.xml b/clover.xml new file mode 100644 index 0000000..e354a07 --- /dev/null +++ b/clover.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..463e384 --- /dev/null +++ b/composer.json @@ -0,0 +1,35 @@ +{ + // TODO: set name + "name": "rocketfellows/-vat-number-format-validators-config", + "authors": [ + { + "name": "Arslan Imamutdinov", + "email": "ara.imamutdinov@gmail.com" + } + ], + "license": "MIT", + "require": { + "php": ">=7.4", + "rocketfellows/specific-country-vat-number-format-validators-config": "1.0.0", + // TODO: require vat format validator package + "rocketfellows/-vat-format-validator": "1.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5", + "phpstan/phpstan": "^1.10", + "squizlabs/php_codesniffer": "3.6.2", + "roave/security-advisories": "dev-latest" + }, + "autoload": { + "psr-4": { + // TODO: set namespace + "rocketfellows\\VatNumberFormatValidatorsConfig\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + // TODO: set namespace + "rocketfellows\\VatNumberFormatValidatorsConfig\\tests\\": "tests/" + } + } +} diff --git a/docker-compose-down.sh b/docker-compose-down.sh new file mode 100644 index 0000000..db6c58e --- /dev/null +++ b/docker-compose-down.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker-compose down diff --git a/docker-compose-up.sh b/docker-compose-up.sh new file mode 100644 index 0000000..b8f93f7 --- /dev/null +++ b/docker-compose-up.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker-compose up -d \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..67afad3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: "3" +services: + php: + build: + dockerfile: Dockerfile + context: ./ + volumes: + - ./:/home/app \ No newline at end of file diff --git a/docker-deploy.sh b/docker-deploy.sh new file mode 100755 index 0000000..2f07c11 --- /dev/null +++ b/docker-deploy.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +docker-compose -f docker-compose.yml up -d && \ +docker-compose exec php composer install && \ +docker-compose exec php composer dump-autoload diff --git a/docker-run-checks.sh b/docker-run-checks.sh new file mode 100644 index 0000000..ca1629c --- /dev/null +++ b/docker-run-checks.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +sh ./docker-run-phpcs.sh && \ +sh ./docker-run-phpstan.sh && \ +sh ./docker-run-unit-tests.sh diff --git a/docker-run-phpcs.sh b/docker-run-phpcs.sh new file mode 100644 index 0000000..b6dea33 --- /dev/null +++ b/docker-run-phpcs.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +echo "=================== PHPCS ===================" + +eval "docker-compose exec php ./vendor/bin/phpcs -p -s --standard=phpcs.xml src tests" + +echo "\n=============================================" diff --git a/docker-run-phpstan.sh b/docker-run-phpstan.sh new file mode 100644 index 0000000..488f7f0 --- /dev/null +++ b/docker-run-phpstan.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +echo "=================== PHPSTAN ===================" + +eval "docker-compose exec php ./vendor/bin/phpstan analyse" + +echo "\n=============================================" diff --git a/docker-run-unit-tests.sh b/docker-run-unit-tests.sh new file mode 100644 index 0000000..bf20794 --- /dev/null +++ b/docker-run-unit-tests.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +echo "=================== UNIT-TESTS ===================" + +eval "docker-compose exec php ./vendor/bin/phpunit --colors=always --verbose --testdox" + +echo "\n=============================================" diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..aafcac2 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,26 @@ + + Base component coding style + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..a76a832 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,5 @@ +parameters: + level: 5 + paths: + - src + - tests \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..5fb8388 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,24 @@ + + + + + ./src + + + + + + + + + ./tests/unit + + + \ No newline at end of file diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/CountryVatNumberFormatValidatorsConfig.php b/src/CountryVatNumberFormatValidatorsConfig.php new file mode 100644 index 0000000..f9f966b --- /dev/null +++ b/src/CountryVatNumberFormatValidatorsConfig.php @@ -0,0 +1,21 @@ +createMock(CountryVatFormatValidatorInterface::class); + + $configClassName = self::TESTING_CONFIG_CLASS; + $config = new $configClassName($newDefaultValidator); + + $actualValidators = []; + + foreach ($config->getValidators() as $validator) { + $actualValidators[] = $validator; + } + + $this->assertExpectedConfigCountry($config); + $this->assertCount(1, $actualValidators); + $this->assertNotInstanceOf(self::EXPECTED_CONFIG_DEFAULT_VALIDATOR_CLASS, $actualValidators[0]); + $this->assertEquals($newDefaultValidator, $actualValidators[0]); + } + + public function testDefaultConfigInitialization(): void + { + $configClassName = self::TESTING_CONFIG_CLASS; + $config = new $configClassName(); + + $actualValidators = []; + + foreach ($config->getValidators() as $validator) { + $actualValidators[] = $validator; + } + + $this->assertExpectedConfigCountry($config); + $this->assertCount(1, $actualValidators); + $this->assertInstanceOf(self::EXPECTED_CONFIG_DEFAULT_VALIDATOR_CLASS, $actualValidators[0]); + } + + /** + * @dataProvider getConfigValidators + * @param CountryVatFormatValidatorInterface|null $defaultValidator + * @param CountryVatFormatValidators|null $additionalValidators + * @param CountryVatFormatValidatorInterface[] $expectedValidators + */ + public function testConfigureConfigValidators( + ?CountryVatFormatValidatorInterface $defaultValidator, + ?CountryVatFormatValidators $additionalValidators, + array $expectedValidators + ): void { + $configClassName = self::TESTING_CONFIG_CLASS; + $config = new $configClassName($defaultValidator, $additionalValidators); + + $actualValidators = []; + + foreach ($config->getValidators() as $validator) { + $actualValidators[] = $validator; + } + + $this->assertExpectedConfigCountry($config); + $this->assertEquals($expectedValidators, $actualValidators); + } + + public function getConfigValidators(): array + { + $defaultValidator = $this->createMock(CountryVatFormatValidatorInterface::class); + $validator = $this->createMock(CountryVatFormatValidatorInterface::class); + + return [ + 'default validator null, additional validators null' => [ + 'defaultValidator' => null, + 'additionalValidators' => null, + 'expectedValidators' => [ + $this->getDefaultConfigValidator(), + ], + ], + 'default validator null, additional validators not null and empty' => [ + 'defaultValidator' => null, + 'additionalValidators' => new CountryVatFormatValidators(), + 'expectedValidators' => [ + $this->getDefaultConfigValidator(), + ], + ], + 'default validator null, additional validators not null and not empty' => [ + 'defaultValidator' => null, + 'additionalValidators' => new CountryVatFormatValidators( + $validator, + $validator, + $validator + ), + 'expectedValidators' => [ + $this->getDefaultConfigValidator(), + $validator, + $validator, + $validator + ], + ], + 'default validator not null, additional validators null' => [ + 'defaultValidator' => $defaultValidator, + 'additionalValidators' => null, + 'expectedValidators' => [ + $defaultValidator, + ], + ], + 'default validator not null, additional validators not null and empty' => [ + 'defaultValidator' => $defaultValidator, + 'additionalValidators' => new CountryVatFormatValidators(), + 'expectedValidators' => [ + $defaultValidator, + ], + ], + 'default validator not null, additional validators not null and not empty' => [ + 'defaultValidator' => $defaultValidator, + 'additionalValidators' => new CountryVatFormatValidators( + $validator, + $validator, + $validator + ), + 'expectedValidators' => [ + $defaultValidator, + $validator, + $validator, + $validator + ], + ], + ]; + } + + private function assertExpectedConfigCountry(CountryVatNumberFormatValidatorsConfigInterface $config): void + { + $this->assertEquals(ISO3166::COUNTRY(), $config->getCountry()); + } + + private function getDefaultConfigValidator(): CountryVatFormatValidatorInterface + { + $defaultConfigValidatorClassName = self::EXPECTED_CONFIG_DEFAULT_VALIDATOR_CLASS; + + return new $defaultConfigValidatorClassName(); + } +}