diff --git a/.editorconfig b/.editorconfig index 23a7072c587b..53faf5c3beac 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,8 @@ root = true end_of_line = lf [*.php] -indent_style = tab +indent_style = space +indent_size = 4 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true diff --git a/.gitattributes b/.gitattributes index 1a7b3deb77e8..bf0e1f766d96 100644 --- a/.gitattributes +++ b/.gitattributes @@ -25,6 +25,7 @@ utils/ export-ignore rector.php export-ignore phpunit.xml.dist export-ignore phpstan.neon.dist export-ignore +.php-cs-fixer.dist.php export-ignore # The source user guide, either user_guide_src/ export-ignore diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6532121074ad..d3afefe5c9fd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,13 +1,18 @@ version: 2 + updates: -- package-ecosystem: composer - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 + - package-ecosystem: 'composer' + directory: '/' + schedule: + interval: 'daily' + open-pull-requests-limit: 10 -- package-ecosystem: "github-actions" - directory: "/" - schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'daily' + ignore: + - dependency-name: '*' + update-types: + - 'version-update:semver-minor' + - 'version-update:semver-patch' diff --git a/.github/workflows/deploy-apidocs.yml b/.github/workflows/deploy-apidocs.yml index 393adaf7c277..3b441e36485d 100644 --- a/.github/workflows/deploy-apidocs.yml +++ b/.github/workflows/deploy-apidocs.yml @@ -1,6 +1,6 @@ # When changes are pushed to the develop branch, # build the current version of the API documentation -# with phpDocumentor and deploy it to the api branch. +# with phpDocumentor and deploy it to codeigniter4/api. name: Deploy API Documentation on: @@ -9,13 +9,14 @@ on: - 'develop' paths: - 'system/**' + - '.github/workflows/deploy-apidocs.yml' jobs: - build: name: Deploy to api - if: (github.repository == 'codeigniter4/CodeIgniter4') - runs-on: ubuntu-latest + if: github.repository == 'codeigniter4/CodeIgniter4' + runs-on: ubuntu-20.04 + steps: - name: Setup credentials run: | @@ -37,37 +38,34 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' - extensions: intl + php-version: '8.0' + coverage: none - - name: Install GraphViz for phpDocumentor - run: | - sudo apt install -yq graphviz - - - name: Download phpDocumentor + - name: Download phpDocumentor v3.1 run: | cd ./source curl \ - -L https://github.com/phpDocumentor/phpDocumentor/releases/download/v2.9.1/phpDocumentor.phar \ + -L https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.1.0/phpDocumentor.phar \ -o admin/phpDocumentor.phar - - name: Prepare + - name: Prepare API repo + working-directory: api run: | - cd ./api - rm -rf ./api/docs* - mkdir -p ./api/docs git reset --hard master + rm -rfv docs + mkdir --parents --verbose docs - - name: Build + - name: Build API in source repo + working-directory: source run: | - cd ./source - chmod +x admin/phpDocumentor.phar - admin/phpDocumentor.phar + php admin/phpDocumentor.phar run --ansi --verbose cp -R ${GITHUB_WORKSPACE}/source/api/build/* ${GITHUB_WORKSPACE}/api/docs - - name: Deploy + - name: Deploy to API repo + working-directory: api run: | - cd ./api git add . - git commit -m "API sync for ${GITHUB_SHA}" - git push + if ! git diff-index --quiet HEAD; then + git commit -m "Updated API for commit ${GITHUB_SHA}" + git push origin master + fi diff --git a/.github/workflows/deploy-framework.yml b/.github/workflows/deploy-framework.yml index fff563878b2e..226cf242ed59 100644 --- a/.github/workflows/deploy-framework.yml +++ b/.github/workflows/deploy-framework.yml @@ -9,7 +9,7 @@ on: jobs: framework: name: Deploy to framework - if: (github.repository == 'codeigniter4/CodeIgniter4') + if: github.repository == 'codeigniter4/CodeIgniter4' runs-on: ubuntu-latest steps: - name: Identify @@ -36,7 +36,7 @@ jobs: run: ./source/.github/scripts/deploy-framework ${GITHUB_WORKSPACE}/source ${GITHUB_WORKSPACE}/framework ${GITHUB_REF##*/} - name: Release - uses: actions/github-script@v4.0.2 + uses: actions/github-script@v4 with: github-token: ${{secrets.ACCESS_TOKEN}} script: | @@ -54,7 +54,7 @@ jobs: appstarter: name: Deploy to appstarter - if: (github.repository == 'codeigniter4/CodeIgniter4') + if: github.repository == 'codeigniter4/CodeIgniter4' runs-on: ubuntu-latest steps: - name: Identify @@ -81,7 +81,7 @@ jobs: run: ./source/.github/scripts/deploy-appstarter ${GITHUB_WORKSPACE}/source ${GITHUB_WORKSPACE}/appstarter ${GITHUB_REF##*/} - name: Release - uses: actions/github-script@v4.0.2 + uses: actions/github-script@v4 with: github-token: ${{secrets.ACCESS_TOKEN}} script: | diff --git a/.github/workflows/test-coding-standards.yml b/.github/workflows/test-coding-standards.yml new file mode 100644 index 000000000000..cb7d9671e2cd --- /dev/null +++ b/.github/workflows/test-coding-standards.yml @@ -0,0 +1,59 @@ +name: Coding Standards + +on: + push: + paths: + - '**.php' + - 'spark' + - '.github/workflows/test-coding-standards.yml' + pull_request: + paths: + - '**.php' + - 'spark' + - '.github/workflows/test-coding-standards.yml' + +jobs: + lint: + name: PHP ${{ matrix.php-version }} Lint with PHP CS Fixer + runs-on: ubuntu-20.04 + + strategy: + fail-fast: false + matrix: + php-version: + - '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-version }} + extensions: tokenizer + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.php-version }}- + ${{ runner.os }}- + + - name: Install dependencies + run: composer update --ansi --no-interaction + + - name: Run lint on `app/`, `admin/`, `public/` + run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --config=.no-header.php-cs-fixer.dist.php --using-cache=no --diff + + - name: Run lint on `system/`, `tests`, `utils/`, and root PHP files + run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff diff --git a/.github/workflows/test-phpcpd.yml b/.github/workflows/test-phpcpd.yml new file mode 100644 index 000000000000..fcc66f7d682c --- /dev/null +++ b/.github/workflows/test-phpcpd.yml @@ -0,0 +1,43 @@ +# 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' + - '4.*' + paths: + - 'app/**' + - 'public/**' + - 'system/**' + - '.github/workflows/test-phpcpd.yml' + push: + branches: + - 'develop' + - '4.*' + paths: + - 'app/**' + - 'public/**' + - 'system/**' + - '.github/workflows/test-phpcpd.yml' + +jobs: + build: + name: Duplicate Code Detection + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: phive + extensions: intl, json, mbstring, xml + + - name: Detect code duplication + run: | + sudo phive --no-progress install --global --trust-gpg-keys 4AA394086372C20A phpcpd + phpcpd --exclude system/Test --exclude system/ThirdParty --exclude system/Database/SQLSRV/Builder.php app/ public/ system/ diff --git a/.github/workflows/test-phpstan.yml b/.github/workflows/test-phpstan.yml index 86b68b058ea1..0e59e3bf4e3a 100644 --- a/.github/workflows/test-phpstan.yml +++ b/.github/workflows/test-phpstan.yml @@ -54,7 +54,7 @@ jobs: run: mkdir -p ${{ steps.composer-cache.outputs.dir }} - name: Cache composer dependencies - uses: actions/cache@v2.1.5 + uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} @@ -64,7 +64,7 @@ jobs: run: mkdir -p build/phpstan - name: Cache PHPStan result cache directory - uses: actions/cache@v2.1.5 + uses: actions/cache@v2 with: path: build/phpstan key: ${{ runner.os }}-phpstan-${{ github.sha }} diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index 1b547fb76884..c093190233cb 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -44,9 +44,9 @@ jobs: db-platforms: ['MySQLi', 'Postgre', 'SQLite3', 'SQLSRV'] mysql-versions: ['5.7'] include: - - php-versions: 7.4 + - php-versions: '7.4' db-platforms: MySQLi - mysql-versions: 8.0 + mysql-versions: '8.0' services: mysql: @@ -107,13 +107,14 @@ jobs: run: | sudo apt-get install --reinstall libgs9-common fonts-noto-mono libgs9:amd64 libijs-0.35:amd64 fonts-urw-base35 ghostscript poppler-data libjbig2dec0:amd64 gsfonts libopenjp2-7:amd64 fonts-droid-fallback ttf-dejavu-core sudo apt-get install -y imagemagick + sudo apt-get install --fix-broken - name: Get composer cache directory id: composercache run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache dependencies - uses: actions/cache@v2.1.5 + uses: actions/cache@v2 with: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} @@ -122,7 +123,7 @@ jobs: - name: Install dependencies run: | composer update --ansi --no-interaction - composer remove --ansi --dev --unused -W rector/rector phpstan/phpstan codeigniter4/codeigniter4-standard squizlabs/php_codesniffer + composer remove --ansi --dev --unused -W rector/rector phpstan/phpstan friendsofphp/php-cs-fixer nexusphp/cs-config codeigniter/coding-standard php -r 'file_put_contents("vendor/laminas/laminas-zendframework-bridge/src/autoload.php", "");' env: COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }} @@ -140,7 +141,7 @@ jobs: - if: github.repository_owner == 'codeigniter4' && matrix.php-versions == '7.4' name: Run Coveralls run: | - composer global require php-coveralls/php-coveralls:^2.4 + composer global require --ansi php-coveralls/php-coveralls:^2.4 php-coveralls --coverage_clover=build/logs/clover.xml -v env: COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-rector.yml b/.github/workflows/test-rector.yml index e1420c965f37..0d7262ceb4ea 100644 --- a/.github/workflows/test-rector.yml +++ b/.github/workflows/test-rector.yml @@ -58,7 +58,7 @@ jobs: run: mkdir -p ${{ steps.composer-cache.outputs.dir }} - name: Cache composer dependencies - uses: actions/cache@v2.1.5 + uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} diff --git a/.gitignore b/.gitignore index b769053b4a4b..74c6d0ce6c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -126,3 +126,5 @@ nb-configuration.xml /results/ /phpunit*.xml /.phpunit.*.cache + +/.php-cs-fixer.php diff --git a/.no-header.php-cs-fixer.dist.php b/.no-header.php-cs-fixer.dist.php new file mode 100644 index 000000000000..12acddb81087 --- /dev/null +++ b/.no-header.php-cs-fixer.dist.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use CodeIgniter\CodingStandard\CodeIgniter4; +use Nexus\CsConfig\Factory; +use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; +use Nexus\CsConfig\Fixer\Comment\SpaceAfterCommentStartFixer; +use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\Finder; + +$finder = Finder::create() + ->files() + ->in([ + __DIR__ . '/admin', + __DIR__ . '/app', + __DIR__ . '/public', + ]) + ->notName('#Logger\.php$#'); + +$overrides = []; + +$options = [ + 'cacheFile' => 'build/.no-header.php-cs-fixer.cache', + 'finder' => $finder, + 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), + 'customRules' => [ + NoCodeSeparatorCommentFixer::name() => true, + SpaceAfterCommentStartFixer::name() => true, + ], +]; + +return Factory::create(new CodeIgniter4(), $overrides, $options)->forProjects(); diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 000000000000..3c9e05fe3b74 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use CodeIgniter\CodingStandard\CodeIgniter4; +use Nexus\CsConfig\Factory; +use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; +use Nexus\CsConfig\Fixer\Comment\SpaceAfterCommentStartFixer; +use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\Finder; + +$finder = Finder::create() + ->files() + ->in([ + __DIR__ . '/system', + __DIR__ . '/tests', + __DIR__ . '/utils', + ]) + ->exclude(['ThirdParty']) + ->notName('#Foobar.php$#') + ->append([ + __FILE__, + __DIR__ . '/.no-header.php-cs-fixer.dist.php', + __DIR__ . '/rector.php', + __DIR__ . '/spark', + ]); + +$overrides = []; + +$options = [ + 'cacheFile' => 'build/.php-cs-fixer.cache', + 'finder' => $finder, + 'customFixers' => FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer'), + 'customRules' => [ + NoCodeSeparatorCommentFixer::name() => true, + SpaceAfterCommentStartFixer::name() => true, + ], +]; + +return Factory::create(new CodeIgniter4(), $overrides, $options)->forLibrary( + 'CodeIgniter 4 framework', + 'CodeIgniter Foundation', + 'admin@codeigniter.com' +); diff --git a/CHANGELOG.md b/CHANGELOG.md index 86777d7fccab..74513d243589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,15 @@ # Changelog -## [Unreleased](https://github.com/codeigniter4/CodeIgniter4/tree/HEAD) +## [v4.1.4](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.4) (2021-09-06) -[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.2...HEAD) +This release focuses on code style. All changes (except those noted below) are cosmetic to bring the code in line with the new +[CodeIgniter Coding Standard](https://github.com/CodeIgniter/coding-standard) (based on PSR-12). + +*Note: Full changelog forthcoming.* + +## [v4.1.3](https://github.com/codeigniter4/CodeIgniter4/tree/v4.1.3) (2021-06-06) + +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.1.2...v4.1.3) **Fixed bugs:** diff --git a/admin/framework/composer.json b/admin/framework/composer.json index e5e88487cfe6..6e3852d2af79 100644 --- a/admin/framework/composer.json +++ b/admin/framework/composer.json @@ -1,47 +1,48 @@ { - "name": "codeigniter4/framework", - "type": "project", - "description": "The CodeIgniter framework v4", - "homepage": "https://codeigniter.com", - "license": "MIT", - "require": { - "php": "^7.3||^8.0", - "ext-curl": "*", - "ext-intl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "kint-php/kint": "^3.3", - "laminas/laminas-escaper": "^2.6", - "psr/log": "^1.1" - }, - "require-dev": { - "codeigniter4/codeigniter4-standard": "^1.0", - "fakerphp/faker": "^1.9", - "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "^9.1", - "predis/predis": "^1.1", - "squizlabs/php_codesniffer": "^3.3" - }, - "suggest": { - "ext-fileinfo": "Improves mime type detection for files" - }, - "autoload": { - "psr-4": { - "CodeIgniter\\": "system/" - }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] - }, - "scripts": { - "post-update-cmd": [ - "CodeIgniter\\ComposerScripts::postUpdate" - ], - "test": "phpunit" - }, - "support": { - "forum": "http://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" - } + "name": "codeigniter4/framework", + "type": "project", + "description": "The CodeIgniter framework v4", + "homepage": "https://codeigniter.com", + "license": "MIT", + "require": { + "php": "^7.3 || ^8.0", + "ext-curl": "*", + "ext-intl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "kint-php/kint": "^3.3", + "laminas/laminas-escaper": "^2.8", + "psr/log": "^1.1" + }, + "require-dev": { + "codeigniter/coding-standard": "^1.1", + "fakerphp/faker": "^1.9", + "friendsofphp/php-cs-fixer": "^3.1", + "mikey179/vfsstream": "^1.6", + "nexusphp/cs-config": "^3.3", + "phpunit/phpunit": "^9.1", + "predis/predis": "^1.1" + }, + "suggest": { + "ext-fileinfo": "Improves mime type detection for files" + }, + "autoload": { + "psr-4": { + "CodeIgniter\\": "system/" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "scripts": { + "post-update-cmd": [ + "CodeIgniter\\ComposerScripts::postUpdate" + ], + "test": "phpunit" + }, + "support": { + "forum": "http://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + } } diff --git a/admin/module/composer.json b/admin/module/composer.json index f2b85c785ad8..70197a43010c 100644 --- a/admin/module/composer.json +++ b/admin/module/composer.json @@ -1,38 +1,38 @@ { - "name": "mydomain/mymodule", - "description": "CodeIgniter4 starter module", - "homepage": "https://codeigniter.com", - "license": "MIT", - "require": { - "php": "^7.3||^8.0" - }, - "require-dev": { - "codeigniter4/codeigniter4": "dev-develop", - "fakerphp/faker": "^1.9", - "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "^9.1" - }, - "suggest": { - "ext-fileinfo": "Improves mime type detection for files" - }, - "autoload-dev": { - "psr-4": { - "Tests\\Support\\": "tests/_support" - } - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/codeigniter4/codeigniter4" - } - ], - "minimum-stability": "dev", - "scripts": { - "test": "phpunit" - }, - "support": { - "forum": "http://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" - } + "name": "mydomain/mymodule", + "description": "CodeIgniter4 starter module", + "homepage": "https://codeigniter.com", + "license": "MIT", + "require": { + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "codeigniter4/codeigniter4": "dev-develop", + "fakerphp/faker": "^1.9", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^9.1" + }, + "suggest": { + "ext-fileinfo": "Improves mime type detection for files" + }, + "autoload-dev": { + "psr-4": { + "Tests\\Support\\": "tests/_support" + } + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/codeigniter4/codeigniter4" + } + ], + "minimum-stability": "dev", + "scripts": { + "test": "phpunit" + }, + "support": { + "forum": "http://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + } } diff --git a/admin/module/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/admin/module/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php index 1bfd4a33c171..2bbdcfe51994 100644 --- a/admin/module/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php +++ b/admin/module/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -1,61 +1,37 @@ - [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'uid' => [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'class' => [ - 'type' => 'varchar', - 'constraint' => 63, - ], - 'icon' => [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'summary' => [ - 'type' => 'varchar', - 'constraint' => 255, - ], - 'created_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - 'updated_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - 'deleted_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - ]; + protected $DBGroup = 'tests'; - $this->forge->addField('id'); - $this->forge->addField($fields); + public function up() + { + $this->forge->addField('id'); + $this->forge->addField([ + 'name' => ['type' => 'varchar', 'constraint' => 31], + 'uid' => ['type' => 'varchar', 'constraint' => 31], + 'class' => ['type' => 'varchar', 'constraint' => 63], + 'icon' => ['type' => 'varchar', 'constraint' => 31], + 'summary' => ['type' => 'varchar', 'constraint' => 255], + 'created_at' => ['type' => 'datetime', 'null' => true], + 'updated_at' => ['type' => 'datetime', 'null' => true], + 'deleted_at' => ['type' => 'datetime', 'null' => true], + ]); - $this->forge->addKey('name'); - $this->forge->addKey('uid'); - $this->forge->addKey(['deleted_at', 'id']); - $this->forge->addKey('created_at'); + $this->forge->addKey('name'); + $this->forge->addKey('uid'); + $this->forge->addKey(['deleted_at', 'id']); + $this->forge->addKey('created_at'); - $this->forge->createTable('factories'); - } + $this->forge->createTable('factories'); + } - public function down() - { - $this->forge->dropTable('factories'); - } + public function down() + { + $this->forge->dropTable('factories'); + } } diff --git a/admin/module/tests/_support/Database/Seeds/ExampleSeeder.php b/admin/module/tests/_support/Database/Seeds/ExampleSeeder.php index 1b14cedaa2dc..f67bf8fb8cae 100644 --- a/admin/module/tests/_support/Database/Seeds/ExampleSeeder.php +++ b/admin/module/tests/_support/Database/Seeds/ExampleSeeder.php @@ -1,40 +1,41 @@ - 'Test Factory', - 'uid' => 'test001', - 'class' => 'Factories\Tests\NewFactory', - 'icon' => 'fas fa-puzzle-piece', - 'summary' => 'Longer sample text for testing', - ], - [ - 'name' => 'Widget Factory', - 'uid' => 'widget', - 'class' => 'Factories\Tests\WidgetPlant', - 'icon' => 'fas fa-puzzle-piece', - 'summary' => 'Create widgets in your factory', - ], - [ - 'name' => 'Evil Factory', - 'uid' => 'evil-maker', - 'class' => 'Factories\Evil\MyFactory', - 'icon' => 'fas fa-book-dead', - 'summary' => 'Abandon all hope, ye who enter here', - ], - ]; + public function run() + { + $factories = [ + [ + 'name' => 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Longer sample text for testing', + ], + [ + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Create widgets in your factory', + ], + [ + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', + 'summary' => 'Abandon all hope, ye who enter here', + ], + ]; - $builder = $this->db->table('factories'); + $builder = $this->db->table('factories'); - foreach ($factories as $factory) - { - $builder->insert($factory); - } - } + foreach ($factories as $factory) { + $builder->insert($factory); + } + } } diff --git a/admin/module/tests/_support/DatabaseTestCase.php b/admin/module/tests/_support/DatabaseTestCase.php index 9eb8fb703e90..fd067a585c87 100644 --- a/admin/module/tests/_support/DatabaseTestCase.php +++ b/admin/module/tests/_support/DatabaseTestCase.php @@ -1,55 +1,61 @@ -mockSession(); - } + $this->mockSession(); + } - /** - * Pre-loads the mock session driver into $this->session. - * - * @var string - */ - protected function mockSession() - { - $config = config('App'); - $this->session = new MockSession(new ArrayHandler($config, '0.0.0.0'), $config); - \Config\Services::injectMock('session', $this->session); - } + /** + * Pre-loads the mock session driver into $this->session. + * + * @var string + */ + protected function mockSession() + { + $config = config('App'); + $this->session = new MockSession(new ArrayHandler($config, '0.0.0.0'), $config); + \Config\Services::injectMock('session', $this->session); + } } diff --git a/admin/module/tests/database/ExampleDatabaseTest.php b/admin/module/tests/database/ExampleDatabaseTest.php index 2de0b6ae01bf..203b1261c7e0 100644 --- a/admin/module/tests/database/ExampleDatabaseTest.php +++ b/admin/module/tests/database/ExampleDatabaseTest.php @@ -2,41 +2,44 @@ use Tests\Support\Models\ExampleModel; -class ExampleDatabaseTest extends \Tests\Support\DatabaseTestCase +/** + * @internal + */ +final class ExampleDatabaseTest extends \Tests\Support\DatabaseTestCase { - public function setUp(): void - { - parent::setUp(); + protected function setUp(): void + { + parent::setUp(); - // Extra code to run before each test - } + // Extra code to run before each test + } - public function testModelFindAll() - { - $model = new ExampleModel(); + public function testModelFindAll() + { + $model = new ExampleModel(); - // Get every row created by ExampleSeeder - $objects = $model->findAll(); + // Get every row created by ExampleSeeder + $objects = $model->findAll(); - // Make sure the count is as expected - $this->assertCount(3, $objects); - } + // Make sure the count is as expected + $this->assertCount(3, $objects); + } - public function testSoftDeleteLeavesRow() - { - $model = new ExampleModel(); - $this->setPrivateProperty($model, 'useSoftDeletes', true); - $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); + public function testSoftDeleteLeavesRow() + { + $model = new ExampleModel(); + $this->setPrivateProperty($model, 'useSoftDeletes', true); + $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); - $object = $model->first(); - $model->delete($object->id); + $object = $model->first(); + $model->delete($object->id); - // The model should no longer find it - $this->assertNull($model->find($object->id)); + // The model should no longer find it + $this->assertNull($model->find($object->id)); - // ... but it should still be in the database - $result = $model->builder()->where('id', $object->id)->get()->getResult(); + // ... but it should still be in the database + $result = $model->builder()->where('id', $object->id)->get()->getResult(); - $this->assertCount(1, $result); - } + $this->assertCount(1, $result); + } } diff --git a/admin/module/tests/session/ExampleSessionTest.php b/admin/module/tests/session/ExampleSessionTest.php index 6ec0d011bd8d..65dd37c6b498 100644 --- a/admin/module/tests/session/ExampleSessionTest.php +++ b/admin/module/tests/session/ExampleSessionTest.php @@ -1,18 +1,21 @@ session->set('logged_in', 123); + public function testSessionSimple() + { + $this->session->set('logged_in', 123); - $value = $this->session->get('logged_in'); + $value = $this->session->get('logged_in'); - $this->assertEquals(123, $value); - } + $this->assertSame(123, $value); + } } diff --git a/admin/module/tests/unit/ExampleTest.php b/admin/module/tests/unit/ExampleTest.php index 2bab3125452f..4306ddfe55d5 100644 --- a/admin/module/tests/unit/ExampleTest.php +++ b/admin/module/tests/unit/ExampleTest.php @@ -1,16 +1,19 @@ assertTrue($test); - } + $this->assertTrue($test); + } } diff --git a/admin/pre-commit b/admin/pre-commit index 94665c1ed4a5..d05724d58146 100644 --- a/admin/pre-commit +++ b/admin/pre-commit @@ -4,60 +4,75 @@ PROJECT=`php -r "echo dirname(dirname(dirname(realpath('$0'))));"` STAGED_FILES_CMD=`git diff --cached --name-only --diff-filter=ACMR HEAD | grep \\\\.php$` # Determine if a file list is passed -if [ "$#" -eq 1 ] -then - oIFS=$IFS - IFS=' - ' - SFILES="$1" - IFS=$oIFS +if [ "$#" -eq 1 ]; then + oIFS=$IFS + IFS=' + ' + SFILES="$1" + IFS=$oIFS fi + SFILES=${SFILES:-$STAGED_FILES_CMD} echo "Starting CodeIgniter precommit..." -if [ "$SFILES" != "" ] -then - echo "Linting PHP code..." - for FILE in $SFILES - do - php -l -d display_errors=0 "$PROJECT/$FILE" - if [ $? != 0 ] - then - echo "Fix the error(s) before commit." - exit 1 - fi - FILES="$FILES $FILE" - done +if [ "$SFILES" != "" ]; then + echo "Linting PHP code..." + for FILE in $SFILES; do + php -l -d display_errors=0 "$PROJECT/$FILE" + + if [ $? != 0 ]; then + echo "Fix the error(s) before commit." + exit 1 + fi + + FILES="$FILES $FILE" + done fi -if [ "$FILES" != "" ] -then - echo "Running PHPStan..." - # Run on whole codebase - if [ -d /proc/cygdrive ] - then - ./vendor/bin/phpstan analyse - else - php ./vendor/bin/phpstan analyse - fi - - if [ $? != 0 ] - then - echo "Fix the phpstan error(s) before commit." - exit 1 - fi +if [ "$FILES" != "" ]; then + echo "Running PHPStan..." + + # Run on whole codebase + if [ -d /proc/cygdrive ]; then + ./vendor/bin/phpstan analyse + else + php ./vendor/bin/phpstan analyse + fi + + if [ $? != 0 ]; then + echo "Fix the phpstan error(s) before commit." + exit 1 + fi fi -if [ "$FILES" != "" ] -then - echo "Running Code Sniffer..." - if [ -d /proc/cygdrive ] - then - ./vendor/bin/phpcbf --standard=./vendor/codeigniter4/codeigniter4-standard/CodeIgniter4 --encoding=utf-8 -n -p $FILES - else - php ./vendor/bin/phpcbf --standard=./vendor/codeigniter4/codeigniter4-standard/CodeIgniter4 --encoding=utf-8 -n -p $FILES - fi +if [ "$FILES" != "" ]; then + echo "Running PHP CS Fixer..." + + # Run on whole codebase to skip on unnecessary filtering + # Run first on app, admin, public + if [ -d /proc/cygdrive ]; then + ./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no --diff --config=.no-header.php-cs-fixer.dist.php + else + php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no --diff --config=.no-header.php-cs-fixer.dist.php + fi + + if [ $? != 0 ]; then + echo "Files in app, admin, or public are not following the coding standards. Please fix them before commit." + exit 1 + fi + + # Next, run on system, tests, utils, and root PHP files + if [ -d /proc/cygdrive ]; then + ./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no --diff + else + php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --using-cache=no --diff + fi + + if [ $? != 0 ]; then + echo "Files in system, tests, utils, or root are not following the coding standards. Please fix them before commit." + exit 1 + fi fi exit $? diff --git a/admin/setup.sh b/admin/setup.sh index 86254e8e8889..55adf547e4bd 100644 --- a/admin/setup.sh +++ b/admin/setup.sh @@ -1,7 +1,7 @@ #!/bin/sh # Install a pre-commit hook that -# automatically runs phpcs to fix styles +# automatically runs php-cs-fixer to lint code mkdir -p .git/hooks cp admin/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit diff --git a/admin/starter/app/Config/Paths.php b/admin/starter/app/Config/Paths.php index 007a6d328e97..d97bbb35a820 100644 --- a/admin/starter/app/Config/Paths.php +++ b/admin/starter/app/Config/Paths.php @@ -13,74 +13,73 @@ * * All paths are relative to the project's root folder. */ - class Paths { - /** - * --------------------------------------------------------------- - * SYSTEM FOLDER NAME - * --------------------------------------------------------------- - * - * This must contain the name of your "system" folder. Include - * the path if the folder is not in the same directory as this file. - * - * @var string - */ - public $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system'; + /** + * --------------------------------------------------------------- + * SYSTEM FOLDER NAME + * --------------------------------------------------------------- + * + * This must contain the name of your "system" folder. Include + * the path if the folder is not in the same directory as this file. + * + * @var string + */ + public $systemDirectory = __DIR__ . '/../../vendor/codeigniter4/framework/system'; - /** - * --------------------------------------------------------------- - * APPLICATION FOLDER NAME - * --------------------------------------------------------------- - * - * If you want this front controller to use a different "app" - * folder than the default one you can set its name here. The folder - * can also be renamed or relocated anywhere on your getServer. If - * you do, use a full getServer path. - * - * @see http://codeigniter.com/user_guide/general/managing_apps.html - * - * @var string - */ - public $appDirectory = __DIR__ . '/..'; + /** + * --------------------------------------------------------------- + * APPLICATION FOLDER NAME + * --------------------------------------------------------------- + * + * If you want this front controller to use a different "app" + * folder than the default one you can set its name here. The folder + * can also be renamed or relocated anywhere on your getServer. If + * you do, use a full getServer path. + * + * @see http://codeigniter.com/user_guide/general/managing_apps.html + * + * @var string + */ + public $appDirectory = __DIR__ . '/..'; - /** - * --------------------------------------------------------------- - * WRITABLE DIRECTORY NAME - * --------------------------------------------------------------- - * - * This variable must contain the name of your "writable" directory. - * The writable directory allows you to group all directories that - * need write permission to a single place that can be tucked away - * for maximum security, keeping it out of the app and/or - * system directories. - * - * @var string - */ - public $writableDirectory = __DIR__ . '/../../writable'; + /** + * --------------------------------------------------------------- + * WRITABLE DIRECTORY NAME + * --------------------------------------------------------------- + * + * This variable must contain the name of your "writable" directory. + * The writable directory allows you to group all directories that + * need write permission to a single place that can be tucked away + * for maximum security, keeping it out of the app and/or + * system directories. + * + * @var string + */ + public $writableDirectory = __DIR__ . '/../../writable'; - /** - * --------------------------------------------------------------- - * TESTS DIRECTORY NAME - * --------------------------------------------------------------- - * - * This variable must contain the name of your "tests" directory. - * - * @var string - */ - public $testsDirectory = __DIR__ . '/../../tests'; + /** + * --------------------------------------------------------------- + * TESTS DIRECTORY NAME + * --------------------------------------------------------------- + * + * This variable must contain the name of your "tests" directory. + * + * @var string + */ + public $testsDirectory = __DIR__ . '/../../tests'; - /** - * --------------------------------------------------------------- - * VIEW DIRECTORY NAME - * --------------------------------------------------------------- - * - * This variable must contain the name of the directory that - * contains the view files used by your application. By - * default this is in `app/Views`. This value - * is used when no value is provided to `Services::renderer()`. - * - * @var string - */ - public $viewDirectory = __DIR__ . '/../Views'; + /** + * --------------------------------------------------------------- + * VIEW DIRECTORY NAME + * --------------------------------------------------------------- + * + * This variable must contain the name of the directory that + * contains the view files used by your application. By + * default this is in `app/Views`. This value + * is used when no value is provided to `Services::renderer()`. + * + * @var string + */ + public $viewDirectory = __DIR__ . '/../Views'; } diff --git a/admin/starter/composer.json b/admin/starter/composer.json index 63112d799057..9f7dc492cbc8 100644 --- a/admin/starter/composer.json +++ b/admin/starter/composer.json @@ -1,41 +1,41 @@ { - "name": "codeigniter4/appstarter", - "type": "project", - "description": "CodeIgniter4 starter app", - "homepage": "https://codeigniter.com", - "license": "MIT", - "require": { - "php": "^7.3||^8.0", - "codeigniter4/framework": "^4" - }, - "require-dev": { - "fakerphp/faker": "^1.9", - "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "^9.1" - }, - "suggest": { - "ext-fileinfo": "Improves mime type detection for files" - }, - "autoload": { - "psr-4": { - "App\\": "app", - "Config\\": "app/Config" - }, - "exclude-from-classmap": [ - "**/Database/Migrations/**" - ] - }, - "autoload-dev": { - "psr-4": { - "Tests\\Support\\": "tests/_support" - } - }, - "scripts": { - "test": "phpunit" - }, - "support": { - "forum": "http://forum.codeigniter.com/", - "source": "https://github.com/codeigniter4/CodeIgniter4", - "slack": "https://codeigniterchat.slack.com" - } + "name": "codeigniter4/appstarter", + "type": "project", + "description": "CodeIgniter4 starter app", + "homepage": "https://codeigniter.com", + "license": "MIT", + "require": { + "php": "^7.3 || ^8.0", + "codeigniter4/framework": "^4" + }, + "require-dev": { + "fakerphp/faker": "^1.9", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^9.1" + }, + "suggest": { + "ext-fileinfo": "Improves mime type detection for files" + }, + "autoload": { + "psr-4": { + "App\\": "app", + "Config\\": "app/Config" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "autoload-dev": { + "psr-4": { + "Tests\\Support\\": "tests/_support" + } + }, + "scripts": { + "test": "phpunit" + }, + "support": { + "forum": "http://forum.codeigniter.com/", + "source": "https://github.com/codeigniter4/CodeIgniter4", + "slack": "https://codeigniterchat.slack.com" + } } diff --git a/admin/starter/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php b/admin/starter/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php index 1bfd4a33c171..2bbdcfe51994 100644 --- a/admin/starter/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php +++ b/admin/starter/tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php @@ -1,61 +1,37 @@ - [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'uid' => [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'class' => [ - 'type' => 'varchar', - 'constraint' => 63, - ], - 'icon' => [ - 'type' => 'varchar', - 'constraint' => 31, - ], - 'summary' => [ - 'type' => 'varchar', - 'constraint' => 255, - ], - 'created_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - 'updated_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - 'deleted_at' => [ - 'type' => 'datetime', - 'null' => true, - ], - ]; + protected $DBGroup = 'tests'; - $this->forge->addField('id'); - $this->forge->addField($fields); + public function up() + { + $this->forge->addField('id'); + $this->forge->addField([ + 'name' => ['type' => 'varchar', 'constraint' => 31], + 'uid' => ['type' => 'varchar', 'constraint' => 31], + 'class' => ['type' => 'varchar', 'constraint' => 63], + 'icon' => ['type' => 'varchar', 'constraint' => 31], + 'summary' => ['type' => 'varchar', 'constraint' => 255], + 'created_at' => ['type' => 'datetime', 'null' => true], + 'updated_at' => ['type' => 'datetime', 'null' => true], + 'deleted_at' => ['type' => 'datetime', 'null' => true], + ]); - $this->forge->addKey('name'); - $this->forge->addKey('uid'); - $this->forge->addKey(['deleted_at', 'id']); - $this->forge->addKey('created_at'); + $this->forge->addKey('name'); + $this->forge->addKey('uid'); + $this->forge->addKey(['deleted_at', 'id']); + $this->forge->addKey('created_at'); - $this->forge->createTable('factories'); - } + $this->forge->createTable('factories'); + } - public function down() - { - $this->forge->dropTable('factories'); - } + public function down() + { + $this->forge->dropTable('factories'); + } } diff --git a/admin/starter/tests/_support/Database/Seeds/ExampleSeeder.php b/admin/starter/tests/_support/Database/Seeds/ExampleSeeder.php index 1b14cedaa2dc..f67bf8fb8cae 100644 --- a/admin/starter/tests/_support/Database/Seeds/ExampleSeeder.php +++ b/admin/starter/tests/_support/Database/Seeds/ExampleSeeder.php @@ -1,40 +1,41 @@ - 'Test Factory', - 'uid' => 'test001', - 'class' => 'Factories\Tests\NewFactory', - 'icon' => 'fas fa-puzzle-piece', - 'summary' => 'Longer sample text for testing', - ], - [ - 'name' => 'Widget Factory', - 'uid' => 'widget', - 'class' => 'Factories\Tests\WidgetPlant', - 'icon' => 'fas fa-puzzle-piece', - 'summary' => 'Create widgets in your factory', - ], - [ - 'name' => 'Evil Factory', - 'uid' => 'evil-maker', - 'class' => 'Factories\Evil\MyFactory', - 'icon' => 'fas fa-book-dead', - 'summary' => 'Abandon all hope, ye who enter here', - ], - ]; + public function run() + { + $factories = [ + [ + 'name' => 'Test Factory', + 'uid' => 'test001', + 'class' => 'Factories\Tests\NewFactory', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Longer sample text for testing', + ], + [ + 'name' => 'Widget Factory', + 'uid' => 'widget', + 'class' => 'Factories\Tests\WidgetPlant', + 'icon' => 'fas fa-puzzle-piece', + 'summary' => 'Create widgets in your factory', + ], + [ + 'name' => 'Evil Factory', + 'uid' => 'evil-maker', + 'class' => 'Factories\Evil\MyFactory', + 'icon' => 'fas fa-book-dead', + 'summary' => 'Abandon all hope, ye who enter here', + ], + ]; - $builder = $this->db->table('factories'); + $builder = $this->db->table('factories'); - foreach ($factories as $factory) - { - $builder->insert($factory); - } - } + foreach ($factories as $factory) { + $builder->insert($factory); + } + } } diff --git a/admin/starter/tests/_support/DatabaseTestCase.php b/admin/starter/tests/_support/DatabaseTestCase.php index 42cbc6f5c1a0..fd067a585c87 100644 --- a/admin/starter/tests/_support/DatabaseTestCase.php +++ b/admin/starter/tests/_support/DatabaseTestCase.php @@ -1,56 +1,61 @@ -mockSession(); - } + $this->mockSession(); + } - /** - * Pre-loads the mock session driver into $this->session. - * - * @var string - */ - protected function mockSession() - { - $config = config('App'); - $this->session = new MockSession(new ArrayHandler($config, '0.0.0.0'), $config); - \Config\Services::injectMock('session', $this->session); - } + /** + * Pre-loads the mock session driver into $this->session. + * + * @var string + */ + protected function mockSession() + { + $config = config('App'); + $this->session = new MockSession(new ArrayHandler($config, '0.0.0.0'), $config); + \Config\Services::injectMock('session', $this->session); + } } diff --git a/admin/starter/tests/database/ExampleDatabaseTest.php b/admin/starter/tests/database/ExampleDatabaseTest.php index 2de0b6ae01bf..203b1261c7e0 100644 --- a/admin/starter/tests/database/ExampleDatabaseTest.php +++ b/admin/starter/tests/database/ExampleDatabaseTest.php @@ -2,41 +2,44 @@ use Tests\Support\Models\ExampleModel; -class ExampleDatabaseTest extends \Tests\Support\DatabaseTestCase +/** + * @internal + */ +final class ExampleDatabaseTest extends \Tests\Support\DatabaseTestCase { - public function setUp(): void - { - parent::setUp(); + protected function setUp(): void + { + parent::setUp(); - // Extra code to run before each test - } + // Extra code to run before each test + } - public function testModelFindAll() - { - $model = new ExampleModel(); + public function testModelFindAll() + { + $model = new ExampleModel(); - // Get every row created by ExampleSeeder - $objects = $model->findAll(); + // Get every row created by ExampleSeeder + $objects = $model->findAll(); - // Make sure the count is as expected - $this->assertCount(3, $objects); - } + // Make sure the count is as expected + $this->assertCount(3, $objects); + } - public function testSoftDeleteLeavesRow() - { - $model = new ExampleModel(); - $this->setPrivateProperty($model, 'useSoftDeletes', true); - $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); + public function testSoftDeleteLeavesRow() + { + $model = new ExampleModel(); + $this->setPrivateProperty($model, 'useSoftDeletes', true); + $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); - $object = $model->first(); - $model->delete($object->id); + $object = $model->first(); + $model->delete($object->id); - // The model should no longer find it - $this->assertNull($model->find($object->id)); + // The model should no longer find it + $this->assertNull($model->find($object->id)); - // ... but it should still be in the database - $result = $model->builder()->where('id', $object->id)->get()->getResult(); + // ... but it should still be in the database + $result = $model->builder()->where('id', $object->id)->get()->getResult(); - $this->assertCount(1, $result); - } + $this->assertCount(1, $result); + } } diff --git a/admin/starter/tests/session/ExampleSessionTest.php b/admin/starter/tests/session/ExampleSessionTest.php index 6ec0d011bd8d..65dd37c6b498 100644 --- a/admin/starter/tests/session/ExampleSessionTest.php +++ b/admin/starter/tests/session/ExampleSessionTest.php @@ -1,18 +1,21 @@ session->set('logged_in', 123); + public function testSessionSimple() + { + $this->session->set('logged_in', 123); - $value = $this->session->get('logged_in'); + $value = $this->session->get('logged_in'); - $this->assertEquals(123, $value); - } + $this->assertSame(123, $value); + } } diff --git a/admin/starter/tests/unit/HealthTest.php b/admin/starter/tests/unit/HealthTest.php index d5e979afca4e..f834ac605b40 100644 --- a/admin/starter/tests/unit/HealthTest.php +++ b/admin/starter/tests/unit/HealthTest.php @@ -2,51 +2,52 @@ use Config\Services; -class HealthTest extends \CodeIgniter\Test\CIUnitTestCase +/** + * @internal + */ +final class HealthTest extends \CodeIgniter\Test\CIUnitTestCase { - public function setUp(): void - { - parent::setUp(); - } - - public function testIsDefinedAppPath() - { - $test = defined('APPPATH'); - - $this->assertTrue($test); - } - - public function testBaseUrlHasBeenSet() - { - $validation = Services::validation(); - $env = false; - - // Check the baseURL in .env - if (is_file(HOMEPATH . '.env')) - { - $env = (bool) preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')); - } - - if ($env) - { - // BaseURL in .env is a valid URL? - // phpunit.xml.dist sets app.baseURL in $_SERVER - // So if you set app.baseURL in .env, it takes precedence - $config = new Config\App(); - $this->assertTrue( - $validation->check($config->baseURL, 'valid_url'), - 'baseURL "' . $config->baseURL . '" in .env is not valid URL' - ); - } - - // Get the baseURL in app/Config/App.php - // You can't use Config\App, because phpunit.xml.dist sets app.baseURL - $reader = new \Tests\Support\Libraries\ConfigReader(); - - // BaseURL in app/Config/App.php is a valid URL? - $this->assertTrue( - $validation->check($reader->baseURL, 'valid_url'), - 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' - ); - } + protected function setUp(): void + { + parent::setUp(); + } + + public function testIsDefinedAppPath() + { + $test = defined('APPPATH'); + + $this->assertTrue($test); + } + + public function testBaseUrlHasBeenSet() + { + $validation = Services::validation(); + $env = false; + + // Check the baseURL in .env + if (is_file(HOMEPATH . '.env')) { + $env = (bool) preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')); + } + + if ($env) { + // BaseURL in .env is a valid URL? + // phpunit.xml.dist sets app.baseURL in $_SERVER + // So if you set app.baseURL in .env, it takes precedence + $config = new Config\App(); + $this->assertTrue( + $validation->check($config->baseURL, 'valid_url'), + 'baseURL "' . $config->baseURL . '" in .env is not valid URL' + ); + } + + // Get the baseURL in app/Config/App.php + // You can't use Config\App, because phpunit.xml.dist sets app.baseURL + $reader = new \Tests\Support\Libraries\ConfigReader(); + + // BaseURL in app/Config/App.php is a valid URL? + $this->assertTrue( + $validation->check($reader->baseURL, 'valid_url'), + 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' + ); + } } diff --git a/admin/userguide/composer.json b/admin/userguide/composer.json index 198450876c89..a8fc259202fd 100644 --- a/admin/userguide/composer.json +++ b/admin/userguide/composer.json @@ -5,7 +5,7 @@ "homepage": "https://codeigniter.com", "license": "MIT", "require": { - "php": "^7.3||^8.0", + "php": "^7.3 || ^8.0", "codeigniter4/framework": "^4" }, "support": { diff --git a/app/Common.php b/app/Common.php index 780ba3f80198..a74d46d1ed5c 100644 --- a/app/Common.php +++ b/app/Common.php @@ -11,5 +11,5 @@ * loaded early on, and may also contain additional functions * that you'd like to use throughout your entire application * - * @link: https://codeigniter4.github.io/CodeIgniter4/ + * @see: https://codeigniter4.github.io/CodeIgniter4/ */ diff --git a/app/Config/App.php b/app/Config/App.php index 86b94d04b217..88b295e9a010 100644 --- a/app/Config/App.php +++ b/app/Config/App.php @@ -6,460 +6,459 @@ class App extends BaseConfig { - /** - * -------------------------------------------------------------------------- - * Base Site URL - * -------------------------------------------------------------------------- - * - * URL to your CodeIgniter root. Typically this will be your base URL, - * WITH a trailing slash: - * - * http://example.com/ - * - * If this is not set then CodeIgniter will try guess the protocol, domain - * and path to your installation. However, you should always configure this - * explicitly and never rely on auto-guessing, especially in production - * environments. - * - * @var string - */ - public $baseURL = 'http://localhost:8080/'; - - /** - * -------------------------------------------------------------------------- - * Index File - * -------------------------------------------------------------------------- - * - * Typically this will be your index.php file, unless you've renamed it to - * something else. If you are using mod_rewrite to remove the page set this - * variable so that it is blank. - * - * @var string - */ - public $indexPage = 'index.php'; - - /** - * -------------------------------------------------------------------------- - * URI PROTOCOL - * -------------------------------------------------------------------------- - * - * This item determines which getServer global should be used to retrieve the - * URI string. The default setting of 'REQUEST_URI' works for most servers. - * If your links do not seem to work, try one of the other delicious flavors: - * - * 'REQUEST_URI' Uses $_SERVER['REQUEST_URI'] - * 'QUERY_STRING' Uses $_SERVER['QUERY_STRING'] - * 'PATH_INFO' Uses $_SERVER['PATH_INFO'] - * - * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! - * - * @var string - */ - public $uriProtocol = 'REQUEST_URI'; - - /** - * -------------------------------------------------------------------------- - * Default Locale - * -------------------------------------------------------------------------- - * - * The Locale roughly represents the language and location that your visitor - * is viewing the site from. It affects the language strings and other - * strings (like currency markers, numbers, etc), that your program - * should run under for this request. - * - * @var string - */ - public $defaultLocale = 'en'; - - /** - * -------------------------------------------------------------------------- - * Negotiate Locale - * -------------------------------------------------------------------------- - * - * If true, the current Request object will automatically determine the - * language to use based on the value of the Accept-Language header. - * - * If false, no automatic detection will be performed. - * - * @var boolean - */ - public $negotiateLocale = false; - - /** - * -------------------------------------------------------------------------- - * Supported Locales - * -------------------------------------------------------------------------- - * - * If $negotiateLocale is true, this array lists the locales supported - * by the application in descending order of priority. If no match is - * found, the first locale will be used. - * - * @var string[] - */ - public $supportedLocales = ['en']; - - /** - * -------------------------------------------------------------------------- - * Application Timezone - * -------------------------------------------------------------------------- - * - * The default timezone that will be used in your application to display - * dates with the date helper, and can be retrieved through app_timezone() - * - * @var string - */ - public $appTimezone = 'America/Chicago'; - - /** - * -------------------------------------------------------------------------- - * Default Character Set - * -------------------------------------------------------------------------- - * - * This determines which character set is used by default in various methods - * that require a character set to be provided. - * - * @see http://php.net/htmlspecialchars for a list of supported charsets. - * - * @var string - */ - public $charset = 'UTF-8'; - - /** - * -------------------------------------------------------------------------- - * URI PROTOCOL - * -------------------------------------------------------------------------- - * - * If true, this will force every request made to this application to be - * made via a secure connection (HTTPS). If the incoming request is not - * secure, the user will be redirected to a secure version of the page - * and the HTTP Strict Transport Security header will be set. - * - * @var boolean - */ - public $forceGlobalSecureRequests = false; - - /** - * -------------------------------------------------------------------------- - * Session Driver - * -------------------------------------------------------------------------- - * - * The session storage driver to use: - * - `CodeIgniter\Session\Handlers\FileHandler` - * - `CodeIgniter\Session\Handlers\DatabaseHandler` - * - `CodeIgniter\Session\Handlers\MemcachedHandler` - * - `CodeIgniter\Session\Handlers\RedisHandler` - * - * @var string - */ - public $sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler'; - - /** - * -------------------------------------------------------------------------- - * Session Cookie Name - * -------------------------------------------------------------------------- - * - * The session cookie name, must contain only [0-9a-z_-] characters - * - * @var string - */ - public $sessionCookieName = 'ci_session'; - - /** - * -------------------------------------------------------------------------- - * Session Expiration - * -------------------------------------------------------------------------- - * - * The number of SECONDS you want the session to last. - * Setting to 0 (zero) means expire when the browser is closed. - * - * @var integer - */ - public $sessionExpiration = 7200; - - /** - * -------------------------------------------------------------------------- - * Session Save Path - * -------------------------------------------------------------------------- - * - * The location to save sessions to and is driver dependent. - * - * For the 'files' driver, it's a path to a writable directory. - * WARNING: Only absolute paths are supported! - * - * For the 'database' driver, it's a table name. - * Please read up the manual for the format with other session drivers. - * - * IMPORTANT: You are REQUIRED to set a valid save path! - * - * @var string - */ - public $sessionSavePath = WRITEPATH . 'session'; - - /** - * -------------------------------------------------------------------------- - * Session Match IP - * -------------------------------------------------------------------------- - * - * Whether to match the user's IP address when reading the session data. - * - * WARNING: If you're using the database driver, don't forget to update - * your session table's PRIMARY KEY when changing this setting. - * - * @var boolean - */ - public $sessionMatchIP = false; - - /** - * -------------------------------------------------------------------------- - * Session Time to Update - * -------------------------------------------------------------------------- - * - * How many seconds between CI regenerating the session ID. - * - * @var integer - */ - public $sessionTimeToUpdate = 300; - - /** - * -------------------------------------------------------------------------- - * Session Regenerate Destroy - * -------------------------------------------------------------------------- - * - * Whether to destroy session data associated with the old session ID - * when auto-regenerating the session ID. When set to FALSE, the data - * will be later deleted by the garbage collector. - * - * @var boolean - */ - public $sessionRegenerateDestroy = false; - - /** - * -------------------------------------------------------------------------- - * Cookie Prefix - * -------------------------------------------------------------------------- - * - * Set a cookie name prefix if you need to avoid collisions. - * - * @var string - * - * @deprecated use Config\Cookie::$prefix property instead. - */ - public $cookiePrefix = ''; - - /** - * -------------------------------------------------------------------------- - * Cookie Domain - * -------------------------------------------------------------------------- - * - * Set to `.your-domain.com` for site-wide cookies. - * - * @var string - * - * @deprecated use Config\Cookie::$domain property instead. - */ - public $cookieDomain = ''; - - /** - * -------------------------------------------------------------------------- - * Cookie Path - * -------------------------------------------------------------------------- - * - * Typically will be a forward slash. - * - * @var string - * - * @deprecated use Config\Cookie::$path property instead. - */ - public $cookiePath = '/'; - - /** - * -------------------------------------------------------------------------- - * Cookie Secure - * -------------------------------------------------------------------------- - * - * Cookie will only be set if a secure HTTPS connection exists. - * - * @var boolean - * - * @deprecated use Config\Cookie::$secure property instead. - */ - public $cookieSecure = false; - - /** - * -------------------------------------------------------------------------- - * Cookie HttpOnly - * -------------------------------------------------------------------------- - * - * Cookie will only be accessible via HTTP(S) (no JavaScript). - * - * @var boolean - * - * @deprecated use Config\Cookie::$httponly property instead. - */ - public $cookieHTTPOnly = true; - - /** - * -------------------------------------------------------------------------- - * Cookie SameSite - * -------------------------------------------------------------------------- - * - * Configure cookie SameSite setting. Allowed values are: - * - None - * - Lax - * - Strict - * - '' - * - * Alternatively, you can use the constant names: - * - `Cookie::SAMESITE_NONE` - * - `Cookie::SAMESITE_LAX` - * - `Cookie::SAMESITE_STRICT` - * - * Defaults to `Lax` for compatibility with modern browsers. Setting `''` - * (empty string) means default SameSite attribute set by browsers (`Lax`) - * will be set on cookies. If set to `None`, `$cookieSecure` must also be set. - * - * @var string - * - * @deprecated use Config\Cookie::$samesite property instead. - */ - public $cookieSameSite = 'Lax'; - - /** - * -------------------------------------------------------------------------- - * Reverse Proxy IPs - * -------------------------------------------------------------------------- - * - * If your server is behind a reverse proxy, you must whitelist the proxy - * IP addresses from which CodeIgniter should trust headers such as - * HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify - * the visitor's IP address. - * - * You can use both an array or a comma-separated list of proxy addresses, - * as well as specifying whole subnets. Here are a few examples: - * - * Comma-separated: '10.0.1.200,192.168.5.0/24' - * Array: ['10.0.1.200', '192.168.5.0/24'] - * - * @var string|string[] - */ - public $proxyIPs = ''; - - /** - * -------------------------------------------------------------------------- - * CSRF Token Name - * -------------------------------------------------------------------------- - * - * The token name. - * - * @deprecated Use `Config\Security` $tokenName property instead of using this property. - * - * @var string - */ - public $CSRFTokenName = 'csrf_test_name'; - - /** - * -------------------------------------------------------------------------- - * CSRF Header Name - * -------------------------------------------------------------------------- - * - * The header name. - * - * @deprecated Use `Config\Security` $headerName property instead of using this property. - * - * @var string - */ - public $CSRFHeaderName = 'X-CSRF-TOKEN'; - - /** - * -------------------------------------------------------------------------- - * CSRF Cookie Name - * -------------------------------------------------------------------------- - * - * The cookie name. - * - * @deprecated Use `Config\Security` $cookieName property instead of using this property. - * - * @var string - */ - public $CSRFCookieName = 'csrf_cookie_name'; - - /** - * -------------------------------------------------------------------------- - * CSRF Expire - * -------------------------------------------------------------------------- - * - * The number in seconds the token should expire. - * - * @deprecated Use `Config\Security` $expire property instead of using this property. - * - * @var integer - */ - public $CSRFExpire = 7200; - - /** - * -------------------------------------------------------------------------- - * CSRF Regenerate - * -------------------------------------------------------------------------- - * - * Regenerate token on every submission? - * - * @deprecated Use `Config\Security` $regenerate property instead of using this property. - * - * @var boolean - */ - public $CSRFRegenerate = true; - - /** - * -------------------------------------------------------------------------- - * CSRF Redirect - * -------------------------------------------------------------------------- - * - * Redirect to previous page with error on failure? - * - * @deprecated Use `Config\Security` $redirect property instead of using this property. - * - * @var boolean - */ - public $CSRFRedirect = true; - - /** - * -------------------------------------------------------------------------- - * CSRF SameSite - * -------------------------------------------------------------------------- - * - * Setting for CSRF SameSite cookie token. Allowed values are: - * - None - * - Lax - * - Strict - * - '' - * - * Defaults to `Lax` as recommended in this link: - * - * @see https://portswigger.net/web-security/csrf/samesite-cookies - * - * @deprecated Use `Config\Security` $samesite property instead of using this property. - * - * @var string - */ - public $CSRFSameSite = 'Lax'; - - /** - * -------------------------------------------------------------------------- - * Content Security Policy - * -------------------------------------------------------------------------- - * - * Enables the Response's Content Secure Policy to restrict the sources that - * can be used for images, scripts, CSS files, audio, video, etc. If enabled, - * the Response object will populate default values for the policy from the - * `ContentSecurityPolicy.php` file. Controllers can always add to those - * restrictions at run time. - * - * For a better understanding of CSP, see these documents: - * - * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ - * @see http://www.w3.org/TR/CSP/ - * - * @var boolean - */ - public $CSPEnabled = false; + /** + * -------------------------------------------------------------------------- + * Base Site URL + * -------------------------------------------------------------------------- + * + * URL to your CodeIgniter root. Typically this will be your base URL, + * WITH a trailing slash: + * + * http://example.com/ + * + * If this is not set then CodeIgniter will try guess the protocol, domain + * and path to your installation. However, you should always configure this + * explicitly and never rely on auto-guessing, especially in production + * environments. + * + * @var string + */ + public $baseURL = 'http://localhost:8080/'; + + /** + * -------------------------------------------------------------------------- + * Index File + * -------------------------------------------------------------------------- + * + * Typically this will be your index.php file, unless you've renamed it to + * something else. If you are using mod_rewrite to remove the page set this + * variable so that it is blank. + * + * @var string + */ + public $indexPage = 'index.php'; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * This item determines which getServer global should be used to retrieve the + * URI string. The default setting of 'REQUEST_URI' works for most servers. + * If your links do not seem to work, try one of the other delicious flavors: + * + * 'REQUEST_URI' Uses $_SERVER['REQUEST_URI'] + * 'QUERY_STRING' Uses $_SERVER['QUERY_STRING'] + * 'PATH_INFO' Uses $_SERVER['PATH_INFO'] + * + * WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded! + * + * @var string + */ + public $uriProtocol = 'REQUEST_URI'; + + /** + * -------------------------------------------------------------------------- + * Default Locale + * -------------------------------------------------------------------------- + * + * The Locale roughly represents the language and location that your visitor + * is viewing the site from. It affects the language strings and other + * strings (like currency markers, numbers, etc), that your program + * should run under for this request. + * + * @var string + */ + public $defaultLocale = 'en'; + + /** + * -------------------------------------------------------------------------- + * Negotiate Locale + * -------------------------------------------------------------------------- + * + * If true, the current Request object will automatically determine the + * language to use based on the value of the Accept-Language header. + * + * If false, no automatic detection will be performed. + * + * @var bool + */ + public $negotiateLocale = false; + + /** + * -------------------------------------------------------------------------- + * Supported Locales + * -------------------------------------------------------------------------- + * + * If $negotiateLocale is true, this array lists the locales supported + * by the application in descending order of priority. If no match is + * found, the first locale will be used. + * + * @var string[] + */ + public $supportedLocales = ['en']; + + /** + * -------------------------------------------------------------------------- + * Application Timezone + * -------------------------------------------------------------------------- + * + * The default timezone that will be used in your application to display + * dates with the date helper, and can be retrieved through app_timezone() + * + * @var string + */ + public $appTimezone = 'America/Chicago'; + + /** + * -------------------------------------------------------------------------- + * Default Character Set + * -------------------------------------------------------------------------- + * + * This determines which character set is used by default in various methods + * that require a character set to be provided. + * + * @see http://php.net/htmlspecialchars for a list of supported charsets. + * + * @var string + */ + public $charset = 'UTF-8'; + + /** + * -------------------------------------------------------------------------- + * URI PROTOCOL + * -------------------------------------------------------------------------- + * + * If true, this will force every request made to this application to be + * made via a secure connection (HTTPS). If the incoming request is not + * secure, the user will be redirected to a secure version of the page + * and the HTTP Strict Transport Security header will be set. + * + * @var bool + */ + public $forceGlobalSecureRequests = false; + + /** + * -------------------------------------------------------------------------- + * Session Driver + * -------------------------------------------------------------------------- + * + * The session storage driver to use: + * - `CodeIgniter\Session\Handlers\FileHandler` + * - `CodeIgniter\Session\Handlers\DatabaseHandler` + * - `CodeIgniter\Session\Handlers\MemcachedHandler` + * - `CodeIgniter\Session\Handlers\RedisHandler` + * + * @var string + */ + public $sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler'; + + /** + * -------------------------------------------------------------------------- + * Session Cookie Name + * -------------------------------------------------------------------------- + * + * The session cookie name, must contain only [0-9a-z_-] characters + * + * @var string + */ + public $sessionCookieName = 'ci_session'; + + /** + * -------------------------------------------------------------------------- + * Session Expiration + * -------------------------------------------------------------------------- + * + * The number of SECONDS you want the session to last. + * Setting to 0 (zero) means expire when the browser is closed. + * + * @var int + */ + public $sessionExpiration = 7200; + + /** + * -------------------------------------------------------------------------- + * Session Save Path + * -------------------------------------------------------------------------- + * + * The location to save sessions to and is driver dependent. + * + * For the 'files' driver, it's a path to a writable directory. + * WARNING: Only absolute paths are supported! + * + * For the 'database' driver, it's a table name. + * Please read up the manual for the format with other session drivers. + * + * IMPORTANT: You are REQUIRED to set a valid save path! + * + * @var string + */ + public $sessionSavePath = WRITEPATH . 'session'; + + /** + * -------------------------------------------------------------------------- + * Session Match IP + * -------------------------------------------------------------------------- + * + * Whether to match the user's IP address when reading the session data. + * + * WARNING: If you're using the database driver, don't forget to update + * your session table's PRIMARY KEY when changing this setting. + * + * @var bool + */ + public $sessionMatchIP = false; + + /** + * -------------------------------------------------------------------------- + * Session Time to Update + * -------------------------------------------------------------------------- + * + * How many seconds between CI regenerating the session ID. + * + * @var int + */ + public $sessionTimeToUpdate = 300; + + /** + * -------------------------------------------------------------------------- + * Session Regenerate Destroy + * -------------------------------------------------------------------------- + * + * Whether to destroy session data associated with the old session ID + * when auto-regenerating the session ID. When set to FALSE, the data + * will be later deleted by the garbage collector. + * + * @var bool + */ + public $sessionRegenerateDestroy = false; + + /** + * -------------------------------------------------------------------------- + * Cookie Prefix + * -------------------------------------------------------------------------- + * + * Set a cookie name prefix if you need to avoid collisions. + * + * @var string + * + * @deprecated use Config\Cookie::$prefix property instead. + */ + public $cookiePrefix = ''; + + /** + * -------------------------------------------------------------------------- + * Cookie Domain + * -------------------------------------------------------------------------- + * + * Set to `.your-domain.com` for site-wide cookies. + * + * @var string + * + * @deprecated use Config\Cookie::$domain property instead. + */ + public $cookieDomain = ''; + + /** + * -------------------------------------------------------------------------- + * Cookie Path + * -------------------------------------------------------------------------- + * + * Typically will be a forward slash. + * + * @var string + * + * @deprecated use Config\Cookie::$path property instead. + */ + public $cookiePath = '/'; + + /** + * -------------------------------------------------------------------------- + * Cookie Secure + * -------------------------------------------------------------------------- + * + * Cookie will only be set if a secure HTTPS connection exists. + * + * @var bool + * + * @deprecated use Config\Cookie::$secure property instead. + */ + public $cookieSecure = false; + + /** + * -------------------------------------------------------------------------- + * Cookie HttpOnly + * -------------------------------------------------------------------------- + * + * Cookie will only be accessible via HTTP(S) (no JavaScript). + * + * @var bool + * + * @deprecated use Config\Cookie::$httponly property instead. + */ + public $cookieHTTPOnly = true; + + /** + * -------------------------------------------------------------------------- + * Cookie SameSite + * -------------------------------------------------------------------------- + * + * Configure cookie SameSite setting. Allowed values are: + * - None + * - Lax + * - Strict + * - '' + * + * Alternatively, you can use the constant names: + * - `Cookie::SAMESITE_NONE` + * - `Cookie::SAMESITE_LAX` + * - `Cookie::SAMESITE_STRICT` + * + * Defaults to `Lax` for compatibility with modern browsers. Setting `''` + * (empty string) means default SameSite attribute set by browsers (`Lax`) + * will be set on cookies. If set to `None`, `$cookieSecure` must also be set. + * + * @var string + * + * @deprecated use Config\Cookie::$samesite property instead. + */ + public $cookieSameSite = 'Lax'; + + /** + * -------------------------------------------------------------------------- + * Reverse Proxy IPs + * -------------------------------------------------------------------------- + * + * If your server is behind a reverse proxy, you must whitelist the proxy + * IP addresses from which CodeIgniter should trust headers such as + * HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify + * the visitor's IP address. + * + * You can use both an array or a comma-separated list of proxy addresses, + * as well as specifying whole subnets. Here are a few examples: + * + * Comma-separated: '10.0.1.200,192.168.5.0/24' + * Array: ['10.0.1.200', '192.168.5.0/24'] + * + * @var string|string[] + */ + public $proxyIPs = ''; + + /** + * -------------------------------------------------------------------------- + * CSRF Token Name + * -------------------------------------------------------------------------- + * + * The token name. + * + * @deprecated Use `Config\Security` $tokenName property instead of using this property. + * + * @var string + */ + public $CSRFTokenName = 'csrf_test_name'; + + /** + * -------------------------------------------------------------------------- + * CSRF Header Name + * -------------------------------------------------------------------------- + * + * The header name. + * + * @deprecated Use `Config\Security` $headerName property instead of using this property. + * + * @var string + */ + public $CSRFHeaderName = 'X-CSRF-TOKEN'; + + /** + * -------------------------------------------------------------------------- + * CSRF Cookie Name + * -------------------------------------------------------------------------- + * + * The cookie name. + * + * @deprecated Use `Config\Security` $cookieName property instead of using this property. + * + * @var string + */ + public $CSRFCookieName = 'csrf_cookie_name'; + + /** + * -------------------------------------------------------------------------- + * CSRF Expire + * -------------------------------------------------------------------------- + * + * The number in seconds the token should expire. + * + * @deprecated Use `Config\Security` $expire property instead of using this property. + * + * @var int + */ + public $CSRFExpire = 7200; + + /** + * -------------------------------------------------------------------------- + * CSRF Regenerate + * -------------------------------------------------------------------------- + * + * Regenerate token on every submission? + * + * @deprecated Use `Config\Security` $regenerate property instead of using this property. + * + * @var bool + */ + public $CSRFRegenerate = true; + + /** + * -------------------------------------------------------------------------- + * CSRF Redirect + * -------------------------------------------------------------------------- + * + * Redirect to previous page with error on failure? + * + * @deprecated Use `Config\Security` $redirect property instead of using this property. + * + * @var bool + */ + public $CSRFRedirect = true; + + /** + * -------------------------------------------------------------------------- + * CSRF SameSite + * -------------------------------------------------------------------------- + * + * Setting for CSRF SameSite cookie token. Allowed values are: + * - None + * - Lax + * - Strict + * - '' + * + * Defaults to `Lax` as recommended in this link: + * + * @see https://portswigger.net/web-security/csrf/samesite-cookies + * @deprecated Use `Config\Security` $samesite property instead of using this property. + * + * @var string + */ + public $CSRFSameSite = 'Lax'; + + /** + * -------------------------------------------------------------------------- + * Content Security Policy + * -------------------------------------------------------------------------- + * + * Enables the Response's Content Secure Policy to restrict the sources that + * can be used for images, scripts, CSS files, audio, video, etc. If enabled, + * the Response object will populate default values for the policy from the + * `ContentSecurityPolicy.php` file. Controllers can always add to those + * restrictions at run time. + * + * For a better understanding of CSP, see these documents: + * + * @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/ + * @see http://www.w3.org/TR/CSP/ + * + * @var bool + */ + public $CSPEnabled = false; } diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index 1ed5e3f65b91..ee27e3b2ce18 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -17,68 +17,71 @@ */ class Autoload extends AutoloadConfig { - /** - * ------------------------------------------------------------------- - * Namespaces - * ------------------------------------------------------------------- - * This maps the locations of any namespaces in your application to - * their location on the file system. These are used by the autoloader - * to locate files the first time they have been instantiated. - * - * The '/app' and '/system' directories are already mapped for you. - * you may change the name of the 'App' namespace if you wish, - * but this should be done prior to creating any namespaced classes, - * else you will need to modify all of those classes for this to work. - * - * Prototype: - *``` - * $psr4 = [ - * 'CodeIgniter' => SYSTEMPATH, - * 'App' => APPPATH - * ]; - *``` - * @var array - */ - public $psr4 = [ - APP_NAMESPACE => APPPATH, // For custom app namespace - 'Config' => APPPATH . 'Config', - ]; + /** + * ------------------------------------------------------------------- + * Namespaces + * ------------------------------------------------------------------- + * This maps the locations of any namespaces in your application to + * their location on the file system. These are used by the autoloader + * to locate files the first time they have been instantiated. + * + * The '/app' and '/system' directories are already mapped for you. + * you may change the name of the 'App' namespace if you wish, + * but this should be done prior to creating any namespaced classes, + * else you will need to modify all of those classes for this to work. + * + * Prototype: + *``` + * $psr4 = [ + * 'CodeIgniter' => SYSTEMPATH, + * 'App' => APPPATH + * ]; + *``` + * + * @var array + */ + public $psr4 = [ + APP_NAMESPACE => APPPATH, // For custom app namespace + 'Config' => APPPATH . 'Config', + ]; - /** - * ------------------------------------------------------------------- - * Class Map - * ------------------------------------------------------------------- - * The class map provides a map of class names and their exact - * location on the drive. Classes loaded in this manner will have - * slightly faster performance because they will not have to be - * searched for within one or more directories as they would if they - * were being autoloaded through a namespace. - * - * Prototype: - *``` - * $classmap = [ - * 'MyClass' => '/path/to/class/file.php' - * ]; - *``` - * @var array - */ - public $classmap = []; + /** + * ------------------------------------------------------------------- + * Class Map + * ------------------------------------------------------------------- + * The class map provides a map of class names and their exact + * location on the drive. Classes loaded in this manner will have + * slightly faster performance because they will not have to be + * searched for within one or more directories as they would if they + * were being autoloaded through a namespace. + * + * Prototype: + *``` + * $classmap = [ + * 'MyClass' => '/path/to/class/file.php' + * ]; + *``` + * + * @var array + */ + public $classmap = []; - /** - * ------------------------------------------------------------------- - * Files - * ------------------------------------------------------------------- - * The files array provides a list of paths to __non-class__ files - * that will be autoloaded. This can be useful for bootstrap operations - * or for loading functions. - * - * Prototype: - * ``` - * $files = [ - * '/path/to/my/file.php', - * ]; - * ``` - * @var array - */ - public $files = []; + /** + * ------------------------------------------------------------------- + * Files + * ------------------------------------------------------------------- + * The files array provides a list of paths to __non-class__ files + * that will be autoloaded. This can be useful for bootstrap operations + * or for loading functions. + * + * Prototype: + * ``` + * $files = [ + * '/path/to/my/file.php', + * ]; + * ``` + * + * @var array + */ + public $files = []; } diff --git a/app/Config/Cache.php b/app/Config/Cache.php index e5711a35fbca..ce1db4d7f24e 100644 --- a/app/Config/Cache.php +++ b/app/Config/Cache.php @@ -12,156 +12,156 @@ class Cache extends BaseConfig { - /** - * -------------------------------------------------------------------------- - * Primary Handler - * -------------------------------------------------------------------------- - * - * The name of the preferred handler that should be used. If for some reason - * it is not available, the $backupHandler will be used in its place. - * - * @var string - */ - public $handler = 'file'; + /** + * -------------------------------------------------------------------------- + * Primary Handler + * -------------------------------------------------------------------------- + * + * The name of the preferred handler that should be used. If for some reason + * it is not available, the $backupHandler will be used in its place. + * + * @var string + */ + public $handler = 'file'; - /** - * -------------------------------------------------------------------------- - * Backup Handler - * -------------------------------------------------------------------------- - * - * The name of the handler that will be used in case the first one is - * unreachable. Often, 'file' is used here since the filesystem is - * always available, though that's not always practical for the app. - * - * @var string - */ - public $backupHandler = 'dummy'; + /** + * -------------------------------------------------------------------------- + * Backup Handler + * -------------------------------------------------------------------------- + * + * The name of the handler that will be used in case the first one is + * unreachable. Often, 'file' is used here since the filesystem is + * always available, though that's not always practical for the app. + * + * @var string + */ + public $backupHandler = 'dummy'; - /** - * -------------------------------------------------------------------------- - * Cache Directory Path - * -------------------------------------------------------------------------- - * - * The path to where cache files should be stored, if using a file-based - * system. - * - * @var string - * - * @deprecated Use the driver-specific variant under $file - */ - public $storePath = WRITEPATH . 'cache/'; + /** + * -------------------------------------------------------------------------- + * Cache Directory Path + * -------------------------------------------------------------------------- + * + * The path to where cache files should be stored, if using a file-based + * system. + * + * @var string + * + * @deprecated Use the driver-specific variant under $file + */ + public $storePath = WRITEPATH . 'cache/'; - /** - * -------------------------------------------------------------------------- - * Cache Include Query String - * -------------------------------------------------------------------------- - * - * Whether to take the URL query string into consideration when generating - * output cache files. Valid options are: - * - * false = Disabled - * true = Enabled, take all query parameters into account. - * Please be aware that this may result in numerous cache - * files generated for the same page over and over again. - * array('q') = Enabled, but only take into account the specified list - * of query parameters. - * - * @var boolean|string[] - */ - public $cacheQueryString = false; + /** + * -------------------------------------------------------------------------- + * Cache Include Query String + * -------------------------------------------------------------------------- + * + * Whether to take the URL query string into consideration when generating + * output cache files. Valid options are: + * + * false = Disabled + * true = Enabled, take all query parameters into account. + * Please be aware that this may result in numerous cache + * files generated for the same page over and over again. + * array('q') = Enabled, but only take into account the specified list + * of query parameters. + * + * @var bool|string[] + */ + public $cacheQueryString = false; - /** - * -------------------------------------------------------------------------- - * Key Prefix - * -------------------------------------------------------------------------- - * - * This string is added to all cache item names to help avoid collisions - * if you run multiple applications with the same cache engine. - * - * @var string - */ - public $prefix = ''; + /** + * -------------------------------------------------------------------------- + * Key Prefix + * -------------------------------------------------------------------------- + * + * This string is added to all cache item names to help avoid collisions + * if you run multiple applications with the same cache engine. + * + * @var string + */ + public $prefix = ''; - /** - * -------------------------------------------------------------------------- - * Default TTL - * -------------------------------------------------------------------------- - * - * The default number of seconds to save items when none is specified. - * - * WARNING: This is not used by framework handlers where 60 seconds is - * hard-coded, but may be useful to projects and modules. This will replace - * the hard-coded value in a future release. - * - * @var integer - */ - public $ttl = 60; + /** + * -------------------------------------------------------------------------- + * Default TTL + * -------------------------------------------------------------------------- + * + * The default number of seconds to save items when none is specified. + * + * WARNING: This is not used by framework handlers where 60 seconds is + * hard-coded, but may be useful to projects and modules. This will replace + * the hard-coded value in a future release. + * + * @var int + */ + public $ttl = 60; - /** - * -------------------------------------------------------------------------- - * File settings - * -------------------------------------------------------------------------- - * Your file storage preferences can be specified below, if you are using - * the File driver. - * - * @var array - */ - public $file = [ - 'storePath' => WRITEPATH . 'cache/', - 'mode' => 0640, - ]; + /** + * -------------------------------------------------------------------------- + * File settings + * -------------------------------------------------------------------------- + * Your file storage preferences can be specified below, if you are using + * the File driver. + * + * @var array + */ + public $file = [ + 'storePath' => WRITEPATH . 'cache/', + 'mode' => 0640, + ]; - /** - * ------------------------------------------------------------------------- - * Memcached settings - * ------------------------------------------------------------------------- - * Your Memcached servers can be specified below, if you are using - * the Memcached drivers. - * - * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached - * - * @var array - */ - public $memcached = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'weight' => 1, - 'raw' => false, - ]; + /** + * ------------------------------------------------------------------------- + * Memcached settings + * ------------------------------------------------------------------------- + * Your Memcached servers can be specified below, if you are using + * the Memcached drivers. + * + * @see https://codeigniter.com/user_guide/libraries/caching.html#memcached + * + * @var array + */ + public $memcached = [ + 'host' => '127.0.0.1', + 'port' => 11211, + 'weight' => 1, + 'raw' => false, + ]; - /** - * ------------------------------------------------------------------------- - * Redis settings - * ------------------------------------------------------------------------- - * Your Redis server can be specified below, if you are using - * the Redis or Predis drivers. - * - * @var array - */ - public $redis = [ - 'host' => '127.0.0.1', - 'password' => null, - 'port' => 6379, - 'timeout' => 0, - 'database' => 0, - ]; + /** + * ------------------------------------------------------------------------- + * Redis settings + * ------------------------------------------------------------------------- + * Your Redis server can be specified below, if you are using + * the Redis or Predis drivers. + * + * @var array + */ + public $redis = [ + 'host' => '127.0.0.1', + 'password' => null, + 'port' => 6379, + 'timeout' => 0, + 'database' => 0, + ]; - /** - * -------------------------------------------------------------------------- - * Available Cache Handlers - * -------------------------------------------------------------------------- - * - * This is an array of cache engine alias' and class names. Only engines - * that are listed here are allowed to be used. - * - * @var array - */ - public $validHandlers = [ - 'dummy' => DummyHandler::class, - 'file' => FileHandler::class, - 'memcached' => MemcachedHandler::class, - 'predis' => PredisHandler::class, - 'redis' => RedisHandler::class, - 'wincache' => WincacheHandler::class, - ]; + /** + * -------------------------------------------------------------------------- + * Available Cache Handlers + * -------------------------------------------------------------------------- + * + * This is an array of cache engine alias' and class names. Only engines + * that are listed here are allowed to be used. + * + * @var array + */ + public $validHandlers = [ + 'dummy' => DummyHandler::class, + 'file' => FileHandler::class, + 'memcached' => MemcachedHandler::class, + 'predis' => PredisHandler::class, + 'redis' => RedisHandler::class, + 'wincache' => WincacheHandler::class, + ]; } diff --git a/app/Config/ContentSecurityPolicy.php b/app/Config/ContentSecurityPolicy.php index a04e3d0f9e6a..6fa5bd7b4cc7 100644 --- a/app/Config/ContentSecurityPolicy.php +++ b/app/Config/ContentSecurityPolicy.php @@ -15,153 +15,153 @@ */ class ContentSecurityPolicy extends BaseConfig { - //------------------------------------------------------------------------- - // Broadbrush CSP management - //------------------------------------------------------------------------- - - /** - * Default CSP report context - * - * @var boolean - */ - public $reportOnly = false; - - /** - * Specifies a URL where a browser will send reports - * when a content security policy is violated. - * - * @var string|null - */ - public $reportURI = null; - - /** - * Instructs user agents to rewrite URL schemes, changing - * HTTP to HTTPS. This directive is for websites with - * large numbers of old URLs that need to be rewritten. - * - * @var boolean - */ - public $upgradeInsecureRequests = false; - - //------------------------------------------------------------------------- - // Sources allowed - // Note: once you set a policy to 'none', it cannot be further restricted - //------------------------------------------------------------------------- - - /** - * Will default to self if not overridden - * - * @var string|string[]|null - */ - public $defaultSrc = null; - - /** - * Lists allowed scripts' URLs. - * - * @var string|string[] - */ - public $scriptSrc = 'self'; - - /** - * Lists allowed stylesheets' URLs. - * - * @var string|string[] - */ - public $styleSrc = 'self'; - - /** - * Defines the origins from which images can be loaded. - * - * @var string|string[] - */ - public $imageSrc = 'self'; - - /** - * Restricts the URLs that can appear in a page's `` element. - * - * Will default to self if not overridden - * - * @var string|string[]|null - */ - public $baseURI = null; - - /** - * Lists the URLs for workers and embedded frame contents - * - * @var string|string[] - */ - public $childSrc = 'self'; - - /** - * Limits the origins that you can connect to (via XHR, - * WebSockets, and EventSource). - * - * @var string|string[] - */ - public $connectSrc = 'self'; - - /** - * Specifies the origins that can serve web fonts. - * - * @var string|string[] - */ - public $fontSrc = null; - - /** - * Lists valid endpoints for submission from `
` tags. - * - * @var string|string[] - */ - public $formAction = 'self'; - - /** - * Specifies the sources that can embed the current page. - * This directive applies to ``, `