From 3da8383f4e728d2f675973565e94b60d92d015a0 Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 30 Dec 2021 23:31:23 +0000 Subject: [PATCH 1/6] Rework test properties --- src/Test/AssetsTestTrait.php | 38 +++++++++++++++---------------- tests/AssetTest.php | 8 +++---- tests/AssetsTestTraitTest.php | 8 +++---- tests/BundleTest.php | 4 ++-- tests/BundlesTestCaseTest.php | 4 ++-- tests/FilterTest.php | 6 ++--- tests/RouteBundleTest.php | 16 ++++++------- tests/_support/AssetsTestCase.php | 30 ------------------------ tests/_support/TestCase.php | 30 ++++++++++++++++++++++++ 9 files changed, 71 insertions(+), 73 deletions(-) delete mode 100644 tests/_support/AssetsTestCase.php create mode 100644 tests/_support/TestCase.php diff --git a/src/Test/AssetsTestTrait.php b/src/Test/AssetsTestTrait.php index 12fde78..cdab0a2 100644 --- a/src/Test/AssetsTestTrait.php +++ b/src/Test/AssetsTestTrait.php @@ -17,42 +17,42 @@ trait AssetsTestTrait { /** - * Virtual workspace + * The virtual workspace. * * @var vfsStreamDirectory|null */ - protected $root; - - /** - * @var AssetsConfig - */ - protected $config; + protected static $root; /** * Whether the publishers have been run. * * @var bool */ - private $published = false; + private static $published = false; + + /** + * @var AssetsConfig + */ + protected $assets; /** * Creates the VFS (if necessary) and updates the Assets config. */ protected function setUpAssetsTestTrait(): void { - if ($this->root === null) { - $this->root = vfsStream::setup('root'); + if (self::$root === null) { + self::$root = vfsStream::setup('root'); } // Create the config - $this->config = new AssetsConfig(); - $this->config->directory = $this->root->url() . DIRECTORY_SEPARATOR; - $this->config->useTimestamps = false; // These make testing much harder + $this->assets = new AssetsConfig(); + $this->assets->directory = self::$root->url() . DIRECTORY_SEPARATOR; + $this->assets->useTimestamps = false; // These make testing much harder - Asset::useConfig($this->config); + Asset::useConfig($this->assets); // Add VFS as an allowed Publisher directory - config('Publisher')->restrictions[$this->config->directory] = '*'; + config('Publisher')->restrictions[$this->assets->directory] = '*'; } /** @@ -61,8 +61,8 @@ protected function setUpAssetsTestTrait(): void protected function tearDownAssetsTestTrait(): void { if (! empty($this->refreshVfs)) { - $this->root = null; - $this->published = false; + self::$root = null; + self::$published = false; } Asset::useConfig(null); @@ -74,7 +74,7 @@ protected function tearDownAssetsTestTrait(): void */ protected function publishAll(): void { - if ($this->published) { + if (self::$published) { return; } @@ -82,6 +82,6 @@ protected function publishAll(): void $publisher->publish(); } - $this->published = true; + self::$published = true; } } diff --git a/tests/AssetTest.php b/tests/AssetTest.php index 9f5d1f3..c148f67 100644 --- a/tests/AssetTest.php +++ b/tests/AssetTest.php @@ -3,12 +3,12 @@ use Tatter\Assets\Asset; use Tatter\Assets\Config\Assets as AssetsConfig; use Tatter\Assets\Exceptions\AssetsException; -use Tests\Support\AssetsTestCase; +use Tests\Support\TestCase; /** * @internal */ -final class AssetTest extends AssetsTestCase +final class AssetTest extends TestCase { public function testStringable() { @@ -48,9 +48,9 @@ public function testLoadsConfig() public function testUseTimestamps() { - $this->config->useTimestamps = true; + $this->assets->useTimestamps = true; - $mtime = filemtime($this->config->directory . 'apple.css'); + $mtime = filemtime($this->assets->directory . 'apple.css'); $expected = ''; $asset = Asset::createFromPath('apple.css'); diff --git a/tests/AssetsTestTraitTest.php b/tests/AssetsTestTraitTest.php index 7e467a0..52f113d 100644 --- a/tests/AssetsTestTraitTest.php +++ b/tests/AssetsTestTraitTest.php @@ -14,7 +14,7 @@ final class AssetsTestTraitTest extends CIUnitTestCase public function testPublishesOnce() { - $file = $this->config->directory . $this->config->vendor . 'fruit/third_party.js'; + $file = $this->assets->directory . $this->assets->vendor . 'fruit/third_party.js'; $this->publishAll(); $this->assertFileExists($file); @@ -27,12 +27,10 @@ public function testPublishesOnce() public function testTearDownRefreshes() { - $this->assertNotNull($this->root); + $this->assertNotNull(self::$root); $this->refreshVfs = true; $this->tearDownAssetsTestTrait(); - $this->assertNull($this->root); - - $this->refreshVfs = false; + $this->assertNull(self::$root); } } diff --git a/tests/BundleTest.php b/tests/BundleTest.php index 0c4f5a6..d16d3da 100644 --- a/tests/BundleTest.php +++ b/tests/BundleTest.php @@ -2,13 +2,13 @@ use Tatter\Assets\Asset; use Tatter\Assets\Bundle; -use Tests\Support\AssetsTestCase; use Tests\Support\Bundles\FruitSalad; +use Tests\Support\TestCase; /** * @internal */ -final class BundleTest extends AssetsTestCase +final class BundleTest extends TestCase { public function testConstructorPaths() { diff --git a/tests/BundlesTestCaseTest.php b/tests/BundlesTestCaseTest.php index 37c141a..352a111 100644 --- a/tests/BundlesTestCaseTest.php +++ b/tests/BundlesTestCaseTest.php @@ -15,8 +15,8 @@ protected function setUp(): void { parent::setUp(); - copy(SUPPORTPATH . 'Files/apple.css', $this->config->directory . 'apple.css'); - copy(SUPPORTPATH . 'Files/banana.js', $this->config->directory . 'banana.js'); + copy(SUPPORTPATH . 'Files/apple.css', $this->assets->directory . 'apple.css'); + copy(SUPPORTPATH . 'Files/banana.js', $this->assets->directory . 'banana.js'); } public function bundleProvider(): array diff --git a/tests/FilterTest.php b/tests/FilterTest.php index 55beb4b..e66b764 100644 --- a/tests/FilterTest.php +++ b/tests/FilterTest.php @@ -11,7 +11,7 @@ /** * @internal */ -final class FilterTest extends AssetsTestCase +final class FilterTest extends TestCase { use FilterTestTrait; @@ -33,7 +33,7 @@ protected function setUp(): void { parent::setUp(); - $this->config->routes = [ + $this->assets->routes = [ '*' => [ 'https://pagecdn.io/lib/cleave/1.6.0/cleave.min.js', FruitSalad::class, @@ -102,7 +102,7 @@ public function testFilterWithArguments() public function testEmptyTags() { - $this->config->routes = []; + $this->assets->routes = []; $caller = $this->getFilterCaller(AssetsFilter::class, 'after'); diff --git a/tests/RouteBundleTest.php b/tests/RouteBundleTest.php index cd16b4b..3d77ab5 100644 --- a/tests/RouteBundleTest.php +++ b/tests/RouteBundleTest.php @@ -2,20 +2,20 @@ use Tatter\Assets\Exceptions\AssetsException; use Tatter\Assets\RouteBundle; -use Tests\Support\AssetsTestCase; use Tests\Support\Bundles\FruitSalad; use Tests\Support\Bundles\LunchBreak; +use Tests\Support\TestCase; /** * @internal */ -final class RouteBundleTest extends AssetsTestCase +final class RouteBundleTest extends TestCase { protected function setUp(): void { parent::setUp(); - $this->config->routes = [ + $this->assets->routes = [ '*' => [ 'https://pagecdn.io/lib/cleave/1.6.0/cleave.min.js', FruitSalad::class, @@ -51,7 +51,7 @@ public function testCreateFromRouteUsesCache() FruitSalad::class, ])); - $this->config->useCache = true; + $this->assets->useCache = true; $this->assertEmpty(cache()->getCacheInfo()); // Place a fake bundle in the cache @@ -64,7 +64,7 @@ public function testCreateFromRouteUsesCache() public function testCreateFromRouteSavesToCache() { - $this->config->useCache = true; + $this->assets->useCache = true; $this->assertEmpty(cache()->getCacheInfo()); $result = RouteBundle::createFromRoute('foo'); @@ -74,7 +74,7 @@ public function testCreateFromRouteSavesToCache() public function testCreateFromRouteEmpty() { - $this->config->routes['*'] = []; + $this->assets->routes['*'] = []; $result = RouteBundle::createFromRoute('foo'); @@ -85,7 +85,7 @@ public function testCreateFromRouteEmpty() public function testCreateFromRouteThrowsNotString() { // @phpstan-ignore-next-line - $this->config->routes['invalid'] = [true]; + $this->assets->routes['invalid'] = [true]; $this->expectException('InvalidArgumentException'); $this->expectExceptionMessage('Config $route items must be strings.'); @@ -95,7 +95,7 @@ public function testCreateFromRouteThrowsNotString() public function testCreateFromRouteThrowsInvalidType() { - $this->config->routes['invalid'] = ['filthyflarmflam']; + $this->assets->routes['invalid'] = ['filthyflarmflam']; $this->expectException(AssetsException::class); $this->expectExceptionMessage(lang('Assets.invalidConfigItem', [''])); diff --git a/tests/_support/AssetsTestCase.php b/tests/_support/AssetsTestCase.php deleted file mode 100644 index 221ae54..0000000 --- a/tests/_support/AssetsTestCase.php +++ /dev/null @@ -1,30 +0,0 @@ -config = config('Assets'); - $this->config->directory = SUPPORTPATH . 'Files/'; - $this->config->vendor = 'external/'; - $this->config->useTimestamps = false; // These make testing much harder - - Asset::useConfig($this->config); - } -} diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php new file mode 100644 index 0000000..466fa18 --- /dev/null +++ b/tests/_support/TestCase.php @@ -0,0 +1,30 @@ +assets = config('Assets'); + $this->assets->directory = SUPPORTPATH . 'Files/'; + $this->assets->vendor = 'external/'; + $this->assets->useTimestamps = false; // These make testing much harder + + Asset::useConfig($this->assets); + } +} From 50affbe59dff15987a80963aef69f93d6407e66d Mon Sep 17 00:00:00 2001 From: MGatner Date: Mon, 3 Jan 2022 01:23:38 +0000 Subject: [PATCH 2/6] Improve refresh accuracy --- src/Test/AssetsTestTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Test/AssetsTestTrait.php b/src/Test/AssetsTestTrait.php index cdab0a2..67f8992 100644 --- a/src/Test/AssetsTestTrait.php +++ b/src/Test/AssetsTestTrait.php @@ -40,7 +40,7 @@ trait AssetsTestTrait */ protected function setUpAssetsTestTrait(): void { - if (self::$root === null) { + if (! empty($this->refreshVfs) || self::$root === null) { self::$root = vfsStream::setup('root'); } From a16ca920732b72a72ffeabdca1f0d14f2bb553f1 Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 3 Feb 2022 14:48:50 +0000 Subject: [PATCH 3/6] Switch to CodeIgniter Dev Kit --- .github/workflows/compare.yml | 29 ---- .github/workflows/deduplicate.yml | 39 ------ .../workflows/{inspect.yml => deptrac.yml} | 49 +++---- .github/workflows/infection.yml | 73 ++++++++++ .github/workflows/phpcpd.yml | 36 +++++ .github/workflows/phpcsfixer.yml | 61 +++++++++ .../workflows/{analyze.yml => phpstan.yml} | 47 +++---- .github/workflows/{test.yml => phpunit.yml} | 51 +++---- .github/workflows/rector.yml | 68 ++++++++++ .github/workflows/unused.yml | 44 +++--- .php-cs-fixer.dist.php | 5 +- composer.json | 19 +-- depfile.yaml | 5 +- infection.json.dist | 4 +- phpstan.neon.dist | 8 +- phpunit.xml.dist | 17 ++- rector.php | 125 ++++++++++++++++++ src/Asset.php | 19 +-- src/Bundle.php | 2 - src/Language/en/Assets.php | 2 + tests/AssetTest.php | 12 +- tests/BundleTest.php | 4 +- tests/FilterTest.php | 15 +-- tests/RouteBundleTest.php | 9 +- 24 files changed, 513 insertions(+), 230 deletions(-) delete mode 100644 .github/workflows/compare.yml delete mode 100644 .github/workflows/deduplicate.yml rename .github/workflows/{inspect.yml => deptrac.yml} (54%) create mode 100644 .github/workflows/infection.yml create mode 100644 .github/workflows/phpcpd.yml create mode 100644 .github/workflows/phpcsfixer.yml rename .github/workflows/{analyze.yml => phpstan.yml} (53%) rename .github/workflows/{test.yml => phpunit.yml} (62%) create mode 100644 .github/workflows/rector.yml create mode 100644 rector.php 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/deduplicate.yml b/.github/workflows/deduplicate.yml deleted file mode 100644 index 827bbbc..0000000 --- a/.github/workflows/deduplicate.yml +++ /dev/null @@ -1,39 +0,0 @@ -# When a PR is opened or a push is made, check code -# for duplication with PHP Copy/Paste Detector. -name: PHPCPD - -on: - pull_request: - branches: - - 'develop' - paths: - - 'app/**' - - 'src/**' - - 'tests/**' - - '.github/workflows/deduplicate.yml' - push: - branches: - - 'develop' - paths: - - 'app/**' - - 'src/**' - - 'tests/**' - - '.github/workflows/deduplicate.yml' - -jobs: - build: - name: Duplicate Code Detection - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - tools: phpcpd - extensions: dom, mbstring - - - name: Detect code duplication - run: phpcpd app/ src/ tests/ diff --git a/.github/workflows/inspect.yml b/.github/workflows/deptrac.yml similarity index 54% rename from .github/workflows/inspect.yml rename to .github/workflows/deptrac.yml index 23440fe..528cdc4 100644 --- a/.github/workflows/inspect.yml +++ b/.github/workflows/deptrac.yml @@ -1,41 +1,40 @@ -# When a PR is opened or a push is made, perform an -# architectural inspection on the code using Deptrac. name: Deptrac on: pull_request: branches: - - 'develop' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.php' - 'composer.**' - 'depfile.yaml' - - '.github/workflows/inspect.yml' + - '.github/workflows/deptrac.yml' push: branches: - - 'develop' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.php' - 'composer.**' - 'depfile.yaml' - - '.github/workflows/inspect.yml' + - '.github/workflows/deptrac.yml' jobs: build: - name: Architectural Inspection + name: Dependency Tracing runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + steps: - name: Checkout uses: actions/checkout@v2 - - name: Setup PHP + - name: Set up PHP uses: shivammathur/setup-php@v2 with: php-version: '8.0' - tools: composer, pecl, phive + tools: phive extensions: intl, json, mbstring, xml + coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -43,14 +42,11 @@ jobs: 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') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - name: Create Deptrac cache directory @@ -63,17 +59,16 @@ jobs: key: ${{ runner.os }}-deptrac-${{ github.sha }} restore-keys: ${{ runner.os }}-deptrac- - - 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: Install dependencies + run: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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 architectural inspection + - 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..2e5d05d --- /dev/null +++ b/.github/workflows/infection.yml @@ -0,0 +1,73 @@ +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@v2 + + - 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@v2 + 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: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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..2c9d209 --- /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@v2 + + - 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..6dd670f --- /dev/null +++ b/.github/workflows/phpcsfixer.yml @@ -0,0 +1,61 @@ +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@v2 + + - 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@v2 + 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: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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/analyze.yml b/.github/workflows/phpstan.yml similarity index 53% rename from .github/workflows/analyze.yml rename to .github/workflows/phpstan.yml index 12c48c1..38300b9 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/phpstan.yml @@ -1,35 +1,33 @@ -# 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' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.php' - 'composer.**' - 'phpstan*' - - '.github/workflows/analyze.yml' + - '.github/workflows/phpstan.yml' push: branches: - - 'develop' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.php' - 'composer.**' - 'phpstan*' - - '.github/workflows/analyze.yml' + - '.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.3', '7.4', '8.0'] + php-versions: ['7.4', '8.0', '8.1'] + steps: - name: Checkout uses: actions/checkout@v2 @@ -38,8 +36,9 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - tools: composer, pecl, phpunit - extensions: intl, json, mbstring, gd, mysqlnd, xdebug, xml, sqlite3 + tools: phpstan, phpunit + extensions: intl, json, mbstring, xml + coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -47,14 +46,11 @@ jobs: 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') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - name: Create PHPStan cache directory @@ -67,15 +63,14 @@ jobs: 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: Install dependencies + run: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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/test.yml b/.github/workflows/phpunit.yml similarity index 62% rename from .github/workflows/test.yml rename to .github/workflows/phpunit.yml index ce38955..e1ba40e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/phpunit.yml @@ -4,32 +4,39 @@ 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 - - strategy: - matrix: - php-versions: ['7.3', '7.4', '8.0'] - 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@v2 - - name: Setup PHP, with composer and extensions + - name: Set up PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - tools: composer, infection, pecl, phive, phpunit - extensions: intl, json, mbstring, gd, mysqlnd, xdebug, xml, sqlite3 + tools: composer, phive, phpunit + extensions: intl, json, mbstring, gd, xdebug, xml, sqlite3 coverage: xdebug env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -42,18 +49,17 @@ jobs: uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} 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: Install dependencies + run: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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 @@ -61,12 +67,6 @@ jobs: TERM: xterm-256color TACHYCARDIA_MONITOR_GA: enabled - - if: matrix.php-versions == '8.0' - 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 - - if: matrix.php-versions == '8.0' name: Run Coveralls continue-on-error: true @@ -85,6 +85,7 @@ jobs: 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..fff0208 --- /dev/null +++ b/.github/workflows/rector.yml @@ -0,0 +1,68 @@ +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@v2 + + - 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@v2 + 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: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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.10 + rector process --dry-run --no-progress-bar diff --git a/.github/workflows/unused.yml b/.github/workflows/unused.yml index 4d2ee36..30976ba 100644 --- a/.github/workflows/unused.yml +++ b/.github/workflows/unused.yml @@ -1,27 +1,27 @@ -# When a PR is opened or a push is made, check code -# for unused packages with Composer Unused. name: Unused on: pull_request: branches: - - 'develop' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.php' + - 'composer.**' - '.github/workflows/unused.yml' push: branches: - - 'develop' + - develop paths: - - 'src/**' - - 'tests/**' + - '**.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@v2 @@ -32,6 +32,7 @@ jobs: php-version: '8.0' tools: composer, composer-unused extensions: intl, json, mbstring, xml + coverage: none env: COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -43,18 +44,27 @@ jobs: uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} 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: Create PHPStan cache directory + run: mkdir -p build/phpstan - - 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: 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 + run: | + composer -q config -g github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}" + 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 --profile --ansi --no-interaction --no-progress --excludePackage=php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index dfa45af..1185b9c 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -6,7 +6,10 @@ $finder = Finder::create() ->files() - ->in(__DIR__) + ->in([ + __DIR__ . '/src/', + __DIR__ . '/tests/', + ]) ->exclude('build') ->append([__FILE__]); diff --git a/composer.json b/composer.json index e99ec28..00b6c90 100644 --- a/composer.json +++ b/composer.json @@ -21,11 +21,16 @@ } ], "require": { - "php": "^7.3 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { - "codeigniter4/codeigniter4": "dev-develop", - "tatter/tools": "^1.15" + "codeigniter4/devkit": "^1.0", + "codeigniter4/framework": "^4.1" + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } }, "autoload": { "psr-4": { @@ -40,12 +45,6 @@ "Tests\\Support\\": "tests/_support" } }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/codeigniter4/CodeIgniter4" - } - ], "minimum-stability": "dev", "prefer-stable": true, "scripts": { @@ -56,11 +55,13 @@ "@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", + "retool": "retool", "style": "php-cs-fixer fix --verbose --ansi --using-cache=no", "test": "phpunit" } diff --git a/depfile.yaml b/depfile.yaml index 4ca1cc7..08efb4b 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -1,7 +1,6 @@ paths: - - ./src - - ./vendor/codeigniter4/codeigniter4/system - - ./vendor/tatter + - ./src/ + - ./vendor/codeigniter4/framework/system/ exclude_files: - '#.*test.*#i' layers: 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 0cded0c..1464e02 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,10 +2,10 @@ parameters: tmpDir: build/phpstan level: 5 paths: - - src - - tests + - src/ + - tests/ bootstrapFiles: - - vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php + - vendor/codeigniter4/framework/system/Test/bootstrap.php excludePaths: - src/Config/Routes.php - src/Views/* @@ -16,7 +16,7 @@ parameters: - 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 a417466..ac88cfc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ - ./src + ./src/ + ./src/Config ./src/Views - ./src/Config/Filters.php - ./src/Config/Routes.php @@ -38,7 +37,7 @@ - + ./tests @@ -75,16 +74,16 @@ - + - + - + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..fab090d --- /dev/null +++ b/rector.php @@ -0,0 +1,125 @@ +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); +}; diff --git a/src/Asset.php b/src/Asset.php index 932d193..f9a4815 100644 --- a/src/Asset.php +++ b/src/Asset.php @@ -29,24 +29,17 @@ final class Asset 'webp', ]; - /** - * @var AssetsConfig|null - */ - private static $config; + private static ?AssetsConfig $config = null; /** * Asset content, ready for injection. - * - * @var string */ - private $tag; + private string $tag; /** * Whether the content should be placed in the head tag. - * - * @var bool */ - private $head; + private bool $head; //-------------------------------------------------------------------- // Configuration @@ -123,11 +116,7 @@ public static function createFromUri(string $uri, ?string $type = null): self $extension = pathinfo(strtok($uri, '?'), PATHINFO_EXTENSION); // Query safe // Check for one of the numerous image extension - if (in_array($extension, self::IMAGE_EXTENSIONS, true)) { - $type = 'img'; - } else { - $type = $extension; - } + $type = in_array($extension, self::IMAGE_EXTENSIONS, true) ? 'img' : $extension; } if ($type === 'css') { diff --git a/src/Bundle.php b/src/Bundle.php index 974e7ad..54912ab 100644 --- a/src/Bundle.php +++ b/src/Bundle.php @@ -106,8 +106,6 @@ final public function add(Asset $asset) /** * Merges Assets from another Bundle. * - * @param self $bundle - * * @return $this */ final public function merge(Bundle $bundle) diff --git a/src/Language/en/Assets.php b/src/Language/en/Assets.php index 4a2447b..06740f5 100644 --- a/src/Language/en/Assets.php +++ b/src/Language/en/Assets.php @@ -1,5 +1,7 @@ 'Unsupported file type: "{0}"', 'invalidConfigItem' => 'Invalid item detected in config: {0}', diff --git a/tests/AssetTest.php b/tests/AssetTest.php index c148f67..437629f 100644 --- a/tests/AssetTest.php +++ b/tests/AssetTest.php @@ -51,7 +51,7 @@ public function testUseTimestamps() $this->assets->useTimestamps = true; $mtime = filemtime($this->assets->directory . 'apple.css'); - $expected = ''; + $expected = ''; $asset = Asset::createFromPath('apple.css'); $this->assertInstanceOf(Asset::class, $asset); @@ -60,7 +60,7 @@ public function testUseTimestamps() public function testCreateFromPath() { - $expected = ''; + $expected = ''; $asset = Asset::createFromPath('apple.css'); $this->assertInstanceOf(Asset::class, $asset); @@ -89,8 +89,8 @@ public function testCreateFromUriImg() public function testCreateFromUriJs() { - $expected = ''; - $asset = Asset::createFromUri('http://banana.com/index.js'); + $expected = ''; + $asset = Asset::createFromUri('https://banana.com/index.js'); $this->assertInstanceOf(Asset::class, $asset); $this->assertSame($expected, (string) $asset); @@ -99,7 +99,7 @@ public function testCreateFromUriJs() public function testCreateFromUriWithExtension() { - $expected = 'Fruit'; + $expected = 'Fruit'; $asset = Asset::createFromUri('fruit', 'img'); $this->assertInstanceOf(Asset::class, $asset); @@ -112,6 +112,6 @@ public function testCreateFromUriThrows() $this->expectException(AssetsException::class); $this->expectExceptionMessage(lang('Assets.unsupportedType', ['exe'])); - $asset = Asset::createFromUri('fruit', 'exe'); + Asset::createFromUri('fruit', 'exe'); } } diff --git a/tests/BundleTest.php b/tests/BundleTest.php index d16d3da..9ac8df3 100644 --- a/tests/BundleTest.php +++ b/tests/BundleTest.php @@ -55,7 +55,7 @@ public function testStringable() protected $paths = ['apple.css']; }; - $this->assertSame('', (string) $asset); + $this->assertSame('', (string) $asset); } public function testHead() @@ -67,7 +67,7 @@ public function testHead() ]; }; - $this->assertSame('', $asset->head()); + $this->assertSame('', $asset->head()); } public function testSerializing() diff --git a/tests/FilterTest.php b/tests/FilterTest.php index e66b764..92e7f1d 100644 --- a/tests/FilterTest.php +++ b/tests/FilterTest.php @@ -15,10 +15,7 @@ final class FilterTest extends TestCase { use FilterTestTrait; - /** - * @var string - */ - private $body = <<<'EOD' + private string $body = <<<'EOD' Test @@ -54,12 +51,12 @@ public function testFilter() Test - +

Hello

- + EOD; @@ -79,14 +76,14 @@ public function testFilterWithArguments() Test - +

Hello

- - + + EOD; diff --git a/tests/RouteBundleTest.php b/tests/RouteBundleTest.php index 3d77ab5..519d220 100644 --- a/tests/RouteBundleTest.php +++ b/tests/RouteBundleTest.php @@ -31,10 +31,10 @@ public function testCreateFromRoute() { $expected = <<<'EOD' - - + + - + EOD; $result = RouteBundle::createFromRoute('admin/foo'); @@ -67,7 +67,7 @@ public function testCreateFromRouteSavesToCache() $this->assets->useCache = true; $this->assertEmpty(cache()->getCacheInfo()); - $result = RouteBundle::createFromRoute('foo'); + RouteBundle::createFromRoute('foo'); $this->assertNotEmpty(cache()->getCacheInfo()); } @@ -84,7 +84,6 @@ public function testCreateFromRouteEmpty() public function testCreateFromRouteThrowsNotString() { - // @phpstan-ignore-next-line $this->assets->routes['invalid'] = [true]; $this->expectException('InvalidArgumentException'); From 9d8e43dd11d30e723fe514fedb03b968423a83c3 Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 3 Feb 2022 14:53:04 +0000 Subject: [PATCH 4/6] Apply property types --- UPGRADING.md | 2 ++ src/Bundle.php | 10 +++++----- src/Config/Assets.php | 22 ++++++---------------- src/Test/AssetsTestTrait.php | 13 +++---------- tests/BundleTest.php | 20 ++++++++++---------- tests/_support/Bundles/FruitSalad.php | 2 +- tests/_support/Bundles/LunchBreak.php | 4 ++-- tests/_support/TestCase.php | 5 +---- 8 files changed, 30 insertions(+), 48 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 62b9995..1e9ca7f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -5,6 +5,8 @@ > Note: This is a complete refactor! Please be sure to read the docs carefully before upgrading. +* Minimum PHP version has been bumped to `7.4` to match the upcoming framework changes +* All properties that can be typed have been * The services no longer exist; remove all references to `Services::Assets` and `Services::manifests` to avoid exceptions * This library no longer publishes Assets; convert Manifests to the framework's new [Publisher format](https://codeigniter.com/user_guide/libraries/publisher.html) * Many of the example Manifests now have an official Publisher equivalent at [Tatter\Frontend](https://github.com/tattersoftware/codeigniter4-frontend) diff --git a/src/Bundle.php b/src/Bundle.php index 54912ab..297a9d2 100644 --- a/src/Bundle.php +++ b/src/Bundle.php @@ -23,35 +23,35 @@ abstract class Bundle * * @var Asset[] */ - protected $assets = []; + protected array $assets = []; /** * Bundle classes to merge with this Bundle. * * @var string[] */ - protected $bundles = []; + protected array $bundles = []; /** * Paths to include in this Bundle. * * @var string[] */ - protected $paths = []; + protected array $paths = []; /** * URIs to include in this Bundle. * * @var string[] */ - protected $uris = []; + protected array $uris = []; /** * Strings to include in this Bundle. * * @var string[] */ - protected $strings = []; + protected array $strings = []; //-------------------------------------------------------------------- // Asset Handling diff --git a/src/Config/Assets.php b/src/Config/Assets.php index 78c83dd..47cf438 100644 --- a/src/Config/Assets.php +++ b/src/Config/Assets.php @@ -14,42 +14,32 @@ class Assets extends BaseConfig /** * Asset URI base, relative to baseURL. - * - * @var string */ - public $uri = 'assets/'; + public string $uri = 'assets/'; /** * Asset storage location in the filesystem. * Must be somewhere web accessible. - * - * @var string */ - public $directory = FCPATH . 'assets/'; + public string $directory = FCPATH . 'assets/'; /** * Path for third-party published Assets. The path is relative to * both $directory and $uri. Recommended to add the resulting file * path to .gitignore so published vendor assets will not be tracked. - * - * @var string */ - public $vendor = 'vendor/'; + public string $vendor = 'vendor/'; /** * Whether to append file modification timestamps on asset tags. * Makes it less likely for modified assets to remain cached. - * - * @var bool */ - public $useTimestamps = true; + public bool $useTimestamps = true; /** * Whether to cache bundles for faster route responses. - * - * @var bool */ - public $useCache = ENVIRONMENT === 'production'; + public bool $useCache = ENVIRONMENT === 'production'; //-------------------------------------------------------------------- // Route Assets @@ -77,7 +67,7 @@ class Assets extends BaseConfig * * @var array */ - public $routes = []; + public array $routes = []; /** * Gathers Assets and Bundles that match the relative URI path. diff --git a/src/Test/AssetsTestTrait.php b/src/Test/AssetsTestTrait.php index 67f8992..164e97b 100644 --- a/src/Test/AssetsTestTrait.php +++ b/src/Test/AssetsTestTrait.php @@ -18,22 +18,15 @@ trait AssetsTestTrait { /** * The virtual workspace. - * - * @var vfsStreamDirectory|null */ - protected static $root; + protected static ?vfsStreamDirectory $root = null; /** * Whether the publishers have been run. - * - * @var bool */ - private static $published = false; + private static bool $published = false; - /** - * @var AssetsConfig - */ - protected $assets; + protected AssetsConfig $assets; /** * Creates the VFS (if necessary) and updates the Assets config. diff --git a/tests/BundleTest.php b/tests/BundleTest.php index 9ac8df3..5ad2080 100644 --- a/tests/BundleTest.php +++ b/tests/BundleTest.php @@ -12,8 +12,8 @@ final class BundleTest extends TestCase { public function testConstructorPaths() { - $bundle = new class () extends Bundle { - protected $paths = ['apple.css']; + $bundle = new class () extends Bundle { + protected array $paths = ['apple.css']; }; $assets = $bundle->getAssets(); @@ -25,8 +25,8 @@ public function testConstructorPaths() public function testConstructorBundles() { - $bundle = new class () extends Bundle { - protected $bundles = [FruitSalad::class]; + $bundle = new class () extends Bundle { + protected array $bundles = [FruitSalad::class]; }; $assets = $bundle->getAssets(); @@ -38,8 +38,8 @@ public function testConstructorBundles() public function testConstructorStrings() { - $bundle = new class () extends Bundle { - protected $strings = ['foobar']; + $bundle = new class () extends Bundle { + protected array $strings = ['foobar']; }; $assets = $bundle->getAssets(); @@ -51,8 +51,8 @@ public function testConstructorStrings() public function testStringable() { - $asset = new class () extends Bundle { - protected $paths = ['apple.css']; + $asset = new class () extends Bundle { + protected array $paths = ['apple.css']; }; $this->assertSame('', (string) $asset); @@ -60,8 +60,8 @@ public function testStringable() public function testHead() { - $asset = new class () extends Bundle { - protected $paths = [ + $asset = new class () extends Bundle { + protected array $paths = [ 'apple.css', 'banana.js', ]; diff --git a/tests/_support/Bundles/FruitSalad.php b/tests/_support/Bundles/FruitSalad.php index 93993bf..1478572 100644 --- a/tests/_support/Bundles/FruitSalad.php +++ b/tests/_support/Bundles/FruitSalad.php @@ -11,7 +11,7 @@ class FruitSalad extends Bundle * * @var string[] */ - protected $paths = [ + protected array $paths = [ 'apple.css', 'banana.js', ]; diff --git a/tests/_support/Bundles/LunchBreak.php b/tests/_support/Bundles/LunchBreak.php index 4ca7cc3..260fe18 100644 --- a/tests/_support/Bundles/LunchBreak.php +++ b/tests/_support/Bundles/LunchBreak.php @@ -11,7 +11,7 @@ class LunchBreak extends Bundle * * @var string[] */ - protected $paths = [ + protected array $paths = [ 'banana.js', 'directory/machines.js', ]; @@ -21,7 +21,7 @@ class LunchBreak extends Bundle * * @var string[] */ - protected $uris = [ + protected array $uris = [ 'https://water.com/glassof.css', ]; } diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index 466fa18..1221f94 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -8,10 +8,7 @@ abstract class TestCase extends CIUnitTestCase { - /** - * @var AssetsConfig - */ - protected $assets; + protected AssetsConfig $assets; /** * Preps the config for the test directory. From 11e57c751a5ba1fc46999e993a5da8950dbd482a Mon Sep 17 00:00:00 2001 From: MGatner Date: Thu, 3 Feb 2022 15:18:13 +0000 Subject: [PATCH 5/6] Fix workflows --- .github/workflows/unused.yml | 2 +- rector.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unused.yml b/.github/workflows/unused.yml index 30976ba..0e7718c 100644 --- a/.github/workflows/unused.yml +++ b/.github/workflows/unused.yml @@ -67,4 +67,4 @@ jobs: fi - name: Detect unused packages - run: composer-unused -vvv --profile --ansi --no-interaction --no-progress --excludePackage=php + run: composer-unused -vvv --ansi --no-interaction --no-progress --excludePackage=php diff --git a/rector.php b/rector.php index fab090d..10f5b93 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/Views', + __DIR__ . '/src/Config/Filters.php', JsonThrowOnErrorRector::class, StringifyStrNeedlesRector::class, From 47af88ccc9507aabf090039193aee9be67772ca8 Mon Sep 17 00:00:00 2001 From: Craig A Rodway Date: Fri, 11 Feb 2022 16:40:41 +0000 Subject: [PATCH 6/6] Fix backslash URI suffix on Windows Changed `$config->uri` to end with literal '/' instead of using DIRECTORY_SEPARATOR constant. --- src/Asset.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Asset.php b/src/Asset.php index f9a4815..d127114 100644 --- a/src/Asset.php +++ b/src/Asset.php @@ -54,7 +54,7 @@ public static function config(): AssetsConfig self::$config = config(AssetsConfig::class); // Standardize formats - self::$config->uri = rtrim(self::$config->uri, '/\\') . DIRECTORY_SEPARATOR; + self::$config->uri = rtrim(self::$config->uri, '/\\') . '/'; self::$config->directory = rtrim(self::$config->directory, '/\\') . DIRECTORY_SEPARATOR; self::$config->vendor = rtrim(self::$config->vendor, '/\\') . DIRECTORY_SEPARATOR; }