From 231878edf4b57ed2e25772eb0ac36c2545d5de21 Mon Sep 17 00:00:00 2001 From: MGatner Date: Wed, 27 Apr 2022 00:01:30 +0000 Subject: [PATCH 1/6] Split out coverage --- src/Filters/MenusFilter.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Filters/MenusFilter.php b/src/Filters/MenusFilter.php index ec67d64..cc6e54d 100644 --- a/src/Filters/MenusFilter.php +++ b/src/Filters/MenusFilter.php @@ -39,12 +39,19 @@ public function after(RequestInterface $request, ResponseInterface $response, $a { throw new InvalidArgumentException('No arguments supplied to Menus filter.'); } + // Ignore irrelevent responses - if ((is_cli() && ENVIRONMENT !== 'testing') || $response instanceof RedirectResponse || empty($response->getBody())) + if ($response instanceof RedirectResponse || empty($response->getBody())) { return null; } + // Check CLI separately for coverage + if (is_cli() && ENVIRONMENT !== 'testing') + { + return null; // @codeCoverageIgnore + } + // Only run on HTMl content if (strpos($response->getHeaderLine('Content-Type'), 'html') === false) { From 126b582d21089e748d657385c4c1f2f067cc9e39 Mon Sep 17 00:00:00 2001 From: MGatner Date: Wed, 27 Apr 2022 00:05:18 +0000 Subject: [PATCH 2/6] Switch to DevKit --- .github/workflows/deptrac.yml | 73 +++++++++++++++ .github/workflows/infection.yml | 72 ++++++++++++++ .github/workflows/phpcpd.yml | 36 +++++++ .github/workflows/phpcsfixer.yml | 60 ++++++++++++ .github/workflows/phpstan.yml | 75 +++++++++++++++ .github/workflows/phpunit.yml | 90 ++++++++++++++++++ .github/workflows/rector.yml | 67 +++++++++++++ .github/workflows/unused.yml | 59 ++++++++++++ .php-cs-fixer.dist.php | 24 ++--- SECURITY.md | 26 ++++++ composer-unused.php | 17 ++++ composer.json | 32 +++++-- depfile.yaml | 155 +++++++++++++++++++++++++++++++ infection.json.dist | 4 +- phpstan.neon.dist | 11 ++- phpunit.xml.dist | 16 ++-- rector.php | 130 ++++++++++++++++++++++++++ 17 files changed, 905 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/deptrac.yml create mode 100644 .github/workflows/infection.yml create mode 100644 .github/workflows/phpcpd.yml create mode 100644 .github/workflows/phpcsfixer.yml create mode 100644 .github/workflows/phpstan.yml create mode 100644 .github/workflows/phpunit.yml create mode 100644 .github/workflows/rector.yml create mode 100644 .github/workflows/unused.yml create mode 100644 SECURITY.md create mode 100644 composer-unused.php create mode 100644 depfile.yaml create mode 100644 rector.php diff --git a/.github/workflows/deptrac.yml b/.github/workflows/deptrac.yml new file mode 100644 index 0000000..441c74d --- /dev/null +++ b/.github/workflows/deptrac.yml @@ -0,0 +1,73 @@ +name: Deptrac + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'depfile.yaml' + - '.github/workflows/deptrac.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'depfile.yaml' + - '.github/workflows/deptrac.yml' + +jobs: + build: + name: Dependency Tracing + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: phive + extensions: intl, json, mbstring, xml + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create Deptrac cache directory + run: mkdir -p build/ + + - name: Cache Deptrac results + uses: actions/cache@v3 + with: + path: build + key: ${{ runner.os }}-deptrac-${{ github.sha }} + restore-keys: ${{ runner.os }}-deptrac- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Trace dependencies + run: | + sudo phive --no-progress install --global --trust-gpg-keys B8F640134AB1782E,A98E898BB53EB748 qossmic/deptrac + deptrac analyze --cache-file=build/deptrac.cache diff --git a/.github/workflows/infection.yml b/.github/workflows/infection.yml new file mode 100644 index 0000000..0d39d58 --- /dev/null +++ b/.github/workflows/infection.yml @@ -0,0 +1,72 @@ +name: Infection + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/infection.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/infection.yml' + +jobs: + main: + name: Mutation Testing + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: infection, phpunit + extensions: intl, json, mbstring, gd, xml, sqlite3 + coverage: xdebug + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Configure matchers + uses: mheap/phpunit-matcher-action@v1 + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Test with PHPUnit + run: vendor/bin/phpunit --teamcity + + - name: Mutate with Infection + run: | + git fetch --depth=1 origin $GITHUB_BASE_REF + infection --threads=2 --skip-initial-tests --coverage=build/phpunit --git-diff-base=origin/$GITHUB_BASE_REF --git-diff-filter=AM --logger-github --ignore-msi-with-no-mutations diff --git a/.github/workflows/phpcpd.yml b/.github/workflows/phpcpd.yml new file mode 100644 index 0000000..d6a877d --- /dev/null +++ b/.github/workflows/phpcpd.yml @@ -0,0 +1,36 @@ +name: PHPCPD + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcpd.yml' + push: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcpd.yml' + +jobs: + build: + name: Code Copy-Paste Detection + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: phpcpd + extensions: dom, mbstring + coverage: none + + - name: Detect duplicate code + run: phpcpd src/ tests/ diff --git a/.github/workflows/phpcsfixer.yml b/.github/workflows/phpcsfixer.yml new file mode 100644 index 0000000..06d6453 --- /dev/null +++ b/.github/workflows/phpcsfixer.yml @@ -0,0 +1,60 @@ +name: PHPCSFixer + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcsfixer.yml' + push: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcsfixer.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Coding Standards + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: json, tokenizer + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Check code for standards compliance + run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..6bdd00f --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,75 @@ +name: PHPStan + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpstan*' + - '.github/workflows/phpstan.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpstan*' + - '.github/workflows/phpstan.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Static Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpstan, phpunit + extensions: intl, json, mbstring, xml + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create PHPStan cache directory + run: mkdir -p build/phpstan + + - name: Cache PHPStan results + uses: actions/cache@v3 + with: + path: build/phpstan + key: ${{ runner.os }}-phpstan-${{ github.sha }} + restore-keys: ${{ runner.os }}-phpstan- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Run static analysis + run: vendor/bin/phpstan analyze diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml new file mode 100644 index 0000000..c875e33 --- /dev/null +++ b/.github/workflows/phpunit.yml @@ -0,0 +1,90 @@ +name: PHPUnit + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/phpunit.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/phpunit.yml' + +jobs: + main: + name: PHP ${{ matrix.php-versions }} Unit Tests + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: composer, phive, phpunit + extensions: intl, json, mbstring, gd, xdebug, xml, sqlite3 + coverage: xdebug + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Test with PHPUnit + run: vendor/bin/phpunit --verbose --coverage-text + env: + TERM: xterm-256color + TACHYCARDIA_MONITOR_GA: enabled + + - if: matrix.php-versions == '8.0' + name: Run Coveralls + continue-on-error: true + run: | + sudo phive --no-progress install --global --trust-gpg-keys E82B2FB314E9906E php-coveralls + php-coveralls --verbose --coverage_clover=build/phpunit/clover.xml --json_path build/phpunit/coveralls-upload.json + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_PARALLEL: true + COVERALLS_FLAG_NAME: PHP ${{ matrix.php-versions }} + + coveralls: + needs: [main] + name: Coveralls Finished + runs-on: ubuntu-latest + steps: + - name: Upload Coveralls results + uses: coverallsapp/github-action@master + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml new file mode 100644 index 0000000..a945743 --- /dev/null +++ b/.github/workflows/rector.yml @@ -0,0 +1,67 @@ +name: Rector + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'rector.php' + - '.github/workflows/rector.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'rector.php' + - '.github/workflows/rector.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Rector Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpstan + extensions: intl, json, mbstring, xml + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Analyze for refactoring + run: | + composer global require --dev rector/rector:^0.12.16 + rector process --dry-run --no-progress-bar diff --git a/.github/workflows/unused.yml b/.github/workflows/unused.yml new file mode 100644 index 0000000..b02fab6 --- /dev/null +++ b/.github/workflows/unused.yml @@ -0,0 +1,59 @@ +name: Unused + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - '.github/workflows/unused.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - '.github/workflows/unused.yml' + +jobs: + build: + name: Unused Package Detection + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: composer, composer-unused + extensions: intl, json, mbstring, xml + coverage: none + env: + COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Detect unused packages + run: composer-unused -vvv --output-format=github --ansi --no-interaction --no-progress diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index ca260f1..1185b9c 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,33 +1,23 @@ files() - ->in(__DIR__) + ->in([ + __DIR__ . '/src/', + __DIR__ . '/tests/', + ]) ->exclude('build') ->append([__FILE__]); -// Remove overrides for incremental changes -$overrides = [ - 'array_indentation' => false, - 'braces' => false, - 'indentation_type' => false, -]; +$overrides = []; $options = [ 'finder' => $finder, 'cacheFile' => 'build/.php-cs-fixer.cache', ]; -/* Reenable after incremental changes are applied -return Factory::create(new Standard(), $overrides, $options)->forLibrary( - 'Library', - 'Tatter Software', - '', - 2021 -); -*/ -return Factory::create(new Standard(), $overrides, $options)->forProjects(); +return Factory::create(new CodeIgniter4(), $overrides, $options)->forProjects(); diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..459a5fb --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,26 @@ +# Security Policy + +The development team and community take all security issues seriously. **Please do not make public any uncovered flaws.** + +## Reporting a Vulnerability + +Thank you for improving the security of our code! Any assistance in removing security flaws will be acknowledged. + +**Please report security flaws by emailing the development team directly: support@tattersoftware.com**. + +The lead maintainer will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating +the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the +progress towards a fix and full announcement, and may ask for additional information or guidance. + +## Disclosure Policy + +When the security team receives a security bug report, they will assign it to a primary handler. +This person will coordinate the fix and release process, involving the following steps: + +- Confirm the problem and determine the affected versions. +- Audit code to find any potential similar problems. +- Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible. + +## Comments on this Policy + +If you have suggestions on how this process could be improved please submit a Pull Request. diff --git a/composer-unused.php b/composer-unused.php new file mode 100644 index 0000000..f46e293 --- /dev/null +++ b/composer-unused.php @@ -0,0 +1,17 @@ +addNamedFilter(NamedFilter::fromString('symfony/config')) + // ->addPatternFilter(PatternFilter::fromString('/symfony-.*/')) + ->setAdditionalFilesFor('codeigniter4/framework', [ + ...Glob::glob(__DIR__ . '/vendor/codeigniter4/framework/system/Helpers/*.php'), + ]); +}; diff --git a/composer.json b/composer.json index 2c80885..dd8d868 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,18 @@ } ], "require": { - "php": "^7.3 || ^8.0", + "php": "^7.4 || ^8.0", "spatie/menu": "^2.10 || ^3.0" }, "require-dev": { - "codeigniter4/codeigniter4": "dev-develop", - "tatter/tools": "^1.10" + "codeigniter4/framework": "^4.1", + "tatter/tools": "^2.0" + }, + "config": { + "allow-plugins": { + "ergebnis/composer-normalize": true, + "phpstan/extension-installer": true + } }, "autoload": { "psr-4": { @@ -39,18 +45,24 @@ "Tests\\Support\\": "tests/_support" } }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/codeigniter4/CodeIgniter4" - } - ], "minimum-stability": "dev", "prefer-stable": true, "scripts": { "analyze": "phpstan analyze", + "ci": [ + "Composer\\Config::disableProcessTimeout", + "@deduplicate", + "@analyze", + "@test", + "@inspect", + "rector process", + "@style" + ], + "deduplicate": "phpcpd app/ src/", + "inspect": "deptrac analyze --cache-file=build/deptrac.cache", "mutate": "infection --threads=2 --skip-initial-tests --coverage=build/phpunit", - "style": "php-cs-fixer fix --verbose --ansi", + "retool": "retool", + "style": "php-cs-fixer fix --verbose --ansi --using-cache=no", "test": "phpunit" } } diff --git a/depfile.yaml b/depfile.yaml new file mode 100644 index 0000000..08efb4b --- /dev/null +++ b/depfile.yaml @@ -0,0 +1,155 @@ +paths: + - ./src/ + - ./vendor/codeigniter4/framework/system/ +exclude_files: + - '#.*test.*#i' +layers: + - name: Model + collectors: + - type: bool + must: + - type: className + regex: .*[A-Za-z]+Model$ + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Model + collectors: + - type: bool + must: + - type: className + regex: .*[A-Za-z]+Model$ + - type: directory + regex: vendor/.* + - name: Controller + collectors: + - type: bool + must: + - type: className + regex: .*\/Controllers\/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Controller + collectors: + - type: bool + must: + - type: className + regex: .*\/Controllers\/.* + - type: directory + regex: vendor/.* + - name: Config + collectors: + - type: bool + must: + - type: directory + regex: src/Config/.* + must_not: + - type: className + regex: .*Services + - type: directory + regex: vendor/.* + - name: Vendor Config + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Config/.* + must_not: + - type: className + regex: .*Services + - name: Entity + collectors: + - type: bool + must: + - type: directory + regex: src/Entities/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Entity + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Entities/.* + - name: View + collectors: + - type: bool + must: + - type: directory + regex: src/Views/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor View + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Views/.* + - name: Service + collectors: + - type: className + regex: .*Services.* +ruleset: + Entity: + - Config + - Model + - Service + - Vendor Config + - Vendor Entity + - Vendor Model + Config: + - Service + - Vendor Config + Model: + - Config + - Entity + - Service + - Vendor Config + - Vendor Entity + - Vendor Model + Service: + - Config + - Vendor Config + + # Ignore anything in the Vendor layers + Vendor Model: + - Config + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Controller: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Config: + - Config + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Entity: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor View: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View +skip_violations: diff --git a/infection.json.dist b/infection.json.dist index b175102..7badcc6 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -1,7 +1,7 @@ { "source": { "directories": [ - "src" + "src/" ], "excludes": [ "Config", @@ -15,5 +15,5 @@ "mutators": { "@default": true }, - "bootstrap": "vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php" + "bootstrap": "vendor/codeigniter4/framework/system/Test/bootstrap.php" } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c45b9b7..f27f414 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,19 +2,20 @@ parameters: tmpDir: build/phpstan level: 5 paths: - - src - - tests + - src/ + - tests/ bootstrapFiles: - - vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php - excludes_analyse: + - vendor/codeigniter4/framework/system/Test/bootstrap.php + excludePaths: - src/Config/Routes.php - src/Views/* ignoreErrors: universalObjectCratesClasses: - CodeIgniter\Entity + - CodeIgniter\Entity\Entity - Faker\Generator scanDirectories: - - vendor/codeigniter4/codeigniter4/system/Helpers + - vendor/codeigniter4/framework/system/Helpers dynamicConstantNames: - APP_NAMESPACE - CI_DEBUG diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a90a1f2..ac88cfc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ - ./src + ./src/ + ./src/Config ./src/Views - ./src/Config/Routes.php @@ -37,7 +37,7 @@ - + ./tests @@ -74,16 +74,16 @@ - + - + - + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..4ab5f02 --- /dev/null +++ b/rector.php @@ -0,0 +1,130 @@ +import(SetList::DEAD_CODE); + $containerConfigurator->import(LevelSetList::UP_TO_PHP_74); + $containerConfigurator->import(PHPUnitSetList::PHPUNIT_SPECIFIC_METHOD); + $containerConfigurator->import(PHPUnitSetList::PHPUNIT_80); + + $parameters = $containerConfigurator->parameters(); + + $parameters->set(Option::PARALLEL, true); + // The paths to refactor (can also be supplied with CLI arguments) + $parameters->set(Option::PATHS, [ + __DIR__ . '/src/', + __DIR__ . '/tests/', + ]); + + // Include Composer's autoload - required for global execution, remove if running locally + $parameters->set(Option::AUTOLOAD_PATHS, [ + __DIR__ . '/vendor/autoload.php', + ]); + + // Do you need to include constants, class aliases, or a custom autoloader? + $parameters->set(Option::BOOTSTRAP_FILES, [ + realpath(getcwd()) . '/vendor/codeigniter4/framework/system/Test/bootstrap.php', + ]); + + if (is_file(__DIR__ . '/phpstan.neon.dist')) { + $parameters->set(Option::PHPSTAN_FOR_RECTOR_PATH, __DIR__ . '/phpstan.neon.dist'); + } + + // Set the target version for refactoring + $parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_74); + + // Auto-import fully qualified class names + $parameters->set(Option::AUTO_IMPORT_NAMES, true); + + // Are there files or rules you need to skip? + $parameters->set(Option::SKIP, [ + __DIR__ . '/src/Views', + + JsonThrowOnErrorRector::class, + StringifyStrNeedlesRector::class, + + // Note: requires php 8 + RemoveUnusedPromotedPropertyRector::class, + + // Ignore tests that might make calls without a result + RemoveEmptyMethodCallRector::class => [ + __DIR__ . '/tests', + ], + + // Ignore files that should not be namespaced + NormalizeNamespaceByPSR4ComposerAutoloadRector::class => [ + __DIR__ . '/src/Helpers', + ], + + // May load view files directly when detecting classes + StringClassNameToClassConstantRector::class, + + // May be uninitialized on purpose + AddDefaultValueForUndefinedVariableRector::class, + ]); + + // Additional rules to apply + $services = $containerConfigurator->services(); + $services->set(SimplifyUselessVariableRector::class); + $services->set(RemoveAlwaysElseRector::class); + $services->set(CountArrayToEmptyArrayComparisonRector::class); + $services->set(ForToForeachRector::class); + $services->set(ChangeNestedForeachIfsToEarlyContinueRector::class); + $services->set(ChangeIfElseValueAssignToEarlyReturnRector::class); + $services->set(SimplifyStrposLowerRector::class); + $services->set(CombineIfRector::class); + $services->set(SimplifyIfReturnBoolRector::class); + $services->set(InlineIfToExplicitIfRector::class); + $services->set(PreparedValueToEarlyReturnRector::class); + $services->set(ShortenElseIfRector::class); + $services->set(SimplifyIfElseToTernaryRector::class); + $services->set(UnusedForeachValueToArrayKeysRector::class); + $services->set(ChangeArrayPushToArrayAssignRector::class); + $services->set(UnnecessaryTernaryExpressionRector::class); + $services->set(AddPregQuoteDelimiterRector::class); + $services->set(SimplifyRegexPatternRector::class); + $services->set(FuncGetArgsToVariadicParamRector::class); + $services->set(MakeInheritedMethodVisibilitySameAsParentRector::class); + $services->set(SimplifyEmptyArrayCheckRector::class); + $services->set(NormalizeNamespaceByPSR4ComposerAutoloadRector::class); + $services->set(TypedPropertyRector::class) + ->configure([ + TypedPropertyRector::INLINE_PUBLIC => true, + ]); +}; From 45d2f8e30cb9458d296c4a748a09e8d370fad4e0 Mon Sep 17 00:00:00 2001 From: MGatner Date: Wed, 27 Apr 2022 00:55:46 +0000 Subject: [PATCH 3/6] Apply static analysis --- rector.php | 8 ++++---- src/Breadcrumb.php | 7 +++---- src/Filters/MenusFilter.php | 3 --- src/Language/en/Menus.php | 2 ++ src/Menu.php | 5 +---- src/Menus/BreadcrumbsMenu.php | 8 ++------ src/Styles/AdminLTEStyle.php | 3 ++- src/Styles/BootstrapStyle.php | 3 ++- src/Styles/BreadcrumbsStyle.php | 3 ++- tests/_support/Menus/TestMenu.php | 2 -- tests/breadcrumbs/BreadcrumbsMenuTest.php | 7 ++----- tests/filter/MenusFilterTest.php | 3 ++- tests/menu/MenuTest.php | 2 -- 13 files changed, 22 insertions(+), 34 deletions(-) diff --git a/rector.php b/rector.php index 4ab5f02..fb8401a 100644 --- a/rector.php +++ b/rector.php @@ -123,8 +123,8 @@ $services->set(MakeInheritedMethodVisibilitySameAsParentRector::class); $services->set(SimplifyEmptyArrayCheckRector::class); $services->set(NormalizeNamespaceByPSR4ComposerAutoloadRector::class); - $services->set(TypedPropertyRector::class) - ->configure([ - TypedPropertyRector::INLINE_PUBLIC => true, - ]); + // $services->set(TypedPropertyRector::class) + // ->configure([ + // TypedPropertyRector::INLINE_PUBLIC => true, + // ]); }; diff --git a/src/Breadcrumb.php b/src/Breadcrumb.php index 0231617..3176b00 100644 --- a/src/Breadcrumb.php +++ b/src/Breadcrumb.php @@ -25,10 +25,9 @@ class Breadcrumb public $display; /** - * @param string $url - * @param string|null $display - */ - public function __construct(string $url, string $display = null) + * @param string|null $display + */ + public function __construct(string $url, string $display = null) { // If no display was passed then make a best guess if (empty($display)) diff --git a/src/Filters/MenusFilter.php b/src/Filters/MenusFilter.php index cc6e54d..7051634 100644 --- a/src/Filters/MenusFilter.php +++ b/src/Filters/MenusFilter.php @@ -26,11 +26,8 @@ public function before(RequestInterface $request, $arguments = null) /** * Renders the menus and injects their content. * - * @param RequestInterface $request - * @param ResponseInterface $response * @param array|null $arguments * - * @return ResponseInterface|null */ public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): ?ResponseInterface { diff --git a/src/Language/en/Menus.php b/src/Language/en/Menus.php index dbad769..790286b 100644 --- a/src/Language/en/Menus.php +++ b/src/Language/en/Menus.php @@ -1,5 +1,7 @@ 'Home', ]; diff --git a/src/Menu.php b/src/Menu.php index f89a039..8db8c73 100644 --- a/src/Menu.php +++ b/src/Menu.php @@ -29,7 +29,7 @@ abstract class Menu public function __construct(BaseMenu $builder = null) { $current = $this->detectCurrent(); - $root = (new URI(site_url()))->getPath() ?? '/'; + $root = (new URI(site_url()))->getPath() ?: '/'; $this->builder = $builder ?? BaseMenu::new()->setActive($current, $root); @@ -55,8 +55,6 @@ public function builder(): BaseMenu /** * Builds the Menu and returns the * rendered HTML string. - * - * @return string */ abstract public function __toString(): string; @@ -69,7 +67,6 @@ abstract public function __toString(): string; * replaced if that bug is fixed or if we get this: * - https://github.com/codeigniter4/CodeIgniter4/pull/4647 * - * @return string * @internal */ protected function detectCurrent(): string diff --git a/src/Menus/BreadcrumbsMenu.php b/src/Menus/BreadcrumbsMenu.php index b030138..5901f3a 100644 --- a/src/Menus/BreadcrumbsMenu.php +++ b/src/Menus/BreadcrumbsMenu.php @@ -38,7 +38,7 @@ class BreadcrumbsMenu extends Menu */ public static function discover(URI $uri = null): array { - $uri = $uri ?? Services::request()->uri; + $uri ??= Services::request()->uri; // Always start with the base URL $breadcrumbs = [ @@ -90,24 +90,20 @@ public static function pop(): ?Breadcrumb /** * Adds a new Breadcrumb to the Menu. * - * @param Breadcrumb $breadcrumb * * @return int New number of items in the Menu */ public static function push(Breadcrumb $breadcrumb): int { - self::$breadcrumbs = self::$breadcrumbs ?? []; + self::$breadcrumbs ??= []; return array_push(self::$breadcrumbs, $breadcrumb); } //-------------------------------------------------------------------- - /** * Builds the Menu and returns the * rendered HTML string. - * - * @return string */ public function __toString(): string { diff --git a/src/Styles/AdminLTEStyle.php b/src/Styles/AdminLTEStyle.php index a93bdaa..1de3719 100644 --- a/src/Styles/AdminLTEStyle.php +++ b/src/Styles/AdminLTEStyle.php @@ -1,5 +1,6 @@ Date: Wed, 27 Apr 2022 01:33:24 +0000 Subject: [PATCH 4/6] Apply updating coding standard --- src/Breadcrumb.php | 52 +++--- src/Config/Filters.php | 4 +- src/Config/Menus.php | 20 ++- src/Filters/MenusFilter.php | 119 ++++++------- src/Language/en/Menus.php | 2 +- src/Menu.php | 134 +++++++------- src/Menus/BreadcrumbsMenu.php | 207 +++++++++++----------- src/Styles/AdminLTEStyle.php | 30 ++-- src/Styles/BootstrapStyle.php | 22 +-- src/Styles/BreadcrumbsStyle.php | 24 +-- tests/_support/Menus/NotMenu.php | 4 +- tests/_support/Menus/TestMenu.php | 20 ++- tests/_support/MenusTestCase.php | 78 ++++---- tests/breadcrumbs/BreadcrumbTest.php | 30 ++-- tests/breadcrumbs/BreadcrumbsMenuTest.php | 158 +++++++++-------- tests/filter/FilterDiscoveryTest.php | 25 +-- tests/filter/MenusFilterTest.php | 178 ++++++++++--------- tests/menu/MenuTest.php | 104 +++++------ tests/menu/StylesTest.php | 94 +++++----- 19 files changed, 664 insertions(+), 641 deletions(-) diff --git a/src/Breadcrumb.php b/src/Breadcrumb.php index 3176b00..e944c24 100644 --- a/src/Breadcrumb.php +++ b/src/Breadcrumb.php @@ -1,4 +1,6 @@ -getSegments(); - $display = ucfirst(end($segments) ?: lang('Menus.home')); - } + // If no display was passed then make a best guess + if (empty($display)) { + $uri = new URI($url); + $segments = $uri->getSegments(); + $display = ucfirst(end($segments) ?: lang('Menus.home')); + } - $this->url = $url; - $this->display = $display; - } + $this->url = $url; + $this->display = $display; + } } diff --git a/src/Config/Filters.php b/src/Config/Filters.php index ad3ad0a..6602c1a 100644 --- a/src/Config/Filters.php +++ b/src/Config/Filters.php @@ -1,4 +1,6 @@ - - */ - public $aliases = [ - 'breadcrumbs' => BreadcrumbsMenu::class, - ]; + /** + * Menu class aliases. + * + * @var array + */ + public $aliases = [ + 'breadcrumbs' => BreadcrumbsMenu::class, + ]; } diff --git a/src/Filters/MenusFilter.php b/src/Filters/MenusFilter.php index 7051634..3233354 100644 --- a/src/Filters/MenusFilter.php +++ b/src/Filters/MenusFilter.php @@ -1,12 +1,14 @@ -getBody())) - { - return null; - } + // Ignore irrelevent responses + if ($response instanceof RedirectResponse || empty($response->getBody())) { + return null; + } - // Check CLI separately for coverage - if (is_cli() && ENVIRONMENT !== 'testing') - { - return null; // @codeCoverageIgnore - } + // Check CLI separately for coverage + if (is_cli() && ENVIRONMENT !== 'testing') { + return null; // @codeCoverageIgnore + } - // Only run on HTMl content - if (strpos($response->getHeaderLine('Content-Type'), 'html') === false) - { - return null; - } + // Only run on HTMl content + if (strpos($response->getHeaderLine('Content-Type'), 'html') === false) { + return null; + } - $config = config('Menus'); - $body = $response->getBody(); + $config = config('Menus'); + $body = $response->getBody(); - // Locate each placeholder - foreach ($arguments as $alias) - { - if (! isset($config->aliases[$alias])) - { - throw new RuntimeException('Unknown menu alias requested: ' . $alias); - } + // Locate each placeholder + foreach ($arguments as $alias) { + if (! isset($config->aliases[$alias])) { + throw new RuntimeException('Unknown menu alias requested: ' . $alias); + } - if (! class_exists($class = $config->aliases[$alias])) - { - throw new RuntimeException('Unable to locate menu class: ' . $class); - } + if (! class_exists($class = $config->aliases[$alias])) { + throw new RuntimeException('Unable to locate menu class: ' . $class); + } - if (! is_a($class, Menu::class, true)) - { - throw new RuntimeException($class . ' must extend ' . Menu::class); - } + if (! is_a($class, Menu::class, true)) { + throw new RuntimeException($class . ' must extend ' . Menu::class); + } - // Grab the menu content - $content = (string) (new $class); - $count = 0; + // Grab the menu content + $content = (string) (new $class()); + $count = 0; - // Swap the content for the placeholder - $body = str_replace('{{' . $alias . '}}', $content, $body, $count); - } + // Swap the content for the placeholder + $body = str_replace('{{' . $alias . '}}', $content, $body, $count); + } - // Use the new body and return the updated Response - return $response->setBody($body); - } + // Use the new body and return the updated Response + return $response->setBody($body); + } } diff --git a/src/Language/en/Menus.php b/src/Language/en/Menus.php index 790286b..3341c2e 100644 --- a/src/Language/en/Menus.php +++ b/src/Language/en/Menus.php @@ -3,5 +3,5 @@ namespace Tatter\Menus\Language\en; return [ - 'home' => 'Home', + 'home' => 'Home', ]; diff --git a/src/Menu.php b/src/Menu.php index 8db8c73..2d4a364 100644 --- a/src/Menu.php +++ b/src/Menu.php @@ -1,4 +1,6 @@ -detectCurrent(); - $root = (new URI(site_url()))->getPath() ?: '/'; + $current = $this->detectCurrent(); + $root = (new URI(site_url()))->getPath() ?: '/'; - $this->builder = $builder ?? BaseMenu::new()->setActive($current, $root); + $this->builder = $builder ?? BaseMenu::new()->setActive($current, $root); - foreach (class_uses_recursive($this) as $trait) - { - $method = 'apply' . class_basename($trait); + foreach (class_uses_recursive($this) as $trait) { + $method = 'apply' . class_basename($trait); - if (method_exists($this, $method)) - { - $this->$method(); - } - } - } + if (method_exists($this, $method)) { + $this->{$method}(); + } + } + } - /** - * Returns the underlying Spatie Menu. - */ - public function builder(): BaseMenu + /** + * Returns the underlying Spatie Menu. + */ + public function builder(): BaseMenu { - return $this->builder; - } + return $this->builder; + } - /** - * Builds the Menu and returns the - * rendered HTML string. - */ - abstract public function __toString(): string; + /** + * Builds the Menu and returns the + * rendered HTML string. + */ + abstract public function __toString(): string; - /** - * Returns the current URL to use for determining - * which menu items should be active. - * Due to this bug: - * - https://github.com/codeigniter4/CodeIgniter4/issues/4116 - * ...we cannot use current_url(). This method can be - * replaced if that bug is fixed or if we get this: - * - https://github.com/codeigniter4/CodeIgniter4/pull/4647 - * - * @internal - */ - protected function detectCurrent(): string + /** + * Returns the current URL to use for determining + * which menu items should be active. + * Due to this bug: + * - https://github.com/codeigniter4/CodeIgniter4/issues/4116 + * ...we cannot use current_url(). This method can be + * replaced if that bug is fixed or if we get this: + * - https://github.com/codeigniter4/CodeIgniter4/pull/4647 + * + * @internal + */ + protected function detectCurrent(): string { - // Force path discovery in a new IncomingRequest - $request = service('request', null, false); - $path = ltrim($request->detectPath($request->config->uriProtocol), '/'); + // Force path discovery in a new IncomingRequest + $request = service('request', null, false); + $path = ltrim($request->detectPath($request->config->uriProtocol), '/'); - // Build the full URL based on the config and path - $url = rtrim($request->config->baseURL, '/ ') . '/'; + // Build the full URL based on the config and path + $url = rtrim($request->config->baseURL, '/ ') . '/'; - // Check for an index page - if ($request->config->indexPage !== '') - { - $url .= $request->config->indexPage; + // Check for an index page + if ($request->config->indexPage !== '') { + $url .= $request->config->indexPage; - // If there is a path then we need a separator - if ($path !== '') - { - $url .= '/'; - } - } + // If there is a path then we need a separator + if ($path !== '') { + $url .= '/'; + } + } - return (string) (new URI($url . $path)); - } + return (string) (new URI($url . $path)); + } } diff --git a/src/Menus/BreadcrumbsMenu.php b/src/Menus/BreadcrumbsMenu.php index 5901f3a..8574d87 100644 --- a/src/Menus/BreadcrumbsMenu.php +++ b/src/Menus/BreadcrumbsMenu.php @@ -1,7 +1,9 @@ -uri; - - // Always start with the base URL - $breadcrumbs = [ - new Breadcrumb(base_url(), lang('Menus.home')), - ]; - - // Add each segment - $segments = []; - foreach ($uri->getSegments() as $segment) - { - $segments[] = $segment; - $breadcrumbs[] = new Breadcrumb(site_url($segments)); - } - self::set($breadcrumbs); - - return self::get(); - } - - /** - * Returns the currently-configured crumbs. - * - * @return Breadcrumb[]|null - */ - public static function get(): ?array + use BreadcrumbsStyle; + + /** + * Array of the Breadcrumbs. + * + * @var Breadcrumb[]|null + */ + protected static $breadcrumbs; + + /** + * Sets the crumbs based on the + * current/provided URI segments. + * + * @return Breadcrumb[] The discovered crumbs + */ + public static function discover(?URI $uri = null): array + { + $uri ??= Services::request()->uri; + + // Always start with the base URL + $breadcrumbs = [ + new Breadcrumb(base_url(), lang('Menus.home')), + ]; + + // Add each segment + $segments = []; + + foreach ($uri->getSegments() as $segment) { + $segments[] = $segment; + $breadcrumbs[] = new Breadcrumb(site_url($segments)); + } + self::set($breadcrumbs); + + return self::get(); + } + + /** + * Returns the currently-configured crumbs. + * + * @return Breadcrumb[]|null + */ + public static function get(): ?array { - return self::$breadcrumbs; - } - - /** - * Sets the crumbs used to build the Menu. - * - * @param Breadcrumb[]|null $breadcrumbs - */ - public static function set(?array $breadcrumbs) + return self::$breadcrumbs; + } + + /** + * Sets the crumbs used to build the Menu. + * + * @param Breadcrumb[]|null $breadcrumbs + */ + public static function set(?array $breadcrumbs) { - self::$breadcrumbs = $breadcrumbs; - } - - /** - * Removes and returns the last crumb. - * - * @return Breadcrumb - */ - public static function pop(): ?Breadcrumb + self::$breadcrumbs = $breadcrumbs; + } + + /** + * Removes and returns the last crumb. + * + * @return Breadcrumb + */ + public static function pop(): ?Breadcrumb { - return is_null(self::$breadcrumbs) ? null : array_pop(self::$breadcrumbs); - } - - /** - * Adds a new Breadcrumb to the Menu. - * - * - * @return int New number of items in the Menu - */ - public static function push(Breadcrumb $breadcrumb): int + return null === self::$breadcrumbs ? null : array_pop(self::$breadcrumbs); + } + + /** + * Adds a new Breadcrumb to the Menu. + * + * @return int New number of items in the Menu + */ + public static function push(Breadcrumb $breadcrumb): int + { + self::$breadcrumbs ??= []; + + return array_push(self::$breadcrumbs, $breadcrumb); + } + + //-------------------------------------------------------------------- + /** + * Builds the Menu and returns the + * rendered HTML string. + */ + public function __toString(): string { - self::$breadcrumbs ??= []; - - return array_push(self::$breadcrumbs, $breadcrumb); - } - - //-------------------------------------------------------------------- - /** - * Builds the Menu and returns the - * rendered HTML string. - */ - public function __toString(): string - { - // If no breadcrumbs are set then initiate discovery - if (is_null(self::$breadcrumbs)) - { - self::discover(); - } - - // Use the last item without a link - $last = self::pop(); - - foreach (self::$breadcrumbs as $breadcrumb) - { - $this->builder->link($breadcrumb->url, $breadcrumb->display); - } - - return $this->builder - ->html($last->display, [ - 'class' => 'breadcrumb-item active' - ])->render(); - } + // If no breadcrumbs are set then initiate discovery + if (null === self::$breadcrumbs) { + self::discover(); + } + + // Use the last item without a link + $last = self::pop(); + + foreach (self::$breadcrumbs as $breadcrumb) { + $this->builder->link($breadcrumb->url, $breadcrumb->display); + } + + return $this->builder + ->html($last->display, [ + 'class' => 'breadcrumb-item active', + ])->render(); + } } diff --git a/src/Styles/AdminLTEStyle.php b/src/Styles/AdminLTEStyle.php index 1de3719..f3c2ddf 100644 --- a/src/Styles/AdminLTEStyle.php +++ b/src/Styles/AdminLTEStyle.php @@ -1,7 +1,9 @@ -builder - ->addClass('nav nav-pills nav-sidebar flex-column') - ->setActiveClass('active menu-open') - ->setAttribute('data-widget', 'treeview') - ->setAttribute('role', 'menu') - ->setAttribute('data-accordion', 'false') - ->registerFilter(function (Link $link) { - $link->addParentClass('nav-item'); - $link->addClass('nav-link'); - }); - } + $this->builder + ->addClass('nav nav-pills nav-sidebar flex-column') + ->setActiveClass('active menu-open') + ->setAttribute('data-widget', 'treeview') + ->setAttribute('role', 'menu') + ->setAttribute('data-accordion', 'false') + ->registerFilter(static function (Link $link) { + $link->addParentClass('nav-item'); + $link->addClass('nav-link'); + }); + } } diff --git a/src/Styles/BootstrapStyle.php b/src/Styles/BootstrapStyle.php index 04a2218..007ead7 100644 --- a/src/Styles/BootstrapStyle.php +++ b/src/Styles/BootstrapStyle.php @@ -1,7 +1,9 @@ -builder - ->addClass('navbar-nav mr-auto') - ->registerFilter(function (Link $link) { - $link->addParentClass('nav-item'); - $link->addClass('nav-link'); - }); - } + $this->builder + ->addClass('navbar-nav mr-auto') + ->registerFilter(static function (Link $link) { + $link->addParentClass('nav-item'); + $link->addClass('nav-link'); + }); + } } diff --git a/src/Styles/BreadcrumbsStyle.php b/src/Styles/BreadcrumbsStyle.php index a44d958..2996fc7 100644 --- a/src/Styles/BreadcrumbsStyle.php +++ b/src/Styles/BreadcrumbsStyle.php @@ -1,7 +1,9 @@ -builder - ->addClass('breadcrumb') - ->setWrapperTag('ol') - ->wrap('nav', ['aria-label' => 'breadcrumb']) - ->registerFilter(function (Link $link) { - $link->addParentClass('breadcrumb-item'); - }); - } + $this->builder + ->addClass('breadcrumb') + ->setWrapperTag('ol') + ->wrap('nav', ['aria-label' => 'breadcrumb']) + ->registerFilter(static function (Link $link) { + $link->addParentClass('breadcrumb-item'); + }); + } } diff --git a/tests/_support/Menus/NotMenu.php b/tests/_support/Menus/NotMenu.php index ab7efd8..84bb046 100644 --- a/tests/_support/Menus/NotMenu.php +++ b/tests/_support/Menus/NotMenu.php @@ -1,4 +1,6 @@ -baseURL = 'http://example.com'; - $config->indexPage = ''; - Factories::injectMock('config', 'App', $config); - - // Set a current URL for checking "active" links - $_SERVER['REQUEST_URI'] = '/current'; - Services::resetSingle('request'); - - // Create some Menu aliases for testing - $config = new MenusConfig(); - $config->aliases = [ - 'test' => TestMenu::class, - 'fake' => NotMenu::class, - 'fail' => 'MissingMenu', - ]; - - $this->config = $config; - Factories::injectMock('config', 'Menus', $this->config); - } + use Expeditable; + + /** + * The configuration. + * + * @var MenusConfig + */ + protected $config; + + protected function setUp(): void + { + parent::setUp(); + + // Use some standard settings that affect URLs + $config = new App(); + $config->baseURL = 'http://example.com'; + $config->indexPage = ''; + Factories::injectMock('config', 'App', $config); + + // Set a current URL for checking "active" links + $_SERVER['REQUEST_URI'] = '/current'; + Services::resetSingle('request'); + + // Create some Menu aliases for testing + $config = new MenusConfig(); + $config->aliases = [ + 'test' => TestMenu::class, + 'fake' => NotMenu::class, + 'fail' => 'MissingMenu', + ]; + + $this->config = $config; + Factories::injectMock('config', 'Menus', $this->config); + } } diff --git a/tests/breadcrumbs/BreadcrumbTest.php b/tests/breadcrumbs/BreadcrumbTest.php index 09de7c7..c1e50f3 100644 --- a/tests/breadcrumbs/BreadcrumbTest.php +++ b/tests/breadcrumbs/BreadcrumbTest.php @@ -1,21 +1,25 @@ -assertSame('banana', $breadcrumb->display); - } + $this->assertSame('banana', $breadcrumb->display); + } - public function testGuessesDisplay() - { - $breadcrumb = new Breadcrumb(site_url('fruit')); + public function testGuessesDisplay() + { + $breadcrumb = new Breadcrumb(site_url('fruit')); - $this->assertSame('Fruit', $breadcrumb->display); - } + $this->assertSame('Fruit', $breadcrumb->display); + } } diff --git a/tests/breadcrumbs/BreadcrumbsMenuTest.php b/tests/breadcrumbs/BreadcrumbsMenuTest.php index 2866818..cae5235 100644 --- a/tests/breadcrumbs/BreadcrumbsMenuTest.php +++ b/tests/breadcrumbs/BreadcrumbsMenuTest.php @@ -1,112 +1,116 @@ -menu = new BreadcrumbsMenu(); - } + $this->menu = new BreadcrumbsMenu(); + } - /** - * Removes any Breadcrumbs. - */ - protected function tearDown(): void - { - parent::tearDown(); + /** + * Removes any Breadcrumbs. + */ + protected function tearDown(): void + { + parent::tearDown(); - BreadcrumbsMenu::set(null); - } + BreadcrumbsMenu::set(null); + } - public function testDiscovery() - { - $_SERVER['REQUEST_URI'] = '/chicken/toast'; - Services::resetSingle('request'); + public function testDiscovery() + { + $_SERVER['REQUEST_URI'] = '/chicken/toast'; + Services::resetSingle('request'); - $expected = [ - new Breadcrumb('http://example.com', 'Home'), - new Breadcrumb('http://example.com/chicken', 'Chicken'), - new Breadcrumb('http://example.com/chicken/toast', 'Toast'), - ]; + $expected = [ + new Breadcrumb('http://example.com', 'Home'), + new Breadcrumb('http://example.com/chicken', 'Chicken'), + new Breadcrumb('http://example.com/chicken/toast', 'Toast'), + ]; - $result = BreadcrumbsMenu::discover(); + $result = BreadcrumbsMenu::discover(); - $this->assertEquals($expected, $result); - } + $this->assertSame($expected, $result); + } - public function testDefaultUsesDiscovery() - { - $expected = ''; - $result = (string) $this->menu; + public function testDefaultUsesDiscovery() + { + $expected = ''; + $result = (string) $this->menu; - $this->assertSame($expected, $result); - } + $this->assertSame($expected, $result); + } - public function testGet() - { - $breadcrumbs = BreadcrumbsMenu::discover(); + public function testGet() + { + $breadcrumbs = BreadcrumbsMenu::discover(); - $result = BreadcrumbsMenu::get(); + $result = BreadcrumbsMenu::get(); - $this->assertSame($breadcrumbs, $result); - } + $this->assertSame($breadcrumbs, $result); + } - public function testSetNull() - { - BreadcrumbsMenu::discover(); - BreadcrumbsMenu::set(null); + public function testSetNull() + { + BreadcrumbsMenu::discover(); + BreadcrumbsMenu::set(null); - $result = BreadcrumbsMenu::get(); + $result = BreadcrumbsMenu::get(); - $this->assertNull($result); - } + $this->assertNull($result); + } - public function testPopNull() - { - $result = BreadcrumbsMenu::pop(); + public function testPopNull() + { + $result = BreadcrumbsMenu::pop(); - $this->assertNull($result); - } + $this->assertNull($result); + } - public function testPop() - { - $breadcrumbs = BreadcrumbsMenu::discover(); + public function testPop() + { + $breadcrumbs = BreadcrumbsMenu::discover(); - $result = BreadcrumbsMenu::pop(); + $result = BreadcrumbsMenu::pop(); - $this->assertSame($breadcrumbs[1], $result); - } + $this->assertSame($breadcrumbs[1], $result); + } - public function testPushNull() - { - $breadcrumb = new Breadcrumb('food'); + public function testPushNull() + { + $breadcrumb = new Breadcrumb('food'); - $result = BreadcrumbsMenu::push($breadcrumb); - $this->assertSame(1, $result); + $result = BreadcrumbsMenu::push($breadcrumb); + $this->assertSame(1, $result); - $this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); - } + $this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); + } - public function testPush() - { - BreadcrumbsMenu::discover(); + public function testPush() + { + BreadcrumbsMenu::discover(); - $breadcrumb = new Breadcrumb('food'); + $breadcrumb = new Breadcrumb('food'); - $result = BreadcrumbsMenu::push($breadcrumb); - $this->assertSame(3, $result); + $result = BreadcrumbsMenu::push($breadcrumb); + $this->assertSame(3, $result); - $this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); - } + $this->assertSame($breadcrumb, BreadcrumbsMenu::pop()); + } } diff --git a/tests/filter/FilterDiscoveryTest.php b/tests/filter/FilterDiscoveryTest.php index a71c268..05d081b 100644 --- a/tests/filter/FilterDiscoveryTest.php +++ b/tests/filter/FilterDiscoveryTest.php @@ -1,8 +1,9 @@ -initialize(); + public function testDiscovers() + { + $filters = Services::filters(); + $filters->initialize(); - $result = $this->getPrivateProperty($filters, 'config'); + $result = $this->getPrivateProperty($filters, 'config'); - $this->assertArrayHasKey('menus', $result->aliases); - $this->assertSame(MenusFilter::class, $result->aliases['menus']); - } + $this->assertArrayHasKey('menus', $result->aliases); + $this->assertSame(MenusFilter::class, $result->aliases['menus']); + } } diff --git a/tests/filter/MenusFilterTest.php b/tests/filter/MenusFilterTest.php index 9358ff0..d965b41 100644 --- a/tests/filter/MenusFilterTest.php +++ b/tests/filter/MenusFilterTest.php @@ -1,96 +1,100 @@ -response->setBody('{{test}}'); - $this->response->setHeader('Content-Type', 'text/html'); - $this->caller = $this->getFilterCaller(MenusFilter::class, 'after'); - } - - public function testEmptyArguments() - { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('No arguments supplied to Menus filter.'); - - ($this->caller)(); - } - - public function testRedirects() - { - $this->response = new RedirectResponse(config('App')); - $caller = $this->getFilterCaller(MenusFilter::class, 'after'); - - $result = $caller(['test']); - - $this->assertNull($result); - } - - public function testUnknownAlias() - { - $this->expectException('RuntimeException'); - $this->expectExceptionMessage('Unknown menu alias requested: popcorn'); - - ($this->caller)(['popcorn']); - } - - public function testUnknownClass() - { - $this->expectException('RuntimeException'); - $this->expectExceptionMessage('Unable to locate menu class: MissingMenu'); - - ($this->caller)(['fail']); - } - - public function testMissingInterface() - { - $this->expectException('RuntimeException'); - $this->expectExceptionMessage('Tests\Support\Menus\NotMenu must extend Tatter\Menus\Menu'); - - ($this->caller)(['fake']); - } - - public function testEmptyBody() - { - $this->response->setBody(''); - $caller = $this->getFilterCaller(MenusFilter::class, 'after'); - - $result = ($caller)(['test']); - $this->assertNull($result); - } - - public function testWrongContentType() - { - $this->response->setHeader('Content-Type', 'application/json'); - $caller = $this->getFilterCaller(MenusFilter::class, 'after'); - - $result = ($caller)(['test']); - $this->assertNull($result); - } - - public function testValid() - { - $result = ($this->caller)(['test']); - $this->assertInstanceOf(ResponseInterface::class, $result); - - $body = $result->getBody(); - $this->assertSame('bananas', $body); - } + use FilterTestTrait; + + /** + * @var Closure + */ + private $caller; + + protected function setUp(): void + { + parent::setUp(); + + $this->response->setBody('{{test}}'); + $this->response->setHeader('Content-Type', 'text/html'); + $this->caller = $this->getFilterCaller(MenusFilter::class, 'after'); + } + + public function testEmptyArguments() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('No arguments supplied to Menus filter.'); + + ($this->caller)(); + } + + public function testRedirects() + { + $this->response = new RedirectResponse(config('App')); + $caller = $this->getFilterCaller(MenusFilter::class, 'after'); + + $result = $caller(['test']); + + $this->assertNull($result); + } + + public function testUnknownAlias() + { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Unknown menu alias requested: popcorn'); + + ($this->caller)(['popcorn']); + } + + public function testUnknownClass() + { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Unable to locate menu class: MissingMenu'); + + ($this->caller)(['fail']); + } + + public function testMissingInterface() + { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Tests\Support\Menus\NotMenu must extend Tatter\Menus\Menu'); + + ($this->caller)(['fake']); + } + + public function testEmptyBody() + { + $this->response->setBody(''); + $caller = $this->getFilterCaller(MenusFilter::class, 'after'); + + $result = ($caller)(['test']); + $this->assertNull($result); + } + + public function testWrongContentType() + { + $this->response->setHeader('Content-Type', 'application/json'); + $caller = $this->getFilterCaller(MenusFilter::class, 'after'); + + $result = ($caller)(['test']); + $this->assertNull($result); + } + + public function testValid() + { + $result = ($this->caller)(['test']); + $this->assertInstanceOf(ResponseInterface::class, $result); + + $body = $result->getBody(); + $this->assertSame('bananas', $body); + } } diff --git a/tests/menu/MenuTest.php b/tests/menu/MenuTest.php index 25aa74a..6edb29c 100644 --- a/tests/menu/MenuTest.php +++ b/tests/menu/MenuTest.php @@ -1,68 +1,70 @@ -builder - ->link(site_url(''), 'Home') - ->link(site_url('/current'), 'Grain') - ->render(); - } - }; - } - - public function testGetBuilder() - { - $result = $this->menu()->builder(); + /** + * Generates a test Menu on-the-fly + */ + private function menu(): Menu + { + return new class () extends Menu { + public function __toString(): string + { + return $this->builder + ->link(site_url(''), 'Home') + ->link(site_url('/current'), 'Grain') + ->render(); + } + }; + } - $this->assertInstanceOf(BaseMenu::class, $result); - } + public function testGetBuilder() + { + $result = $this->menu()->builder(); - public function testUsesBuilder() - { - $menu = new class(BaseMenu::new()->link(site_url('/home'), 'asparagus')) extends Menu { + $this->assertInstanceOf(BaseMenu::class, $result); + } - public function __toString(): string - { - return $this->builder->render(); - } - }; + public function testUsesBuilder() + { + $menu = new class (BaseMenu::new()->link(site_url('/home'), 'asparagus')) extends Menu { + public function __toString(): string + { + return $this->builder->render(); + } + }; - $result = (string) $menu; + $result = (string) $menu; - $this->assertSame('', $result); - } + $this->assertSame('', $result); + } - public function testGetUsesCurrentUrl() - { - $expected = ''; - $result = $this->menu()->__toString(); + public function testGetUsesCurrentUrl() + { + $expected = ''; + $result = $this->menu()->__toString(); - $this->assertSame($expected, $result); - } + $this->assertSame($expected, $result); + } - public function testGetUsesIndexPage() - { - $config = config('App'); - $config->indexPage = 'index.php'; - Services::injectMock('request', null); + public function testGetUsesIndexPage() + { + $config = config('App'); + $config->indexPage = 'index.php'; + Services::injectMock('request', null); - $expected = ''; - $result = $this->menu()->__toString(); + $expected = ''; + $result = $this->menu()->__toString(); - $this->assertSame($expected, $result); - } + $this->assertSame($expected, $result); + } } diff --git a/tests/menu/StylesTest.php b/tests/menu/StylesTest.php index a8aa780..ef1b611 100644 --- a/tests/menu/StylesTest.php +++ b/tests/menu/StylesTest.php @@ -1,52 +1,54 @@ -builder - ->link(site_url('/'), 'Home') - ->link(site_url('/current'), 'Grain') - ->render(); - } - }; - - $result = $menu->__toString(); - - $this->assertStringContainsString('li class="nav-item"', $result); - $this->assertStringContainsString('class="nav-link"', $result); - } - - public function testAdminLTEStyleAppliesClasses() - { - $menu = new class extends Menu { - - use AdminLTEStyle; - - public function __toString(): string - { - return $this->builder - ->link(site_url('/'), 'Home') - ->link(site_url('/current'), 'Grain') - ->render(); - } - }; - - $result = $menu->__toString(); - - $this->assertStringContainsString('data-widget="treeview"', $result); - $this->assertStringContainsString('class="nav nav-pills', $result); - $this->assertStringContainsString('class="nav-link"', $result); - } + public function testBootstrapStyleAppliesClasses() + { + $menu = new class () extends Menu { + use BootstrapStyle; + + public function __toString(): string + { + return $this->builder + ->link(site_url('/'), 'Home') + ->link(site_url('/current'), 'Grain') + ->render(); + } + }; + + $result = $menu->__toString(); + + $this->assertStringContainsString('li class="nav-item"', $result); + $this->assertStringContainsString('class="nav-link"', $result); + } + + public function testAdminLTEStyleAppliesClasses() + { + $menu = new class () extends Menu { + use AdminLTEStyle; + + public function __toString(): string + { + return $this->builder + ->link(site_url('/'), 'Home') + ->link(site_url('/current'), 'Grain') + ->render(); + } + }; + + $result = $menu->__toString(); + + $this->assertStringContainsString('data-widget="treeview"', $result); + $this->assertStringContainsString('class="nav nav-pills', $result); + $this->assertStringContainsString('class="nav-link"', $result); + } } From ba6eb9911bcad78bbf184af443d2d621b083a9ba Mon Sep 17 00:00:00 2001 From: MGatner Date: Wed, 27 Apr 2022 01:41:16 +0000 Subject: [PATCH 5/6] Fix assertions --- tests/breadcrumbs/BreadcrumbsMenuTest.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/breadcrumbs/BreadcrumbsMenuTest.php b/tests/breadcrumbs/BreadcrumbsMenuTest.php index cae5235..ef34b7c 100644 --- a/tests/breadcrumbs/BreadcrumbsMenuTest.php +++ b/tests/breadcrumbs/BreadcrumbsMenuTest.php @@ -38,15 +38,17 @@ public function testDiscovery() $_SERVER['REQUEST_URI'] = '/chicken/toast'; Services::resetSingle('request'); + $breadcrumbs = BreadcrumbsMenu::discover(); + $expected = [ - new Breadcrumb('http://example.com', 'Home'), - new Breadcrumb('http://example.com/chicken', 'Chicken'), - new Breadcrumb('http://example.com/chicken/toast', 'Toast'), + 'http://example.com', + 'http://example.com/chicken', + 'http://example.com/chicken/toast', ]; + $this->assertSame($expected, array_column($breadcrumbs, 'url')); - $result = BreadcrumbsMenu::discover(); - - $this->assertSame($expected, $result); + $expected = ['Home', 'Chicken', 'Toast']; + $this->assertSame($expected, array_column($breadcrumbs, 'display')); } public function testDefaultUsesDiscovery() From fa58dc6b7984f6e02165961122f696253f884be0 Mon Sep 17 00:00:00 2001 From: MGatner Date: Wed, 27 Apr 2022 01:44:25 +0000 Subject: [PATCH 6/6] Fix workflows --- .github/workflows/analyze.yml | 81 ------------------------------- .github/workflows/compare.yml | 29 ----------- .github/workflows/test.yml | 90 ----------------------------------- rector.php | 1 + 4 files changed, 1 insertion(+), 200 deletions(-) delete mode 100644 .github/workflows/analyze.yml delete mode 100644 .github/workflows/compare.yml delete mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml deleted file mode 100644 index 12c48c1..0000000 --- a/.github/workflows/analyze.yml +++ /dev/null @@ -1,81 +0,0 @@ -# When a PR is opened or a push is made, perform -# a static analysis check on the code using PHPStan. -name: PHPStan - -on: - pull_request: - branches: - - 'develop' - paths: - - 'src/**' - - 'tests/**' - - 'composer.**' - - 'phpstan*' - - '.github/workflows/analyze.yml' - push: - branches: - - 'develop' - paths: - - 'src/**' - - 'tests/**' - - 'composer.**' - - 'phpstan*' - - '.github/workflows/analyze.yml' - -jobs: - build: - name: PHP ${{ matrix.php-versions }} Static Analysis - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - php-versions: ['7.3', '7.4', '8.0'] - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - tools: composer, pecl, phpunit - extensions: intl, json, mbstring, gd, mysqlnd, xdebug, xml, sqlite3 - env: - COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Create composer cache directory - run: mkdir -p ${{ steps.composer-cache.outputs.dir }} - - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Create PHPStan cache directory - run: mkdir -p build/phpstan - - - name: Cache PHPStan results - uses: actions/cache@v2 - with: - path: build/phpstan - key: ${{ runner.os }}-phpstan-${{ github.sha }} - restore-keys: ${{ runner.os }}-phpstan- - - - name: Install dependencies (limited) - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name }} - run: composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader - - - name: Install dependencies (authenticated) - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} - run: composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader - env: - COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }} - - - name: Run static analysis - run: vendor/bin/phpstan analyze diff --git a/.github/workflows/compare.yml b/.github/workflows/compare.yml deleted file mode 100644 index c6b5e9b..0000000 --- a/.github/workflows/compare.yml +++ /dev/null @@ -1,29 +0,0 @@ -# When a PR is opened or a push is made, compare -# code for backwards compatibility. -name: RoaveBC - -on: - pull_request: - branches: - - develop - paths: - - 'src/**' - -jobs: - compare: - name: Compare for Backwards Compatibility - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Run comparison (limited) - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name }} - uses: docker://nyholm/roave-bc-check-ga - - - name: Run comparison (authenticated) - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} - uses: docker://nyholm/roave-bc-check-ga - env: - COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 7bfa417..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: PHPUnit - -on: - pull_request: - branches: - - develop - push: - branches: - - develop - -jobs: - main: - name: PHP ${{ matrix.php-versions }} Unit Tests - - strategy: - matrix: - php-versions: ['7.3', '7.4', '8.0'] - - runs-on: ubuntu-latest - - if: "!contains(github.event.head_commit.message, '[ci skip]')" - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - tools: composer, pecl, phpunit - extensions: intl, json, mbstring, gd, mysqlnd, xdebug, xml, sqlite3 - coverage: xdebug - env: - COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Cache composer dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies (limited) - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name }} - run: composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader - - - name: Install dependencies (authenticated) - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }} - run: composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader - env: - COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }} - - - name: Enable Tachycardia - run: echo "TACHYCARDIA_MONITOR_GA=enabled" >> $GITHUB_ENV - - - name: Test with PHPUnit - run: vendor/bin/phpunit --verbose --coverage-text - env: - TERM: xterm-256color - - - if: matrix.php-versions == '8.0' - name: Mutate with Infection - run: | - composer global require infection/infection - git fetch --depth=1 origin $GITHUB_BASE_REF - infection --threads=2 --skip-initial-tests --coverage=build/phpunit --git-diff-base=origin/$GITHUB_BASE_REF --git-diff-filter=AM --logger-github --ignore-msi-with-no-mutations - - - if: matrix.php-versions == '8.0' - name: Run Coveralls - run: vendor/bin/php-coveralls --verbose --coverage_clover=build/phpunit/clover.xml --json_path build/phpunit/coveralls-upload.json - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_PARALLEL: true - COVERALLS_FLAG_NAME: PHP ${{ matrix.php-versions }} - - coveralls: - needs: [main] - name: Coveralls Finished - runs-on: ubuntu-latest - steps: - - name: Upload Coveralls results - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - parallel-finished: true diff --git a/rector.php b/rector.php index fb8401a..c25dae2 100644 --- a/rector.php +++ b/rector.php @@ -74,6 +74,7 @@ // Are there files or rules you need to skip? $parameters->set(Option::SKIP, [ + __DIR__ . '/src/Config/Filters.php', __DIR__ . '/src/Views', JsonThrowOnErrorRector::class,