From 2643bbfdccd450b7a66d4290433fc08b88c43f58 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 14 Nov 2023 02:16:33 +0330 Subject: [PATCH 1/9] publish CI-DEA-RULE --- .github/ISSUE_TEMPLATE/bug_report.yml | 112 ++++++++++ .github/ISSUE_TEMPLATE/config.yml | 9 + .github/ISSUE_TEMPLATE/feature_request.md | 11 + .github/ISSUE_TEMPLATE/planned-work.md | 10 + .github/dependabot.yml | 32 +++ .github/release.yml | 26 +++ .github/workflows/deptrac.yml | 72 +++++++ .github/workflows/docs.yml | 27 +++ .github/workflows/phpcpd.yml | 36 ++++ .github/workflows/phpcsfixer.yml | 59 ++++++ .github/workflows/phpstan.yml | 74 +++++++ .github/workflows/phpunit-lang.yml | 63 ++++++ .github/workflows/phpunit.yml | 185 ++++++++++++++++ .github/workflows/psalm.yml | 70 +++++++ .github/workflows/rector.yml | 66 ++++++ .github/workflows/unused.yml | 58 +++++ .gitignore | 112 ++++++++++ .php-cs-fixer.dist.php | 45 ++++ LICENSE | 2 +- README.md | 35 ++++ SECURITY.md | 26 +++ UPGRADING.md | 2 + admin/pre-commit | 52 +++++ admin/setup.sh | 6 + composer-unused.php | 15 ++ composer.json | 85 ++++++++ deptrac.yaml | 157 ++++++++++++++ docs/assets/css/dark_mode.css | 74 +++++++ docs/assets/favicon.ico | Bin 0 -> 5087 bytes docs/assets/flame.svg | 11 + docs/assets/hljs.js | 3 + docs/assets/js/hljs.js | 3 + docs/how_to_use.md | 93 ++++++++ docs/index.md | 34 +++ docs/install.md | 49 +++++ infection.json.dist | 19 ++ mkdocs.yml | 85 ++++++++ phpstan-baseline.php | 10 + phpstan.neon.dist | 24 +++ phpunit.xml.dist | 103 +++++++++ psalm-baseline.xml | 4 + psalm.xml | 19 ++ psalm_autoload.php | 26 +++ rector.php | 133 ++++++++++++ roave-bc-check.yaml | 3 + src/Commands/DEARulePublish.php | 57 +++++ src/Config/DEARule.php | 96 +++++++++ src/Config/Registrar.php | 36 ++++ ...23-11-11-105553_LogsTempEmailMigration.php | 70 +++++++ src/Language/en/DEAValidatorRule.php | 18 ++ src/Language/fa/DEAValidatorRule.php | 18 ++ src/Models/LogsTempEmailModel.php | 48 +++++ src/Validation/DEAValidator.php | 149 +++++++++++++ .../Migrations/LogsTempEmailMigrationTest.php | 96 +++++++++ tests/Models/LogsTempEmailModelTest.php | 77 +++++++ tests/Validation/DEAValidatorTest.php | 198 ++++++++++++++++++ 56 files changed, 3002 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/planned-work.md create mode 100644 .github/dependabot.yml create mode 100644 .github/release.yml create mode 100644 .github/workflows/deptrac.yml create mode 100644 .github/workflows/docs.yml create mode 100644 .github/workflows/phpcpd.yml create mode 100644 .github/workflows/phpcsfixer.yml create mode 100644 .github/workflows/phpstan.yml create mode 100644 .github/workflows/phpunit-lang.yml create mode 100644 .github/workflows/phpunit.yml create mode 100644 .github/workflows/psalm.yml create mode 100644 .github/workflows/rector.yml create mode 100644 .github/workflows/unused.yml create mode 100644 .gitignore create mode 100644 .php-cs-fixer.dist.php create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 UPGRADING.md create mode 100644 admin/pre-commit create mode 100644 admin/setup.sh create mode 100644 composer-unused.php create mode 100644 composer.json create mode 100644 deptrac.yaml create mode 100644 docs/assets/css/dark_mode.css create mode 100644 docs/assets/favicon.ico create mode 100644 docs/assets/flame.svg create mode 100644 docs/assets/hljs.js create mode 100644 docs/assets/js/hljs.js create mode 100644 docs/how_to_use.md create mode 100644 docs/index.md create mode 100644 docs/install.md create mode 100644 infection.json.dist create mode 100644 mkdocs.yml create mode 100644 phpstan-baseline.php create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml.dist create mode 100644 psalm-baseline.xml create mode 100644 psalm.xml create mode 100644 psalm_autoload.php create mode 100644 rector.php create mode 100644 roave-bc-check.yaml create mode 100644 src/Commands/DEARulePublish.php create mode 100644 src/Config/DEARule.php create mode 100644 src/Config/Registrar.php create mode 100644 src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php create mode 100644 src/Language/en/DEAValidatorRule.php create mode 100644 src/Language/fa/DEAValidatorRule.php create mode 100644 src/Models/LogsTempEmailModel.php create mode 100644 src/Validation/DEAValidator.php create mode 100644 tests/Database/Migrations/LogsTempEmailMigrationTest.php create mode 100644 tests/Models/LogsTempEmailModelTest.php create mode 100644 tests/Validation/DEAValidatorTest.php diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..e342374 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,112 @@ +name: Bug report +description: Create a report to help us improve CodeIgniter DEA Rule +title: "Bug: " +labels: ['bug'] + +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Before you begin, **please ensure that there are no existing issues, + whether still open or closed, related to your report**. + If there is, your report will be closed promptly. + + --- + + - type: input + id: php-version + attributes: + label: PHP Version + description: | + e.g. 8.2.6 + validations: + required: true + + - type: input + id: codeigniter-version + attributes: + label: CodeIgniter4 Version + description: | + e.g. 4.4.3 + validations: + required: true + + - type: input + id: dea-rule-version + attributes: + label: CodeIgniter DEA Rule Version + description: | + e.g. 1.0.0-beta.1 + If you are not using the [latest version](https://github.com/datamweb/codeigniter-dea-rule/releases), please + check to see if the problem occurs with the latest version. + validations: + required: true + + - type: dropdown + id: operating-systems + attributes: + label: Which operating systems have you tested for this bug? + description: You may select more than one. + multiple: true + options: + - macOS + - Windows + - Linux + validations: + required: true + + - type: dropdown + id: server + attributes: + label: Which server did you use? + options: + - apache + - cli + - cli-server (PHP built-in webserver) + - cgi-fcgi + - fpm-fcgi + - phpdbg + validations: + required: true + + - type: input + id: database + attributes: + label: Database + description: e.g. MySQL 5.6, MariaDB 10.2, PostgreSQL 9.6 + validations: + required: true + + - type: textarea + id: description + attributes: + label: What happened? + placeholder: Tell us what you see! + validations: + required: true + + - type: textarea + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior. + validations: + required: true + + - type: textarea + attributes: + label: Expected Output + description: What do you expect to happen instead of this filed bug? + validations: + required: true + + - type: textarea + attributes: + label: Anything else? + description: | + Links? References? Anything that will give us more context about the issue you are encountering! + + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..c1b07e5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,9 @@ +blank_issues_enabled: false +contact_links: + - name: GitHub Discussions + url: https://github.com/datamweb/codeigniter-dea-rule/discussions + about: Please ask your support questions in the Discussions. Thanks! + + - name: CodeIgniter Slack channel + url: https://join.slack.com/t/codeigniterchat/shared_invite/zt-244xrrslc-l_I69AJSi5y2a2RVN~xIdQ + about: Engage with other members of the community in our Slack channel. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..e46c755 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,11 @@ +--- +name: Feature request +about: How to submit a feature request +title: '' +labels: '' +assignees: '' + +--- + +Please submit feature requests to [Discussions](https://github.com/datamweb/codeigniter-dea-rule/discussions/categories/ideas). +We use GitHub Issues to track bugs and planned work. diff --git a/.github/ISSUE_TEMPLATE/planned-work.md b/.github/ISSUE_TEMPLATE/planned-work.md new file mode 100644 index 0000000..4faa45e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/planned-work.md @@ -0,0 +1,10 @@ +--- +name: Planned work +about: Approved work planning +title: 'Dev: ' +labels: dev +assignees: '' + +--- + +Repo maintainers will create "issues" for planned work, so it can be tracked. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6fdf02a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,32 @@ +version: 2 +updates: +- package-ecosystem: composer + directory: "/" + schedule: + interval: daily + time: "08:30" + timezone: "Asia/Tehran" + open-pull-requests-limit: 5 + target-branch: "develop" + reviewers: + - "datamweb" + assignees: + - "datamweb" + labels: + - "dependa bot" + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + time: "08:30" + timezone: "Asia/Tehran" + open-pull-requests-limit: 5 + target-branch: "develop" + reviewers: + - "datamweb" + assignees: + - "datamweb" + labels: + - "dependa bot" + \ No newline at end of file diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..b2eb4ae --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,26 @@ +changelog: + exclude: + authors: + - dependabot + categories: + - title: Breaking Changes + labels: + - 'breaking change' + - title: Fixed Bugs + labels: + - bug + - title: New Features + labels: + - 'new feature' + - title: Enhancements + labels: + - enhancement + - title: Translations + labels: + - lang + - title: Refactoring + labels: + - refactor + - title: Others (Only for checking. Remove this category) + labels: + - "*" diff --git a/.github/workflows/deptrac.yml b/.github/workflows/deptrac.yml new file mode 100644 index 0000000..078f78b --- /dev/null +++ b/.github/workflows/deptrac.yml @@ -0,0 +1,72 @@ +name: Deptrac + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'depfile.yaml' + - '.github/workflows/deptrac.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'depfile.yaml' + - '.github/workflows/deptrac.yml' + +jobs: + build: + name: Dependency Tracing + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: phive + extensions: intl, json, mbstring, xml + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create Deptrac cache directory + run: mkdir -p build/ + + - name: Cache Deptrac results + uses: actions/cache@v3 + with: + path: build + key: ${{ runner.os }}-deptrac-${{ github.sha }} + restore-keys: ${{ runner.os }}-deptrac- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Trace dependencies + run: | + sudo phive --no-progress install --global --trust-gpg-keys B8F640134AB1782E,A98E898BB53EB748 qossmic/deptrac + deptrac analyze --cache-file=build/deptrac.cache diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..03473f9 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,27 @@ +name: docs +on: + push: + branches: + - develop + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + - name: Install Dependencies + run: | + pip3 install mkdocs-material + pip3 install mkdocs-git-revision-date-localized-plugin + pip3 install mkdocs-redirects + - name: Publish codeigniter DEA Rule Documentation + run: mkdocs gh-deploy --force diff --git a/.github/workflows/phpcpd.yml b/.github/workflows/phpcpd.yml new file mode 100644 index 0000000..9fe6d9e --- /dev/null +++ b/.github/workflows/phpcpd.yml @@ -0,0 +1,36 @@ +name: PHPCPD + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcpd.yml' + push: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcpd.yml' + +jobs: + build: + name: Code Copy-Paste Detection + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: phpcpd + extensions: dom, mbstring + coverage: none + + - name: Detect duplicate code + run: phpcpd src/ tests/ diff --git a/.github/workflows/phpcsfixer.yml b/.github/workflows/phpcsfixer.yml new file mode 100644 index 0000000..915633b --- /dev/null +++ b/.github/workflows/phpcsfixer.yml @@ -0,0 +1,59 @@ +name: PHPCSFixer + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcsfixer.yml' + push: + branches: + - develop + paths: + - '**.php' + - '.github/workflows/phpcsfixer.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Coding Standards + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: json, tokenizer + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Check code for standards compliance + run: vendor/bin/php-cs-fixer fix --verbose --ansi --dry-run --using-cache=no --diff diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..638291d --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,74 @@ +name: PHPStan + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpstan*' + - '.github/workflows/phpstan.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpstan*' + - '.github/workflows/phpstan.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Static Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpstan, phpunit + extensions: intl, json, mbstring, xml + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create PHPStan cache directory + run: mkdir -p build/phpstan + + - name: Cache PHPStan results + uses: actions/cache@v3 + with: + path: build/phpstan + key: ${{ runner.os }}-phpstan-${{ github.sha }} + restore-keys: ${{ runner.os }}-phpstan- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Run static analysis + run: vendor/bin/phpstan analyze diff --git a/.github/workflows/phpunit-lang.yml b/.github/workflows/phpunit-lang.yml new file mode 100644 index 0000000..dbd7f5a --- /dev/null +++ b/.github/workflows/phpunit-lang.yml @@ -0,0 +1,63 @@ +name: Language Unit Tests + +on: + pull_request: + branches: + - develop + paths: + - 'src/Language/**.php' + - '!src/Language/en/**.php' + - 'phpunit*' + - '.github/workflows/phpunit-lang.yml' + push: + branches: + - develop + paths: + - 'src/Language/**.php' + - '!src/Language/en/**.php' + - 'phpunit*' + - '.github/workflows/phpunit-lang.yml' + +jobs: + main: + name: Language Unit Tests + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: composer, phive, phpunit + extensions: intl, json, mbstring, gd, xdebug, xml, sqlite3 + coverage: xdebug + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Test with PHPUnit + run: vendor/bin/phpunit --verbose --no-coverage --testsuite lang + env: + TERM: xterm-256color + TACHYCARDIA_MONITOR_GA: enabled diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml new file mode 100644 index 0000000..0482ce2 --- /dev/null +++ b/.github/workflows/phpunit.yml @@ -0,0 +1,185 @@ +name: PHPUnit + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/phpunit.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'phpunit*' + - '.github/workflows/phpunit.yml' + +jobs: + main: + name: PHP ${{ matrix.php-versions }} - ${{ matrix.db-platforms }} - ${{ matrix.dependencies }} + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + matrix: + php-versions: ['7.4', '8.0', '8.1', '8.2'] + db-platforms: ['MySQLi', 'SQLite3'] + mysql-versions: ['5.7'] + dependencies: ['highest'] + include: + # MySQL 8.0 + - php-versions: '7.4' + db-platforms: MySQLi + mysql-versions: '8.0' + dependencies: 'highest' + # Lowest Dependency + - php-versions: '7.4' + db-platforms: MySQLi + mysql-versions: '5.7' + dependencies: 'lowest' + # Postgre + - php-versions: '7.4' + db-platforms: Postgre + mysql-versions: '5.7' + dependencies: 'highest' + # SQLSRV + - php-versions: '7.4' + db-platforms: SQLSRV + mysql-versions: '5.7' + dependencies: 'highest' + # OCI8 + - php-versions: '7.4' + db-platforms: OCI8 + mysql-versions: '5.7' + dependencies: 'highest' + + services: + mysql: + image: mysql:${{ matrix.mysql-versions }} + env: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: test + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + + postgres: + image: postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test + ports: + - 5432:5432 + options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3 + + mssql: + image: mcr.microsoft.com/mssql/server:2019-CU10-ubuntu-20.04 + env: + SA_PASSWORD: 1Secure*Password1 + ACCEPT_EULA: Y + MSSQL_PID: Developer + ports: + - 1433:1433 + options: --health-cmd="/opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q 'SELECT @@VERSION'" --health-interval=10s --health-timeout=5s --health-retries=3 + + oracle: + image: quillbuilduser/oracle-18-xe + env: + ORACLE_ALLOW_REMOTE: true + ports: + - 1521:1521 + options: --health-cmd="/opt/oracle/product/18c/dbhomeXE/bin/sqlplus -s sys/Oracle18@oracledbxe/XE as sysdba <<< 'SELECT 1 FROM DUAL'" --health-interval=10s --health-timeout=5s --health-retries=3 + + steps: + - name: Create database for MSSQL Server + if: matrix.db-platforms == 'SQLSRV' + run: sqlcmd -S 127.0.0.1 -U sa -P 1Secure*Password1 -Q "CREATE DATABASE test" + + - name: Install Oracle InstantClient + if: matrix.db-platforms == 'OCI8' + run: | + sudo apt-get install wget libaio1 alien + sudo wget https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm + sudo wget https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-devel-18.5.0.0.0-3.x86_64.rpm + sudo wget https://download.oracle.com/otn_software/linux/instantclient/185000/oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm + sudo alien oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm + sudo alien oracle-instantclient18.5-devel-18.5.0.0.0-3.x86_64.rpm + sudo alien oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm + sudo dpkg -i oracle-instantclient18.5-basic_18.5.0.0.0-4_amd64.deb oracle-instantclient18.5-devel_18.5.0.0.0-4_amd64.deb oracle-instantclient18.5-sqlplus_18.5.0.0.0-4_amd64.deb + echo "LD_LIBRARY_PATH=/lib/oracle/18.5/client64/lib/" >> $GITHUB_ENV + echo "NLS_LANG=AMERICAN_AMERICA.UTF8" >> $GITHUB_ENV + echo "C_INCLUDE_PATH=/usr/include/oracle/18.5/client64" >> $GITHUB_ENV + echo 'NLS_DATE_FORMAT=YYYY-MM-DD HH24:MI:SS' >> $GITHUB_ENV + echo 'NLS_TIMESTAMP_FORMAT=YYYY-MM-DD HH24:MI:SS' >> $GITHUB_ENV + echo 'NLS_TIMESTAMP_TZ_FORMAT=YYYY-MM-DD HH24:MI:SS' >> $GITHUB_ENV + + - name: Create database for Oracle Database + if: matrix.db-platforms == 'OCI8' + run: echo -e "ALTER SESSION SET CONTAINER = XEPDB1;\nCREATE BIGFILE TABLESPACE \"TEST\" DATAFILE '/opt/oracle/product/18c/dbhomeXE/dbs/TEST' SIZE 10M AUTOEXTEND ON MAXSIZE UNLIMITED SEGMENT SPACE MANAGEMENT AUTO EXTENT MANAGEMENT LOCAL AUTOALLOCATE;\nCREATE USER \"ORACLE\" IDENTIFIED BY \"ORACLE\" DEFAULT TABLESPACE \"TEST\" TEMPORARY TABLESPACE TEMP QUOTA UNLIMITED ON \"TEST\";\nGRANT CONNECT,RESOURCE TO \"ORACLE\";\nexit;" | /lib/oracle/18.5/client64/bin/sqlplus -s sys/Oracle18@localhost:1521/XE as sysdba + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: composer, phive, phpunit + extensions: intl, json, mbstring, gd, xdebug, xml, sqlite3, sqlsrv, oci8, pgsql + coverage: xdebug + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install ${{ env.COMPOSER_UPDATE_FLAGS }} --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update ${{ env.COMPOSER_UPDATE_FLAGS }} --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + env: + COMPOSER_UPDATE_FLAGS: ${{ matrix.dependencies == 'lowest' && '--prefer-lowest' || '' }} + + - name: Test with PHPUnit + run: vendor/bin/phpunit --verbose --coverage-text --testsuite main + env: + DB: ${{ matrix.db-platforms }} + TERM: xterm-256color + TACHYCARDIA_MONITOR_GA: enabled + + - if: matrix.php-versions == '8.0' + name: Run Coveralls + continue-on-error: true + run: | + sudo phive --no-progress install --global --trust-gpg-keys E82B2FB314E9906E php-coveralls + php-coveralls --verbose --coverage_clover=build/phpunit/clover.xml --json_path build/phpunit/coveralls-upload.json + env: + COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_PARALLEL: true + COVERALLS_FLAG_NAME: PHP ${{ matrix.php-versions }} - ${{ matrix.db-platforms }} + + coveralls: + needs: [main] + name: Coveralls Finished + runs-on: ubuntu-latest + steps: + - name: Upload Coveralls results + uses: coverallsapp/github-action@master + continue-on-error: true + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 0000000..57ad2c7 --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,70 @@ +name: Psalm + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'psalm*' + - '.github/workflows/psalm.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'psalm*' + - '.github/workflows/psalm.yml' + +jobs: + build: + name: Psalm Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: phpstan, phpunit + extensions: intl, json, mbstring, xml + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Create Psalm cache directory + run: mkdir -p build/psalm + + - name: Cache Psalm results + uses: actions/cache@v3 + with: + path: build/psalm + key: ${{ runner.os }}-psalm-${{ github.sha }} + restore-keys: ${{ runner.os }}-psalm- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Run Psalm analysis + run: vendor/bin/psalm diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml new file mode 100644 index 0000000..7ad6534 --- /dev/null +++ b/.github/workflows/rector.yml @@ -0,0 +1,66 @@ +name: Rector + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'rector.php' + - '.github/workflows/rector.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - 'rector.php' + - '.github/workflows/rector.yml' + +jobs: + build: + name: PHP ${{ matrix.php-versions }} Rector Analysis + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + strategy: + fail-fast: false + matrix: + php-versions: ['7.4', '8.0', '8.1'] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpstan + extensions: intl, json, mbstring, xml + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Analyze for refactoring + run: | + composer global require --dev rector/rector:^0.15.1 + rector process --dry-run --no-progress-bar diff --git a/.github/workflows/unused.yml b/.github/workflows/unused.yml new file mode 100644 index 0000000..6341fbb --- /dev/null +++ b/.github/workflows/unused.yml @@ -0,0 +1,58 @@ +name: Unused + +on: + pull_request: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - '.github/workflows/unused.yml' + push: + branches: + - develop + paths: + - '**.php' + - 'composer.*' + - '.github/workflows/unused.yml' + +jobs: + build: + name: Unused Package Detection + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: composer, composer-unused + extensions: intl, json, mbstring, xml + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get composer cache directory + run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: ${{ env.COMPOSER_CACHE_FILES_DIR }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + if [ -f composer.lock ]; then + composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader + else + composer update --no-progress --no-interaction --prefer-dist --optimize-autoloader + fi + + - name: Detect unused packages + run: composer-unused -vvv --output-format=github --ansi --no-interaction --no-progress diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa2b298 --- /dev/null +++ b/.gitignore @@ -0,0 +1,112 @@ +#------------------------- +# Operating Specific Junk Files +#------------------------- + +# OS X +.DS_Store +.AppleDouble +.LSOverride + +# OS X Thumbnails +._* + +# Windows image file caches +Thumbs.db +ehthumbs.db +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Linux +*~ + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +#------------------------- +# Environment Files +#------------------------- +# These should never be under version control, +# as it poses a security risk. +.env +.vagrant +Vagrantfile + +#------------------------- +# Temporary Files +#------------------------- +php_errors.log + +#------------------------- +# Test Files +#------------------------- +tests/coverage* + +# Don't save phpunit under version control. +phpunit + +#------------------------- +# Composer +#------------------------- +vendor/ +composer.lock + +#------------------------- +# MkDocs +#------------------------- +site/ + +#------------------------- +# IDE / Development Files +#------------------------- + +# Modules Testing +_modules/* + +# phpenv local config +.php-version + +# Jetbrains editors (PHPStorm, etc) +.idea/ +*.iml + +# Netbeans +nbproject/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +nb-configuration.xml +.nb-gradle/ + +# Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache +*.sublime-workspace +*.sublime-project +.phpintel +/api/ + +# Visual Studio Code +.vscode/ + +/results/ +/phpunit*.xml +/.phpunit.*.cache + +/.php-cs-fixer.php \ No newline at end of file diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..6fc6843 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,45 @@ + + * + * 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 PhpCsFixer\Finder; + +$finder = Finder::create() + ->files() + ->in([ + __DIR__ . '/src/', + __DIR__ . '/tests/', + ]) + ->exclude('build') + ->append([ + __FILE__, + __DIR__ . '/rector.php', + ]); + +$overrides = [ + 'declare_strict_types' => true, + 'void_return' => true, +]; + +$options = [ + 'finder' => $finder, + 'cacheFile' => 'build/.php-cs-fixer.cache', +]; + +return Factory::create(new CodeIgniter4(), $overrides, $options)->forLibrary( + 'CodeIgniter-DEA-Rule', + 'Datamweb', + 'pooya_parsa_dadashi@yahoo.com', + 2023, +); diff --git a/LICENSE b/LICENSE index d27e952..87dd396 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Pooya Parsa +Copyright (c) 2023 Pooya Parsa Dadashi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b4ffb5 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +[Farsi](./README.fa-IR.md) | English +## CodeIgniter DEA Rule +[![PHPUnit](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml) +[![PHPStan](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml) +[![Rector](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml) +[![Psalm](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml) +[![PHPCSFixer](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcsfixer.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcsfixer.yml) +[![PHPCPD](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcpd.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcpd.yml) +[![Unused](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml) +[![Deptrac](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml) + + +

CodeIgniter DEA Rule

+ +[![Latest Stable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rulev?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Total Downloads](http://poser.pugx.org/datamweb/codeigniter-dea-ruledownloads?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Latest Unstable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rulev/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![License](http://poser.pugx.org/datamweb/codeigniter-dea-rulelicense?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![PHP Version Require](http://poser.pugx.org/datamweb/codeigniter-dea-rulerequire/php?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) + + +**`CodeIgniter DEA Rule`** helps you to validate the email provided by the user and to deal with it if the email was of Temporary & Disponsable Emails(DEA) use type. +**`CodeIgniter DEA Rule`** is actually a [custom validation rule](https://codeigniter.com/user_guide/libraries/validation.html?#creating-custom-rules), but with more features than a rule. + +**`CodeIgniter DEA Rule`** allows you to check emails in a comprehensive list of Temporary & Disponsable Emails(DEA), but it is not satisfied with this amount, you can create a custom database(file)/list of emails that you recognize as disposable. + +In this project, as much as possible, the *Code Quality Control Tools used by the Codeigniter4 Core Team* have been used. + +

CodeIgniter DEA Rule

+ + +## Acknowledgements + +Every open-source project depends on it's contributors to be a success. The following users have +contributed in one manner or another in making **`CodeIgniter DEA Rule`**: + + + Contributors + \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..db83cd9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,26 @@ +# Security Policy + +The development team and community take all security issues seriously. **Please do not make public any uncovered flaws.** + +## Reporting a Vulnerability + +Thank you for improving the security of our code! Any assistance in removing security flaws will be acknowledged. + +**Please report security flaws by emailing the development team directly: security@codeigniter4.ir**. + +The lead maintainer will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating +the next steps in handling your report. After the initial reply to your report, the security team will endeavor to keep you informed of the +progress towards a fix and full announcement, and may ask for additional information or guidance. + +## Disclosure Policy + +When the security team receives a security bug report, they will assign it to a primary handler. +This person will coordinate the fix and release process, involving the following steps: + +- Confirm the problem and determine the affected versions. +- Audit code to find any potential similar problems. +- Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible. + +## Comments on this Policy + +If you have suggestions on how this process could be improved please submit a Pull Request. diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000..5492957 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,2 @@ +# Upgrade Guide + diff --git a/admin/pre-commit b/admin/pre-commit new file mode 100644 index 0000000..296e140 --- /dev/null +++ b/admin/pre-commit @@ -0,0 +1,52 @@ +#!/bin/sh + +PROJECT=`php -r "echo dirname(dirname(dirname(realpath('$0'))));"` +STAGED_PHP_FILES=`git diff --cached --name-only --diff-filter=ACMR HEAD | grep \\\\.php$` + +echo "Starting CodeIgniter precommit..." + +if [ "$STAGED_PHP_FILES" != "" ]; then + echo "Linting PHP code..." + for FILE in $STAGED_PHP_FILES; 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..." + + 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 PHP CS Fixer..." + + if [ -d /proc/cygdrive ]; then + ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff + else + php ./vendor/bin/php-cs-fixer fix --verbose --dry-run --diff + fi + + if [ $? != 0 ]; then + echo "Some files are not following the coding standards. Please fix them before commit (try 'composer style')." + exit 1 + fi +fi + +exit $? diff --git a/admin/setup.sh b/admin/setup.sh new file mode 100644 index 0000000..2e0075e --- /dev/null +++ b/admin/setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +# Install a pre-commit hook that +# automatically runs phpcs to fix styles +cp admin/pre-commit .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit \ No newline at end of file diff --git a/composer-unused.php b/composer-unused.php new file mode 100644 index 0000000..95e170b --- /dev/null +++ b/composer-unused.php @@ -0,0 +1,15 @@ +setAdditionalFilesFor('codeigniter4/framework', [ + __DIR__ . '/vendor/codeigniter4/framework/system/Helpers/*.php', + ]); +}; diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..0ca3d4c --- /dev/null +++ b/composer.json @@ -0,0 +1,85 @@ +{ + "name": "datamweb/codeiegniter-dea-rule", + "description": "Temporary & Disponsable Emails Validation In CodeIgniter4", + "license": "MIT", + "type": "library", + "keywords": [ + "codeigniter", + "temporary_email", + "disponsable_email", + "rule", + "validation" + ], + "authors": [ + { + "name": "Pooya Parsa Dadashi", + "email": "Pooya_parsa_dadashi@yahoo.com", + "role": "Developer" + } + ], + "homepage": "https://github.com/datamweb/codeiegniter-dea-rule", + "require": { + "php": "^7.4.3 || ^8.0" + }, + "require-dev": { + "codeigniter4/devkit": "^1.0", + "codeigniter/phpstan-codeigniter": "^1.4", + "codeigniter4/framework": "^4.2.7", + "mikey179/vfsstream": "^1.6.7", + "mockery/mockery": "^1.0", + "rector/rector": "^0.18.6" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "Datamweb\\CodeIgniterDEARule\\": "src" + }, + "exclude-from-classmap": [ + "**/Database/Migrations/**" + ] + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests", + "Tests\\Support\\": "tests/_support" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } + }, + "scripts": { + "post-update-cmd": [ + "bash admin/setup.sh" + ], + "analyze": [ + "phpstan analyze", + "psalm", + "rector process --dry-run" + ], + "sa": "@analyze", + "ci": [ + "Composer\\Config::disableProcessTimeout", + "@cs", + "@deduplicate", + "@inspect", + "@analyze", + "@test" + ], + "cs": "php-cs-fixer fix --ansi --verbose --dry-run --diff", + "cs-fix": "php-cs-fixer fix --ansi --verbose --diff", + "deduplicate": "phpcpd src/", + "inspect": "deptrac analyze --cache-file=build/deptrac.cache", + "mutate": "infection --threads=2 --skip-initial-tests --coverage=build/phpunit", + "style": "@cs-fix", + "test": "phpunit" + }, + "support": { + "forum": "https://github.com/datamweb/codeigniter-dea-rule/discussions", + "source": "https://github.com/datamweb/codeigniter-dea-rule", + "issues": "https://github.com/datamweb/codeigniter-dea-rule/issues", + "docs": "https://www.dea-rule.codeigniter4.ir" + } +} diff --git a/deptrac.yaml b/deptrac.yaml new file mode 100644 index 0000000..b94081d --- /dev/null +++ b/deptrac.yaml @@ -0,0 +1,157 @@ +parameters: + paths: + - ./src/ + - ./vendor/codeigniter4/framework/system/ + exclude_files: + - '#.*test.*#i' + layers: + - name: Model + collectors: + - type: bool + must: + - type: className + regex: .*[A-Za-z]+Model$ + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Model + collectors: + - type: bool + must: + - type: className + regex: .*[A-Za-z]+Model$ + - type: directory + regex: vendor/.* + - name: Controller + collectors: + - type: bool + must: + - type: className + regex: .*\/Controllers\/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Controller + collectors: + - type: bool + must: + - type: className + regex: .*\/Controllers\/.* + - type: directory + regex: vendor/.* + - name: Config + collectors: + - type: bool + must: + - type: directory + regex: src/Config/.* + must_not: + - type: className + regex: .*Services + - type: directory + regex: vendor/.* + - name: Vendor Config + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Config/.* + must_not: + - type: className + regex: .*Services + - name: Entity + collectors: + - type: bool + must: + - type: directory + regex: src/Entities/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor Entity + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Entities/.* + - name: View + collectors: + - type: bool + must: + - type: directory + regex: src/Views/.* + must_not: + - type: directory + regex: vendor/.* + - name: Vendor View + collectors: + - type: bool + must: + - type: directory + regex: vendor/.*/Views/.* + - name: Service + collectors: + - type: className + regex: .*Services.* + ruleset: + Entity: + - Config + - Model + - Service + - Vendor Config + - Vendor Entity + - Vendor Model + Config: + - Model + - Service + - Vendor Config + Model: + - Config + - Entity + - Service + - Vendor Config + - Vendor Entity + - Vendor Model + Service: + - Config + - Vendor Config + + # Ignore anything in the Vendor layers + Vendor Model: + - Config + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Controller: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Config: + - Config + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor Entity: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + Vendor View: + - Service + - Vendor Config + - Vendor Controller + - Vendor Entity + - Vendor Model + - Vendor View + skip_violations: diff --git a/docs/assets/css/dark_mode.css b/docs/assets/css/dark_mode.css new file mode 100644 index 0000000..8bc72d6 --- /dev/null +++ b/docs/assets/css/dark_mode.css @@ -0,0 +1,74 @@ +[data-md-color-scheme="slate"] { + --md-primary-fg-color: #6a290d; + --md-primary-fg-color--light: #8d7474; + --md-primary-fg-color--dark: #6d554d; + + .hljs-title, + .hljs-title.class_, + .hljs-title.class_.inherited__, + .hljs-title.function_ { + color: #c9a69b; + } + + .hljs-meta .hljs-string, + .hljs-regexp, + .hljs-string { + color: #a3b4c7; + } + + .hljs-attr, + .hljs-attribute, + .hljs-literal, + .hljs-meta, + .hljs-number, + .hljs-operator, + .hljs-selector-attr, + .hljs-selector-class, + .hljs-selector-id, + .hljs-variable { + color: #c1b79f; + } + + .hljs-doctag, + .hljs-keyword, + .hljs-meta .hljs-keyword, + .hljs-template-tag, + .hljs-template-variable, + .hljs-type, + .hljs-variable.language_ { + color: #c97100; + } + + .hljs-subst { + color: #ddba52 + } + + .md-typeset .note > .admonition-title, + .md-typeset .note > summary { + background-color: #0000001a; + } + + .md-typeset .admonition.note, + .md-typeset details.note { + border-color: #675647; + } + + .md-typeset .note > .admonition-title:before, + .md-typeset .note > summary:before { + background-color: #65686d; + -webkit-mask-image: var(--md-admonition-icon--note); + mask-image: var(--md-admonition-icon--note); + } + + .md-typeset .admonition.warning, + .md-typeset details.warning { + border-color: #776144; + } + + .md-typeset .warning > .admonition-title:before, + .md-typeset .warning > summary:before { + background-color: #d9913bc2; + -webkit-mask-image: var(--md-admonition-icon--warning); + mask-image: var(--md-admonition-icon--warning); + } +} diff --git a/docs/assets/favicon.ico b/docs/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a725c10e725181a53bd893fdae6e8d39370b8268 GIT binary patch literal 5087 zcmeHLWmlAs)4rGPZb<pF90Ud)*{GXMbkr~e5EULLK zrJ>$`%u7dE9yH(274nbZx~mv@0RaBLdVF#akeN*b0BBcQ>Uv85lFKR-|Fi#1;Q!SG z%4Wp_{;mFlw~nSRz<@`c#0(^iOA}w3)uC>E(VQM1qA>XnQZTTm(d*+uU%arcYyu7y z|B{Eb5qt_Nk@&TQOZz)f`Al@O)(Gcli$>dLhRV-wK`ifvJ0^ekSfQD3f`V{F&VCP3 z0lRhUXzHBh(nzQ(^ zo^$$!^7$H^B{FO1o%nKbMCOx^E;1KNHR=w!9AI9pK}qNNSiQ}rZ>cMxpBW9H-PZal z8M0Pot8eM%y2b&3_zgr+PR~F4Aje4-2BYe&rm?nIth$QDN&?Gikh>FT)#>S|D|La> za3vg*H5{Z>l?iD%1%uM(71J_oz6lynlD0NC z^vG__d19Ad6oI2|9Q3|PLkNMVxPV~o_Hrda5JUok7y{MuAz?I*xQ5hsFzo~N7;*hza2$BZg$1^hpA zJM+_cSK|W?7n08WIEF8G(PeowJJbG1l{vfvF~6+c6oXb{pnyX2aComrG6eVzZTs-M zC=A5>#S-5$UHWYV+88goNpiiZX86u0?tY`z7z_*9XNYIuodsStz?vDs0d9FZ6_V^r zXA@H?mjWct%++OE)x=PRGL{S*GTY(|ha?MAn565PCd(26w9(u{EbCQ;chEZMXW>8f z(TfRMfXsNS zYiLzxnqBS*7Ybth0wF!Q@s}Sxkq>0@)iSe$|H19tA*p#xN`*wBhCQ>0bu>hP)FfZ~ z9a9e>lFd2(S$}rlMV|kiMTJnGwIdzddw1v5U+>eOuFJGgnUwGs|NZ!{d)JIZtV27g zEa9vbzObUBC_k#7sU|g(WeZCV)gM2n6HoHeY$`;6)}#XWc8KJ%Lpvd=D>4tI>iSb3 zA3CCri|WUm^X!CByhYumN5QExtF|CFP+Kc}EZdP`&&SWN(#TqEstQroj0kI$N}1xp zTbT}R7{q%6EE{eV3a3qsYEo@mEsX{ZT|AxF5=tW#Iq-x+v3L3ooqbu;kJ+gJ^QGlaAImES_sM519~q<+uupb{1z zXM2~OGFnj^uFf~NORO(%uUOkUX9s?*R{WM`v9s8lWj~aj9?km{{o_T7z-#-9(X8bb z0Ziz|ET-&nGZ;6;rOZbZjC?D3tj8|bv}|CU=h^1Sus^nJW; z<#Im7gDDzY8%r|vC-s5pJKIQcjHwnz z>4&7U${gh`adTp^R_T&`)RK6WUM=UOXiT;QI&~t79c7F=lI$SVdz~HQH?^?xpmzcVTZ1$hVvO$6M z1O8A2Vo$9NA1)tEgo`q&ldDT@Wy!R0>u<1Y+RbN8`x$->MhD$4yps)c?lGC~;`syvkKA0mljCRJ#|P3&{iq}&qcvTtRB0Ta4Kqg1 zjyRCkj|m5msZvtu#d@(YUT(2;HN`sX91vW|UVKeHz>S}W?U|~HxgEr(TTQ`{*Gg)C zM^Iqi)tH#&hS-KjYUcr8IN1Y;6YGV@fF~Z!)8w7gLq|4Vf0mZ{Ms!-1(eRNat;Wuu z#?>BTT44I8v?(ap1ECqvVo>jWJpmFX!TJr&U8{}GoBz*YS=ZE=v$NE>!6&ILd$paB zcGS0>XlZOUOWUYJ#$a9g%X;o^2B4}L&Qean2E?2*jdQHzJ-v9wO591v46;Z6y1_T9 zGL%$+^#i+SFu+$Sw9f*!LD^(w5*aJkC!`nVKqBu-1({?(pAV)(5{2d}G6&paeA_*& z2^%x-mU`%_EU?t~l%}rt#T_DA3OtAMnqt<2OQS5x11D`4t*%p=jqXC2sZ~DM<3hV} z#>_Z&779A;LQ^U!5j3lEaAH=5<>fvqy+;wt%;w>5yl<#1U(HpnYoI*QDKIAj$Hnj5p;AQk(&af2#8{IVCTQGHC!bHpkRuE$x@X zoYH&+oBV6et4)LyO?-WKRw{24qWEE*Q{3$P@4lv89@}B-9NrC>1nk_Vu`I(b%M+Md z?B>49et2B-i~U+_;Nn^ML6Q&Lh3$)4^&bz^ZgW?23HiyEx_o%;(&@)-(*dfS#=5Zy8D;OnklK6Ed4 zv2*-U=P{4EMkDI8HcF=}#NZrLptZGvI*u{1wjNvqn$Y_z1xEy3r^s;(9A*130)WIdm4n#+~IaZex7{W(zVWH`^(E+BNMFfe*>8?`_4fL+?n z-ToyYCxLRLw>|gDL8d9U_|@7qgb?DxMWy#wn+eB2z-(;5BhU_7VPn)+6wuT~Un&aI zS`dIUq%h$a*S;Mp_Qh|lyJr2WU}Gh3rDhXfWToWJrZ+TK9_-k#ijtdBD-TH2a;2C| z8|omB@Z@J5BCy+EqrSZ32@<{`vGDo`jVx?jD6#1#D_^c!8xduV`4O~VbDJHh8m;BD zrz`}=DPmU6r%$8=C)b>v&o+4GsQ}WL9x9n`7=@{nj&$Nr6NCGeC0GvR!+`rzCpMk0 zo(y}DLP?K>DJzu8*@KP0J0)I-hj*B+m~^zQ;2cKQn5&>0maGv^g^Y>TIgpL^DHw7; znk}8S5Rx23&YV=LeCY^3VO7r9qKHhjZ9f85a6OLPQw~%x_`AxIOUKH4XV)pf!0yL< z(Eb}4w9%bSKcDN|1DO)1Fh2f$EIdIjX35k0ZX#fA{w=TIuqlSkt6YS-C9$EF@8yBr z{0;3uoYWBJ+;6;|bYDIu&_idjz-*m2HyVAeBJmrVEnefgZhY2a6=J5Li6zWsjRc#pK154+ZGOYWVE%kS?P+>23dBgZBD zR0}__PoyIj_t`Fl$4&1-&8%GX3xw*=o3vA!`UEUo+RS?9o~Y2u87$$oG83z#!$|~O z(r~bB(rbHdV3=lOyu}HI&2f)VV5~xgFe`rfXq;+SuEvQ=d@)5%g!CLOMQAveg=>9V zqX=)v$XZ*K@=WH$Rv2$d10Ha*u-(an(4vm%rImJk{zU|Q{AfMH!QdDmyQN(Wf2Ux= zZs;`kg3@?1`~ebg(M_SX|Ccp8I7?o zf@e^_d@}L{Q=9nCBXfXLVR3nL{(?yKRiBa4ig~tV;FZO8=7tl|DE1+aD`zs_P`}$r z=a_W8fw=t&WhS0#joWM2$hbs?B1vxWK@)-Fa{-*V*_Z?&nQOc8`+?Aq2(QCtmg?#MhMVHo*fAdc-9}&&-RpeE@&D>J*E!^L)%ncWt{W5g*v5}*T{d2|cibR*B zgy{K}_R9B1miK`Z0`?A?2PjnC6H)_fh52`j39Tf~eU0iFwTx9ejqNODOWhgy5|Ps# z1d|i-1i<<-WeSLlB8^S+$SO1I + + + + + + + + + + diff --git a/docs/assets/hljs.js b/docs/assets/hljs.js new file mode 100644 index 0000000..6f9098a --- /dev/null +++ b/docs/assets/hljs.js @@ -0,0 +1,3 @@ +document.addEventListener('DOMContentLoaded', (event) => { + hljs.highlightAll(); +}); diff --git a/docs/assets/js/hljs.js b/docs/assets/js/hljs.js new file mode 100644 index 0000000..6f9098a --- /dev/null +++ b/docs/assets/js/hljs.js @@ -0,0 +1,3 @@ +document.addEventListener('DOMContentLoaded', (event) => { + hljs.highlightAll(); +}); diff --git a/docs/how_to_use.md b/docs/how_to_use.md new file mode 100644 index 0000000..43b56e6 --- /dev/null +++ b/docs/how_to_use.md @@ -0,0 +1,93 @@ +# How to Use + +In general, after installing **`codeigniter-dea-rule`**, a new rule is added to Codegniter's validation rules, named `is_temp_email`. From now on, you can use it like other CI4 rules. + +`is_temp_email` rule could now be used just like any other rule: + +| Rule | Parameter | Description | Example | +|----------------|-----------| -----------------------------------------------------------| --------------| +| `is_temp_email`| No | Fails if the field contains a Disposable Temporary E-mail. |`is_temp_email`| + +## How To Use Rule + + + + +```php +// e.g. +$validation->setRules([ + 'email' => 'required|max_length[19]|is_temp_email', +]); +``` + +```php +// e.g. +// In Controller. + +if (! $this->validate([ + 'email' => 'required|max_length[19]|is_temp_email', + 'password' => 'required|min_length[10]', +])) { + // The validation failed. + return view('login', [ + 'errors' => $this->validator->getErrors(), + ]); +} + +// The validation was successful. +``` + +```php +// ... + +$rules = [ + 'email' => 'required|max_length[254]|valid_email|is_temp_email', + 'password' => 'required|max_length[255]|min_length[10]', + 'passconf' => 'required|max_length[255]|matches[password]', +]; + +// ... +``` + +## Practical Examples For CodeIgniter Shield + +As you know, [CodeIgniter Shield](https://github.com/codeigniter4/shield) allows you to easily apply your [custom validation rules](https://codeigniter4.github.io/shield/customization/validation_rules) to fields. In the example below, we have shown how to use `is_temp_email` rule for the user registration form. +Add the $registration property with the all validation rules and `is_temp_email` for registration in **app/Config/Validation.php**: +```php +//-------------------------------------------------------------------- +// Rules For Registration +//-------------------------------------------------------------------- +public $registration = [ + 'username' => [ + 'label' => 'Auth.username', + 'rules' => [ + 'required', + 'max_length[30]', + 'min_length[3]', + 'regex_match[/\A[a-zA-Z0-9\.]+\z/]', + 'is_unique[users.username]', + ], + ], + 'email' => [ + 'label' => 'Auth.email', + 'rules' => [ + 'required', + 'max_length[254]', + 'valid_email', + 'is_unique[auth_identities.secret]', + 'is_temp_email', // just add this line + ], + ], + 'password' => [ + 'label' => 'Auth.password', + 'rules' => 'required|max_byte[72]|strong_password[]', + 'errors' => [ + 'max_byte' => 'Auth.errorPasswordTooLongBytes' + ] + ], + 'password_confirm' => [ + 'label' => 'Auth.passwordConfirm', + 'rules' => 'required|matches[password]', + ], +]; +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..cdac2a5 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,34 @@ +## CodeIgniter DEA Rule +[![PHPUnit](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml) +[![PHPStan](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml) +[![Rector](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml) +[![Psalm](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml) +[![PHPCSFixer](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcsfixer.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcsfixer.yml) +[![PHPCPD](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcpd.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcpd.yml) +[![Unused](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml) +[![Deptrac](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml) + + +

CodeIgniter DEA Rule

+ +[![Latest Stable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Total Downloads](http://poser.pugx.org/datamweb/codeigniter-dea-rule/downloads?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Latest Unstable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![License](http://poser.pugx.org/datamweb/codeigniter-dea-rule/license?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![PHP Version Require](http://poser.pugx.org/datamweb/codeigniter-dea-rule/require/php?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) + + +**`CodeIgniter DEA Rule`** helps you to validate the email provided by the user and to deal with it if the email was of Temporary & Disponsable Emails(DEA) use type. +**`CodeIgniter DEA Rule`** is actually a [custom validation rule](https://codeigniter.com/user_guide/libraries/validation.html?#creating-custom-rules), but with more features than a rule. + +**`CodeIgniter DEA Rule`** allows you to check emails in a comprehensive list of Temporary & Disponsable Emails(DEA), but it is not satisfied with this amount, you can create a custom database of emails that you recognize as disposable. + +In this project, as much as possible, the *Code Quality Control Tools used by the Codeigniter4 Core Team* have been used. + +

CodeIgniter DEA Rule

+ + +## Acknowledgements + +Every open-source project depends on it's contributors to be a success. The following users have +contributed in one manner or another in making **`CodeIgniter DEA Rule`**: + + + Contributors + \ No newline at end of file diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..c607949 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,49 @@ +# Installation + +These instructions assume that you have already installed the [**CodeIgniter 4 app starter**](https://codeigniter.com/user_guide/installation/installing_composer.html#installation) as the basis for your new project, set up your `.env` file, and created a database that you can access via the Spark CLI script. + +## Requirements + +- [Composer](https://getcomposer.org) _If you install through Composer_. +- [Codeigniter](https://codeigniter4.github.io/CodeIgniter4/installation/installing_composer.html#installation) **v4.4.3** or later +- PHP 7.4.3+ + +## Composer Installation + +Installation is done through [Composer](https://getcomposer.org). The example assumes you have it installed globally. +If you have it installed as a phar, or otherwise you will need to adjust the way you call composer itself. + +```console +composer require datamweb/codeigniter-dea-rule +``` + +## Manually Installation + +You can manually install **`codeigniter-dea-rule`** by extracting the project file to path `app\ThirdParty\codeigniter-dea-rule` and then adding: + +```php +public $psr4 = [ + // add this line + 'Datamweb\\CodeIgniterDEARule' => APPPATH . 'ThirdParty/codeigniter-dea-rule/src', +]; +``` +to the app\Config\Autoload.php file, however we do **not recommend** this. Please use the Composer. + +## Add Required Table +**`codeigniter-dea-rule`** After the efforts of users, it collects information with DEA emails, so that the administrator can have accurate statistical information. +These attempts are stored in the `logs_temp_email` table. Therefore, there is a need to create a new table to store this data. +Run the following command to create the desired table. + +```php +php spark migrate -n Datamweb\CodeIgniterDEARule +``` + +## Publish DEARule Config in app + +**`codeigniter-dea-rule`** uses a configuration file named **DEARule.php**. Therefore, by setting it, if you update for a new version, file **DEARule.php** may be overwritten, which causes the settings you have already made to be lost. + +To solve this problem, run the following command to create a new configuration file in path **app/Config/DEARule.php**. From now on, you should make all the settings in file **app/Config/DEARule.php** Not **vendor\datamweb\codeigniter-dea-rule\src\Config\DEARule.php**. + +```console +php spark dea-rule:publish +``` diff --git a/infection.json.dist b/infection.json.dist new file mode 100644 index 0000000..7badcc6 --- /dev/null +++ b/infection.json.dist @@ -0,0 +1,19 @@ +{ + "source": { + "directories": [ + "src/" + ], + "excludes": [ + "Config", + "Database/Migrations", + "Views" + ] + }, + "logs": { + "text": "build/infection.log" + }, + "mutators": { + "@default": true + }, + "bootstrap": "vendor/codeigniter4/framework/system/Test/bootstrap.php" +} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..d4aa214 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,85 @@ +site_name: CodeIgniter DEA Rule +site_description: Documentation for Temporary & Disponsable Emails Validation In CodeIgniter4 + +theme: + name: material + logo: assets/flame.svg + favicon: assets/favicon.ico + icon: + repo: fontawesome/brands/github + font: + text: Raleway + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep orange + accent: orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep orange + accent: orange + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - toc.integrate + - content.code.copy + - navigation.footer + - content.action.edit + - navigation.top + - search.suggest + - search.highlight + - search.share + +extra: + homepage: https://codeigniter4.ir + generator: false + + social: + - icon: material/github + link: https://github.com/datamweb/codeigniter-dea-rule + name: GitHub + - icon: material/twitter + link: https://twitter.com/datamweb + name: X + - icon: material/forum + link: https://forum.codeigniter.com + name: Forum Codeigniter + - icon: material/slack + link: https://join.slack.com/t/codeigniterchat/shared_invite/zt-244xrrslc-l_I69AJSi5y2a2RVN~xIdQ + name: Slack + + +repo_url: https://github.com/datamweb/codeigniter-dea-rule +edit_uri: edit/develop/docs/ +copyright: Copyright © 2023 Pooya Parsa Dadashi(Datamweb). + +markdown_extensions: + - pymdownx.superfences + - pymdownx.highlight: + use_pygments: false + - admonition + - pymdownx.details + +extra_css: + - https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/styles/default.min.css + - assets/css/dark_mode.css + +extra_javascript: + - https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.8.0/build/highlight.min.js + - assets/js/hljs.js + +plugins: + - search + - git-revision-date-localized: + enable_creation_date: true + +nav: + - Home: index.md + - Installation: install.md + - How To Use: how_to_use.md \ No newline at end of file diff --git a/phpstan-baseline.php b/phpstan-baseline.php new file mode 100644 index 0000000..145db48 --- /dev/null +++ b/phpstan-baseline.php @@ -0,0 +1,10 @@ + '#^Property Datamweb\\\\CodeIgniterDEARule\\\\Database\\\\Migrations\\\\LogsTempEmailMigration\\:\\:\\$attributes type has no value type specified in iterable type array\\.$#', +// 'count' => 1, +// 'path' => __DIR__ . '/src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php', +// ]; +return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..f925077 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,24 @@ +includes: + - phpstan-baseline.php +parameters: + tmpDir: build/phpstan + level: 6 + paths: + - src/ + - tests/ + bootstrapFiles: + - vendor/codeigniter4/framework/system/Test/bootstrap.php + + universalObjectCratesClasses: + - CodeIgniter\Entity + - CodeIgniter\Entity\Entity + - Faker\Generator + scanDirectories: + - vendor/codeigniter4/framework/system/Helpers + dynamicConstantNames: + - APP_NAMESPACE + - CI_DEBUG + - ENVIRONMENT + - CodeIgniter\CodeIgniter::CI_VERSION + codeigniter: + checkArgumentTypeOfFactories: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..609c716 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,103 @@ + + + + + + ./src/ + + + ./src/Config + ./src/Language + + + + + + + + + + + + + ./tests + + + + + + + + + 0.50 + + + 30 + + + 2 + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 0000000..d5f56a3 --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..34d358b --- /dev/null +++ b/psalm.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/psalm_autoload.php b/psalm_autoload.php new file mode 100644 index 0000000..d1fab7d --- /dev/null +++ b/psalm_autoload.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use Rector\CodeQuality\Rector\BooleanAnd\SimplifyEmptyArrayCheckRector; +use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector; +use Rector\CodeQuality\Rector\Expression\InlineIfToExplicitIfRector; +use Rector\CodeQuality\Rector\Foreach_\UnusedForeachValueToArrayKeysRector; +use Rector\CodeQuality\Rector\FuncCall\ChangeArrayPushToArrayAssignRector; +use Rector\CodeQuality\Rector\FuncCall\SimplifyRegexPatternRector; +use Rector\CodeQuality\Rector\FuncCall\SimplifyStrposLowerRector; +use Rector\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector; +use Rector\CodeQuality\Rector\If_\CombineIfRector; +use Rector\CodeQuality\Rector\If_\ShortenElseIfRector; +use Rector\CodeQuality\Rector\If_\SimplifyIfElseToTernaryRector; +use Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector; +use Rector\CodeQuality\Rector\Ternary\UnnecessaryTernaryExpressionRector; +use Rector\CodingStyle\Rector\ClassMethod\FuncGetArgsToVariadicParamRector; +use Rector\CodingStyle\Rector\ClassMethod\MakeInheritedMethodVisibilitySameAsParentRector; +use Rector\CodingStyle\Rector\FuncCall\CountArrayToEmptyArrayComparisonRector; +use Rector\Config\RectorConfig; +use Rector\Core\ValueObject\PhpVersion; +use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPromotedPropertyRector; +use Rector\EarlyReturn\Rector\Foreach_\ChangeNestedForeachIfsToEarlyContinueRector; +use Rector\EarlyReturn\Rector\If_\ChangeIfElseValueAssignToEarlyReturnRector; +use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector; +use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; +use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; +use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; +use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector; +use Rector\PHPUnit\Set\PHPUnitSetList; +use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector; +use Rector\Set\ValueObject\LevelSetList; +use Rector\Set\ValueObject\SetList; +use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector; + +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->sets([ + SetList::DEAD_CODE, + LevelSetList::UP_TO_PHP_74, + PHPUnitSetList::PHPUNIT_CODE_QUALITY, + PHPUnitSetList::PHPUNIT_100, + ]); + + $rectorConfig->parallel(); + + // The paths to refactor (can also be supplied with CLI arguments) + $rectorConfig->paths([ + __DIR__ . '/src/', + __DIR__ . '/tests/', + ]); + + // Include Composer's autoload - required for global execution, remove if running locally + $rectorConfig->autoloadPaths([ + __DIR__ . '/vendor/autoload.php', + ]); + + // Do you need to include constants, class aliases, or a custom autoloader? + $rectorConfig->bootstrapFiles([ + realpath(getcwd()) . '/vendor/codeigniter4/framework/system/Test/bootstrap.php', + ]); + + $rectorConfig->phpstanConfigs([ + __DIR__ . '/phpstan.neon.dist', + __DIR__ . '/vendor/codeigniter/phpstan-codeigniter/extension.neon', + ]); + + // Set the target version for refactoring + $rectorConfig->phpVersion(PhpVersion::PHP_74); + + // Auto-import fully qualified class names + $rectorConfig->importNames(); + + // Are there files or rules you need to skip? + $rectorConfig->skip([ + JsonThrowOnErrorRector::class, + StringifyStrNeedlesRector::class, + + // Note: requires php 8 + RemoveUnusedPromotedPropertyRector::class, + + // May load view files directly when detecting classes + StringClassNameToClassConstantRector::class, + + TypedPropertyFromAssignsRector::class => [ + __DIR__ . '/src/Models/LogsTempEmailModel.php', + __DIR__ . '/src/Commands/DEARulePublish.php', + ], + ]); + + // auto import fully qualified class names + $rectorConfig->importNames(); + + $rectorConfig->rule(SimplifyUselessVariableRector::class); + $rectorConfig->rule(RemoveAlwaysElseRector::class); + $rectorConfig->rule(CountArrayToEmptyArrayComparisonRector::class); + $rectorConfig->rule(ChangeNestedForeachIfsToEarlyContinueRector::class); + $rectorConfig->rule(ChangeIfElseValueAssignToEarlyReturnRector::class); + $rectorConfig->rule(SimplifyStrposLowerRector::class); + $rectorConfig->rule(CombineIfRector::class); + $rectorConfig->rule(SimplifyIfReturnBoolRector::class); + $rectorConfig->rule(InlineIfToExplicitIfRector::class); + $rectorConfig->rule(PreparedValueToEarlyReturnRector::class); + $rectorConfig->rule(ShortenElseIfRector::class); + $rectorConfig->rule(SimplifyIfElseToTernaryRector::class); + $rectorConfig->rule(UnusedForeachValueToArrayKeysRector::class); + $rectorConfig->rule(ChangeArrayPushToArrayAssignRector::class); + $rectorConfig->rule(UnnecessaryTernaryExpressionRector::class); + $rectorConfig->rule(SimplifyRegexPatternRector::class); + $rectorConfig->rule(FuncGetArgsToVariadicParamRector::class); + $rectorConfig->rule(MakeInheritedMethodVisibilitySameAsParentRector::class); + $rectorConfig->rule(SimplifyEmptyArrayCheckRector::class); + $rectorConfig + ->ruleWithConfiguration(TypedPropertyFromAssignsRector::class, [ + /** + * The INLINE_PUBLIC value is default to false to avoid BC break, if you use for libraries and want to preserve BC break, you don't need to configure it, as it included in LevelSetList::UP_TO_PHP_74 + * Set to true for projects that allow BC break + */ + TypedPropertyFromAssignsRector::INLINE_PUBLIC => true, + ]); + $rectorConfig->rule(StringClassNameToClassConstantRector::class); + $rectorConfig->rule(PrivatizeFinalClassPropertyRector::class); + $rectorConfig->rule(CompleteDynamicPropertiesRector::class); +}; diff --git a/roave-bc-check.yaml b/roave-bc-check.yaml new file mode 100644 index 0000000..6773bb8 --- /dev/null +++ b/roave-bc-check.yaml @@ -0,0 +1,3 @@ +parameters: + ignoreErrors: + - '#\[BC\] SKIPPED: .+ could not be found in the located source#' diff --git a/src/Commands/DEARulePublish.php b/src/Commands/DEARulePublish.php new file mode 100644 index 0000000..2df1409 --- /dev/null +++ b/src/Commands/DEARulePublish.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Commands; + +use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\CLI; +use CodeIgniter\Publisher\Publisher; +use Throwable; + +class DEARulePublish extends BaseCommand +{ + protected $group = 'CodeIgniter DEA Rule'; + protected $name = 'dea-rule:publish'; + protected $description = 'Publish DEARule config file into the current application.'; + + public function run(array $params): void + { + // Use the Autoloader to figure out the module path + $source = service('autoloader')->getNamespace('Datamweb\\CodeIgniterDEARule')[0]; + + $publisher = new Publisher($source, APPPATH); + + try { + // Add only the desired components + $publisher->addPaths([ + 'Config\DEARule.php', + ])->merge(false); // Be careful not to overwrite anything + } catch (Throwable $e) { + $this->showError($e); + + return; + } + + // If publication succeeded then update namespaces + foreach ($publisher->getPublished() as $file) { + // Replace the namespace + $contents = file_get_contents($file); + + $contents = str_replace('namespace Datamweb\\CodeIgniterDEARule\\Config', 'namespace Config', $contents); + $contents = str_replace('class DEARule', 'class DEARule extends \\Datamweb\\CodeIgniterDEARule\\Config\\DEARule', $contents); + + file_put_contents($file, $contents); + } + CLI::write(CLI::color(' Published! ', 'green') . 'You can customize the configuration by editing the "app/Config/DEARule.php" file.'); + } +} diff --git a/src/Config/DEARule.php b/src/Config/DEARule.php new file mode 100644 index 0000000..b3a50da --- /dev/null +++ b/src/Config/DEARule.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Config; + +class DEARule +{ + /** + * -------------------------------------------------------------------- + * Domain Database Files Used Blacklisted + * -------------------------------------------------------------------- + * We use a large database to check temporary emails. However, + * If you want to specifically identify the domain as Temporary Email, add it there. + * + * @var string[] + * @phpstan-var list + */ + public array $filesBlacklisted = [ + 'https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt', + //'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf', + //'https://gist.githubusercontent.com/saaiful/dd2b4b34a02171d7f9f0b979afe48f65/raw/2ad5590be72b69a51326b3e9d229f615e866f2e5/blocklist.txt', + + // APPPATH . 'myCustomDomainBlacklisted.txt', + ]; + + /** + * -------------------------------------------------------------------- + * Add New Domain To Domains Blacklisted + * -------------------------------------------------------------------- + * We use a large database to check temporary emails. However, + * If you want to specifically identify the domain as Temporary Email, add it there. + * + * @var string[] + * @phpstan-var list + */ + public array $domainBlacklisted = [ + // 'not-allowed-to-register.com', + ]; + + /** + * -------------------------------------------------------------------- + * Add Emails To White Listed + * -------------------------------------------------------------------- + * The email added here will be considered valid anyway. + * + * @var string[] + * @phpstan-var list + */ + public array $emailsWhiteListed = [ + // 'foo@allowed-to-register.com', + ]; + + /** + * -------------------------------------------------------------------- + * Skipping the rule `is_temp_email` + * -------------------------------------------------------------------- + * If for any reason you want rule `is_temp_email` checking to be disabled, set it to true. + */ + public bool $jumpFromRule = false; + + /** + * -------------------------------------------------------------------- + * Customize the DB group used for Model/Migration + * -------------------------------------------------------------------- + */ + public ?string $DBGroup = null; + + /** + * -------------------------------------------------------------------- + * Customize The Temp Email Attempts Table name + * -------------------------------------------------------------------- + * All attempts made with disposable emails are recorded in this table. + * The information in this table will help you to have accurate statistics of attempts to use disposable emails. + * You can block users with a specific IP by checking IPs if needed. + */ + public string $tableName = 'logs_temp_email'; + + /** + * -------------------------------------------------------------------- + * Set ON/OFF Attempts If Disposable Email Detection + * -------------------------------------------------------------------- + * By default, if a Disposable Email is detected, the user's data is stored in the DB. + * If you can't save data, set `false`. + */ + public bool $recordedAttemptsIfDisposableEmails = true; +} diff --git a/src/Config/Registrar.php b/src/Config/Registrar.php new file mode 100644 index 0000000..f276d8b --- /dev/null +++ b/src/Config/Registrar.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Config; + +use Datamweb\CodeIgniterDEARule\Validation\DEAValidator; + +class Registrar +{ + /** + * -------------------------------------------------------------------------- + * Registrar DEAValidator::class + * -------------------------------------------------------------------------- + * Register the `is-temp-email` rule for used like CI4 rules. + * + * @return array>> + */ + public static function Validation(): array + { + return [ + 'ruleSets' => [ + DEAValidator::class, + ], + ]; + } +} diff --git a/src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php b/src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php new file mode 100644 index 0000000..2f8fe7a --- /dev/null +++ b/src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Database\Migrations; + +use CodeIgniter\Database\Forge; +use CodeIgniter\Database\Migration; +use Datamweb\CodeIgniterDEARule\Config\DEARule; + +class LogsTempEmailMigration extends Migration +{ + private string $tableName; + + /** + * @var string[] + */ + private array $attributes; + + public function __construct(?Forge $forge = null) + { + /** @var DEARule $DEARuleConfig */ + $DEARuleConfig = config('DEARule'); + + if ($DEARuleConfig->DBGroup !== null) { + $this->DBGroup = $DEARuleConfig->DBGroup; + } + + parent::__construct($forge); + + $this->tableName = $DEARuleConfig->tableName; + $this->attributes = ($this->db->getPlatform() === 'MySQLi') ? ['ENGINE' => 'InnoDB'] : []; + } + + public function up(): void + { + /** + * Temp Email Attempts Table + * Records Temp Email attempts. + */ + $this->forge->addField([ + 'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true], + 'email' => ['type' => 'varchar', 'constraint' => 255], + 'try_url_string' => ['type' => 'varchar', 'constraint' => 100, 'null' => false, 'comment' => 'Path part of the current URL relative to baseURL that was attempted with the disposable email.'], + 'ip_address' => ['type' => 'varchar', 'constraint' => 255], + 'agent_string' => ['type' => 'varchar', 'constraint' => 255, 'null' => true], + 'device' => ['type' => 'varchar', 'constraint' => 255, 'null' => false], + 'platform' => ['type' => 'varchar', 'constraint' => 255, 'null' => true], + 'filter_by' => ['type' => 'varchar', 'constraint' => 20, 'comment' => 'Diagnosis by which source.'], + 'created_at' => ['type' => 'datetime', 'null' => true], + ]); + $this->forge->addPrimaryKey('id'); + + $this->forge->createTable($this->tableName, true, $this->attributes); + } + + public function down(): void + { + $this->forge->dropTable($this->tableName, true); + } +} diff --git a/src/Language/en/DEAValidatorRule.php b/src/Language/en/DEAValidatorRule.php new file mode 100644 index 0000000..989e902 --- /dev/null +++ b/src/Language/en/DEAValidatorRule.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +return [ + 'emailIsTemporary' => 'Registration/Login with temporary emails is not allowed.', + 'emailInvalid' => 'The email address is invalid.', + 'emailIsSuspicious' => 'We have identified the provided email as suspicious.', +]; diff --git a/src/Language/fa/DEAValidatorRule.php b/src/Language/fa/DEAValidatorRule.php new file mode 100644 index 0000000..eb7b885 --- /dev/null +++ b/src/Language/fa/DEAValidatorRule.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +return [ + 'emailIsTemporary' => 'ثبت نام/ ورود با ایمیل های یکبارمصرف مجاز نمی باشد.', + 'emailInvalid' => 'آدرس ایمیل صحیح نیست.', + 'emailIsSuspicious' => 'ما ایمیل ارائه شده را مشکوک تشخیص دادیم.', +]; diff --git a/src/Models/LogsTempEmailModel.php b/src/Models/LogsTempEmailModel.php new file mode 100644 index 0000000..318f731 --- /dev/null +++ b/src/Models/LogsTempEmailModel.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Models; + +use CodeIgniter\Model; +use Datamweb\CodeIgniterDEARule\Config\DEARule; + +class LogsTempEmailModel extends Model +{ + protected $primaryKey = 'id'; + protected $returnType = 'array'; + + /** + * @var string[] + */ + protected $allowedFields = [ + 'email', 'try_url_string', 'ip_address', 'agent_string', 'device', 'platform', 'filter_by', + ]; + + // Dates + protected $useTimestamps = true; + protected $dateFormat = 'datetime'; + protected $createdField = 'created_at'; + protected $updatedField = ''; + + protected function initialize(): void + { + /** @var DEARule $config */ + $config = config('DEARule'); + + if ($config->DBGroup !== null) { + $this->DBGroup = $config->DBGroup; + } + + $this->table = $config->tableName; + } +} diff --git a/src/Validation/DEAValidator.php b/src/Validation/DEAValidator.php new file mode 100644 index 0000000..4f63d15 --- /dev/null +++ b/src/Validation/DEAValidator.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Datamweb\CodeIgniterDEARule\Validation; + +use CodeIgniter\HTTP\Request; +use CodeIgniter\HTTP\UserAgent; +use Datamweb\CodeIgniterDEARule\Config\DEARule; +use Datamweb\CodeIgniterDEARule\Models\LogsTempEmailModel; + +class DEAValidator +{ + protected DEARule $config; + protected UserAgent $userAgent; + protected Request $request; + + public function __construct() + { + /** @var DEARule $DEARuleConfig */ + $DEARuleConfig = config('DEARule'); + + $this->config = $DEARuleConfig; + + $this->userAgent = new UserAgent(); + $this->request = new Request(); + } + + /** + * -------------------------------------------------------------------- + * Rule For Check Disposable Temporary E-mail + * -------------------------------------------------------------------- + * This method was created according to the instructions for creating new validation rules in CodeIgniter4. + * + * @see https://codeigniter.com/user_guide/libraries/validation.html?highlight=ruls#id39 + */ + public function is_temp_email(string $value, ?string &$error = null): bool + { + if ($this->config->jumpFromRule === true) { + return true; + } + + if (! filter_var($value, FILTER_VALIDATE_EMAIL)) { + $error = lang('DEAValidatorRule.emailInvalid'); + + return false; + } + + if (in_array($value, $this->config->emailsWhiteListed, true)) { + return true; + } + + $domain = trim(substr(strrchr($value, '@'), 1)); + + if (in_array($domain, $this->config->domainBlacklisted, true)) { + $this->insertToDB($value, 'domainBlacklisted'); + + $error = lang('DEAValidatorRule.emailIsSuspicious'); + + return false; + } + + if ($this->checkMailIsTemporaryByFiles($domain) === true) { + $this->insertToDB($value, 'filesBlacklisted'); + + $error = lang('DEAValidatorRule.emailIsTemporary'); + + return false; + } + + return true; + } + + /** + * -------------------------------------------------------------------- + * Check E-mail Is Disposable Temporary By Multi DB-Files + * -------------------------------------------------------------------- + * This function checks whether the provided email is in the Disposable/Temporary email category or not. + * This function will merge all the database files together and perform a final check on the total list. + */ + private function checkMailIsTemporaryByFiles(string $domain): bool + { + /** @var array */ + $Files = []; + + foreach ($this->config->filesBlacklisted as $dbFiles) { + $Files[] = array_map('trim', file($dbFiles)); + } + + foreach ($Files as $sub_array) { + if (in_array($domain, $sub_array, true)) { + return true; + } + } + + return false; + } + + /** + * -------------------------------------------------------------------- + * Insert Info For Any Try TEMP EMAIL + * -------------------------------------------------------------------- + * This function records info(agent,ip,...) in the db for data analysis. + */ + private function insertToDB(string $email, string $filter_by): void + { + if ($this->config->recordedAttemptsIfDisposableEmails === true) { + /** @var LogsTempEmailModel $model */ + $model = model('LogsTempEmailModel', false); + + $model->insert([ + 'email' => $email, + 'try_url_string' => uri_string(), + 'ip_address' => $this->request->getIPAddress(), + 'agent_string' => $this->userAgent->getAgentString(), + 'device' => $this->getDevice(), + 'platform' => $this->userAgent->getPlatform(), + 'filter_by' => $filter_by, + ]); + } + } + + /** + * @see https://codeigniter.com/user_guide/libraries/user_agent.html#example + */ + private function getDevice(): string + { + if ($this->userAgent->isBrowser()) { + $currentAgent = $this->userAgent->getBrowser() . ' ' . $this->userAgent->getVersion(); + } elseif ($this->userAgent->isRobot()) { + $currentAgent = $this->userAgent->getRobot(); + } elseif ($this->userAgent->isMobile()) { + $currentAgent = $this->userAgent->getMobile(); + } else { + $currentAgent = 'Unidentified User Agent'; + } + + return $currentAgent; + } +} diff --git a/tests/Database/Migrations/LogsTempEmailMigrationTest.php b/tests/Database/Migrations/LogsTempEmailMigrationTest.php new file mode 100644 index 0000000..d6ed9e5 --- /dev/null +++ b/tests/Database/Migrations/LogsTempEmailMigrationTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Database\Migrations; + +use CodeIgniter\CLI\CLI; +use CodeIgniter\Config\Factories; +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\DatabaseTestTrait; +use CodeIgniter\Test\StreamFilterTrait; + +/** + * @internal + */ +final class LogsTempEmailMigrationTest extends CIUnitTestCase +{ + use DatabaseTestTrait; + use StreamFilterTrait; + + protected function setUp(): void + { + parent::setUp(); + + putenv('NO_COLOR=1'); + CLI::init(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + putenv('NO_COLOR'); + CLI::init(); + $this->resetStreamFilterBuffer(); + } + + public function testMigration(): void + { + command('migrate -n Datamweb\\\\CodeIgniterDEARule'); + + $result = $this->getNormalizedResult(); + $expected = 'Running: (Datamweb\CodeIgniterDEARule) 2023-11-11-105553_Datamweb\CodeIgniterDEARule\Database\Migrations\LogsTempEmailMigration'; + $this->assertStringContainsString($expected, $result); + + $this->resetStreamFilterBuffer(); + + command('db:table logs_temp_email'); + $result = $this->getNormalizedResult(); + + $expected = 'Data of Table "logs_temp_email":'; + $this->assertStringContainsString($expected, $result); + + $expected = <<<'EOL' + +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ + | id | email | try_url_string | ip_address | agent_string | device | platform | filter_by | created_at | + +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ + EOL; + $this->assertStringContainsString($expected, $result); + } + + // public function testRunMigrationByNewTableName(): void + // { + // // !! Need Refactor If you Can Send PR + // // $this->markTestIncomplete('This test has not been implemented yet.'); + + // $config = config('DEARule'); + // $config->tableName = 'my_logs_temp_email'; + + // Factories::injectMock('config', 'DEARule', $config); + + // command('migrate -n Datamweb\\\\CodeIgniterDEARule'); + + // $this->resetStreamFilterBuffer(); + + // command('db:table my_logs_temp_email'); + // $result = $this->getNormalizedResult(); + + // $expected = 'Data of Table "my_logs_temp_email":'; + // $this->assertStringContainsString($expected, $result); + // } + + private function getNormalizedResult(): string + { + return str_replace(PHP_EOL, "\n", $this->getStreamFilterBuffer()); + } +} diff --git a/tests/Models/LogsTempEmailModelTest.php b/tests/Models/LogsTempEmailModelTest.php new file mode 100644 index 0000000..c97392b --- /dev/null +++ b/tests/Models/LogsTempEmailModelTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Models; + +use CodeIgniter\Config\Factories; +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\DatabaseTestTrait; +use CodeIgniter\Validation\ValidationInterface; +use Config\Services; +use Datamweb\CodeIgniterDEARule\Config\DEARule; + +/** + * @internal + */ +final class LogsTempEmailModelTest extends CIUnitTestCase +{ + use DatabaseTestTrait; + + /** + * @var bool + */ + protected $migrate = true; + + /** + * @var string + */ + protected $namespace = 'Datamweb\CodeIgniterDEARule'; + + private ValidationInterface $validation; + + protected function setUp(): void + { + parent::setUp(); + $this->validation = Services::validation(); + $this->validation->reset(); + } + + public function testSeeDBForTempEmail(): void + { + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertFalse($this->validation->run(['email' => 'foo@0-mail.com'])); + + $this->seeInDatabase('logs_temp_email', [ + 'email' => 'foo@0-mail.com', + 'filter_by' => 'filesBlacklisted', + ]); + } + + public function testSeeDBForTempEmailByDomainBlacklisted(): void + { + /** @var DEARule $config */ + $config = config('DEARule'); + $config->domainBlacklisted = [ + 'not-allowed-to-register.com', + ]; + Factories::injectMock('config', 'DEARule', $config); + + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertFalse($this->validation->run(['email' => 'foo@not-allowed-to-register.com'])); + + $this->seeInDatabase('logs_temp_email', [ + 'email' => 'foo@not-allowed-to-register.com', + 'filter_by' => 'domainBlacklisted', + ]); + } +} diff --git a/tests/Validation/DEAValidatorTest.php b/tests/Validation/DEAValidatorTest.php new file mode 100644 index 0000000..1c84d65 --- /dev/null +++ b/tests/Validation/DEAValidatorTest.php @@ -0,0 +1,198 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Validation; + +use CodeIgniter\Config\Factories; +use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Test\DatabaseTestTrait; +use CodeIgniter\Validation\ValidationInterface; +use Config\Services; +use Datamweb\CodeIgniterDEARule\Config\DEARule; + +/** + * @internal + */ +final class DEAValidatorTest extends CIUnitTestCase +{ + use DatabaseTestTrait; + + private ValidationInterface $validation; + + protected function setUp(): void + { + parent::setUp(); + $this->validation = Services::validation(); + $this->validation->reset(); + + /** @var DEARule $config */ + $config = config('DEARule'); + $config->recordedAttemptsIfDisposableEmails = false; + + Factories::injectMock('config', 'DEARule', $config); + } + + /** + * @dataProvider provideIsTempEmail + * + * @param array $data + */ + public function testIsTempEmail(array $data, bool $expected): void + { + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertSame($expected, $this->validation->run($data)); + // $this->validation->run($data); + // $this->assertSame( + // ['email' => lang('DEAValidatorRule.emailInvalid')], + // $this->validation->getErrors('email') + // ); + } + + /** + * @return array|bool>> $data + */ + public static function provideIsTempEmail(): iterable + { + yield from [ + // temp email from https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt + [['email' => 'foo@0-mail.com'], false], + [['email' => 'biz@0-mail.com'], false], + [['email' => 'any@0-mail.com'], false], + [['email' => 'foo@kino24.ru'], false], + [['email' => 'biz@kino24.ru'], false], + [['email' => 'any@kino24.ru'], false], + + // no temp email + [['email' => 'email@no-temp-email.com'], true], + [['email' => 'email@no-temp-email.com'], true], + + // invalid email format + [['email' => 'email-invalid.com'], false], + [['email' => 'emai#email.com'], false], + ]; + } + + /** + * @dataProvider provideIsTempEmailByMutiDBFiles + * + * @param array $data + */ + public function testIsTempEmailByMutiDBFiles(array $data, bool $expected): void + { + // Off data storage in the DB due to not running the migration + /** @var DEARule $config */ + $config = config('DEARule'); + $config->filesBlacklisted = [ + 'https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt', + 'https://gist.githubusercontent.com/saaiful/dd2b4b34a02171d7f9f0b979afe48f65/raw/2ad5590be72b69a51326b3e9d229f615e866f2e5/blocklist.txt', + ]; + + Factories::injectMock('config', 'DEARule', $config); + + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertSame($expected, $this->validation->run($data)); + } + + /** + * @return array|bool>> $data + */ + public static function provideIsTempEmailByMutiDBFiles(): iterable + { + yield from [ + // temp email from https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt + [['email' => 'foo@0-mail.com'], false], + [['email' => 'biz@0-mail.com'], false], + [['email' => 'any@0-mail.com'], false], + [['email' => 'foo@kino24.ru'], false], + [['email' => 'biz@kino24.ru'], false], + [['email' => 'any@kino24.ru'], false], + // temp email from 'https://gist.githubusercontent.com/saaiful/dd2b4b34a02171d7f9f0b979afe48f65/raw/2ad5590be72b69a51326b3e9d229f615e866f2e5/blocklist.txt' + [['email' => 'foo@a45.in'], false], + [['email' => 'biz@a45.in'], false], + [['email' => 'any@a45.in'], false], + [['email' => 'foo@cachedot.net'], false], + [['email' => 'biz@cachedot.net'], false], + [['email' => 'any@cachedot.net'], false], + ]; + } + + /** + * @dataProvider provideIsTempEmailByDomainBlacklisted + * + * @param array $data + */ + public function testIsTempEmailByDomainBlacklisted(array $data, bool $expected): void + { + /** @var DEARule $config */ + $config = config('DEARule'); + $config->domainBlacklisted = [ + 'not-allowed-to-register.com', + 'not-allowed-to-login.com', + ]; + + Factories::injectMock('config', 'DEARule', $config); + + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertSame($expected, $this->validation->run($data)); + } + + /** + * @return array|bool>> $data + */ + public static function provideIsTempEmailByDomainBlacklisted(): iterable + { + yield from [ + [['email' => 'foo@not-allowed-to-register.com'], false], + [['email' => 'biz@not-allowed-to-register.com'], false], + [['email' => 'any@not-allowed-to-register.com'], false], + [['email' => 'foo@not-allowed-to-login.com'], false], + [['email' => 'biz@not-allowed-to-login.com'], false], + [['email' => 'any@not-allowed-to-login.com'], false], + ]; + } + + /** + * @dataProvider provideEmailIsDomainBlacklistedButEmailsWhiteListed + * + * @param array $data + */ + public function testEmailIsDomainBlacklistedButEmailsWhiteListed(array $data, bool $expected): void + { + /** @var DEARule $config */ + $config = config('DEARule'); + $config->domainBlacklisted = [ + 'not-allowed-to-register.com', + 'not-allowed-to-login.com', + ]; + $config->emailsWhiteListed = [ + 'foo@not-allowed-to-register.com', + 'foo@not-allowed-to-login.com', + ]; + + Factories::injectMock('config', 'DEARule', $config); + + $this->validation->setRules(['email' => 'is_temp_email']); + $this->assertSame($expected, $this->validation->run($data)); + } + + /** + * @return array|bool>> $data + */ + public static function provideEmailIsDomainBlacklistedButEmailsWhiteListed(): iterable + { + yield from [ + [['email' => 'foo@not-allowed-to-register.com'], true], + [['email' => 'foo@not-allowed-to-login.com'], true], + ]; + } +} From 508b1cb7c7e5c58160032392da82074862f73f43 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 14 Nov 2023 02:18:38 +0330 Subject: [PATCH 2/9] chore: remove unneeded plg --- .github/workflows/docs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 03473f9..88ca40b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,6 +22,5 @@ jobs: run: | pip3 install mkdocs-material pip3 install mkdocs-git-revision-date-localized-plugin - pip3 install mkdocs-redirects - name: Publish codeigniter DEA Rule Documentation run: mkdocs gh-deploy --force From f726bd469ec609680d5c3e2999b18df5198e72e5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Tue, 14 Nov 2023 02:40:07 +0330 Subject: [PATCH 3/9] publish CI-DEA-RULE --- .github/workflows/rector.yml | 2 +- README.md | 7 +- docs/index.md | 1 + phpstan-baseline.php | 15 ++- phpunit.xml.dist | 6 +- rector.php | 1 + src/Commands/DEARulePublish.php | 2 +- src/Config/DEARule.php | 4 +- tests/_support/Config/Registrar.php | 145 ++++++++++++++++++++++++++++ 9 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 tests/_support/Config/Registrar.php diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index 7ad6534..2e1718b 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -62,5 +62,5 @@ jobs: - name: Analyze for refactoring run: | - composer global require --dev rector/rector:^0.15.1 + composer global require --dev rector/rector:^0.18.7 rector process --dry-run --no-progress-bar diff --git a/README.md b/README.md index 1b4ffb5..22e6737 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,19 @@ [Farsi](./README.fa-IR.md) | English ## CodeIgniter DEA Rule [![PHPUnit](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml) +[![Coverage Status](https://coveralls.io/repos/github/datamweb/codeigniter-dea-rule/badge.svg?branch=develop)](https://coveralls.io/github/datamweb/codeigniter-dea-rule?branch=develop) [![PHPStan](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml) [![Rector](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml) [![Psalm](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml) -[![PHPCSFixer](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcsfixer.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcsfixer.yml) -[![PHPCPD](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcpd.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-ruleactions/workflows/phpcpd.yml) +[![PHPCSFixer](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcsfixer.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcsfixer.yml) +[![PHPCPD](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcpd.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpcpd.yml) [![Unused](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml) [![Deptrac](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml)

CodeIgniter DEA Rule

-[![Latest Stable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rulev?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Total Downloads](http://poser.pugx.org/datamweb/codeigniter-dea-ruledownloads?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![Latest Unstable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rulev/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![License](http://poser.pugx.org/datamweb/codeigniter-dea-rulelicense?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) [![PHP Version Require](http://poser.pugx.org/datamweb/codeigniter-dea-rulerequire/php?style=for-the-badge)](https://packagist.org/packages/datamweb/shield-oauth) +[![Latest Stable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Total Downloads](http://poser.pugx.org/datamweb/codeigniter-dea-rule/downloads?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Latest Unstable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![License](http://poser.pugx.org/datamweb/codeigniter-dea-rule/license?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![PHP Version Require](http://poser.pugx.org/datamweb/codeigniter-dea-rule/require/php?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) **`CodeIgniter DEA Rule`** helps you to validate the email provided by the user and to deal with it if the email was of Temporary & Disponsable Emails(DEA) use type. diff --git a/docs/index.md b/docs/index.md index cdac2a5..0f1ad72 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,6 @@ ## CodeIgniter DEA Rule [![PHPUnit](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpunit.yml) +[![Coverage Status](https://coveralls.io/repos/github/datamweb/codeigniter-dea-rule/badge.svg?branch=develop)](https://coveralls.io/github/datamweb/codeigniter-dea-rule?branch=develop) [![PHPStan](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/phpstan.yml) [![Rector](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/rector.yml) [![Psalm](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/psalm.yml) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 145db48..9183266 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -2,9 +2,14 @@ $ignoreErrors = []; -// $ignoreErrors[] = [ -// 'message' => '#^Property Datamweb\\\\CodeIgniterDEARule\\\\Database\\\\Migrations\\\\LogsTempEmailMigration\\:\\:\\$attributes type has no value type specified in iterable type array\\.$#', -// 'count' => 1, -// 'path' => __DIR__ . '/src/Database/Migrations/2023-11-11-105553_LogsTempEmailMigration.php', -// ]; +$ignoreErrors[] = [ + 'message' => '#^Property Tests\\\\Support\\\\Config\\\\Registrar\\:\\:\\$dbConfig type has no value type specified in iterable type array\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method Tests\\\\Support\\\\Config\\\\Registrar\\:\\:Database\\(\\) return type has no value type specified in iterable type array\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', +]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 609c716..e89b18e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -91,13 +91,13 @@ - + - + diff --git a/rector.php b/rector.php index 106fdf5..67c6bdb 100644 --- a/rector.php +++ b/rector.php @@ -94,6 +94,7 @@ TypedPropertyFromAssignsRector::class => [ __DIR__ . '/src/Models/LogsTempEmailModel.php', __DIR__ . '/src/Commands/DEARulePublish.php', + __DIR__ . '/tests/_support/Config/Registrar.php', ], ]); diff --git a/src/Commands/DEARulePublish.php b/src/Commands/DEARulePublish.php index 2df1409..f02b0fc 100644 --- a/src/Commands/DEARulePublish.php +++ b/src/Commands/DEARulePublish.php @@ -3,7 +3,7 @@ declare(strict_types=1); /** - * This file is part of CodeIgniter4 GO TO PAY. + * This file is part of CodeIgniter-DEA-Rule. * * (c) 2023 Datamweb * diff --git a/src/Config/DEARule.php b/src/Config/DEARule.php index b3a50da..a3fe45b 100644 --- a/src/Config/DEARule.php +++ b/src/Config/DEARule.php @@ -27,8 +27,8 @@ class DEARule */ public array $filesBlacklisted = [ 'https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt', - //'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf', - //'https://gist.githubusercontent.com/saaiful/dd2b4b34a02171d7f9f0b979afe48f65/raw/2ad5590be72b69a51326b3e9d229f615e866f2e5/blocklist.txt', + // 'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf', + // 'https://gist.githubusercontent.com/saaiful/dd2b4b34a02171d7f9f0b979afe48f65/raw/2ad5590be72b69a51326b3e9d229f615e866f2e5/blocklist.txt', // APPPATH . 'myCustomDomainBlacklisted.txt', ]; diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php new file mode 100644 index 0000000..7cfcff4 --- /dev/null +++ b/tests/_support/Config/Registrar.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Support\Config; + +/** + * Class Registrar + * + * Provides a basic registrar class for testing BaseConfig registration functions. + */ +class Registrar +{ + /** + * DB config array for testing purposes. + * + * @var array + * + * @psalm-suppress RedundantCondition + */ + protected static $dbConfig = [ + 'MySQLi' => [ + 'DSN' => '', + 'hostname' => '127.0.0.1', + 'username' => 'root', + 'password' => '', + 'database' => 'test', + 'DBDriver' => 'MySQLi', + 'DBPrefix' => 'db_', + 'pConnect' => false, + 'DBDebug' => true, + 'charset' => 'utf8', + 'DBCollat' => 'utf8_general_ci', + 'swapPre' => '', + 'encrypt' => false, + 'compress' => false, + 'strictOn' => false, + 'failover' => [], + 'port' => 3306, + ], + 'Postgre' => [ + 'DSN' => '', + 'hostname' => 'localhost', + 'username' => 'postgres', + 'password' => 'postgres', + 'database' => 'test', + 'DBDriver' => 'Postgre', + 'DBPrefix' => 'db_', + 'pConnect' => false, + 'DBDebug' => true, + 'charset' => 'utf8', + 'DBCollat' => 'utf8_general_ci', + 'swapPre' => '', + 'encrypt' => false, + 'compress' => false, + 'strictOn' => false, + 'failover' => [], + 'port' => 5432, + ], + 'SQLite3' => [ + 'DSN' => '', + 'hostname' => 'localhost', + 'username' => '', + 'password' => '', + 'database' => 'database.db', + 'DBDriver' => 'SQLite3', + 'DBPrefix' => 'db_', + 'pConnect' => false, + 'DBDebug' => true, + 'charset' => 'utf8', + 'DBCollat' => 'utf8_general_ci', + 'swapPre' => '', + 'encrypt' => false, + 'compress' => false, + 'strictOn' => false, + 'failover' => [], + 'port' => 3306, + 'foreignKeys' => true, + ], + 'SQLSRV' => [ + 'DSN' => '', + 'hostname' => 'localhost', + 'username' => 'sa', + 'password' => '1Secure*Password1', + 'database' => 'test', + 'DBDriver' => 'SQLSRV', + 'DBPrefix' => 'db_', + 'pConnect' => false, + 'DBDebug' => true, + 'charset' => 'utf8', + 'DBCollat' => 'utf8_general_ci', + 'swapPre' => '', + 'encrypt' => false, + 'compress' => false, + 'strictOn' => false, + 'failover' => [], + 'port' => 1433, + ], + 'OCI8' => [ + 'DSN' => 'localhost:1521/XEPDB1', + 'hostname' => '', + 'username' => 'ORACLE', + 'password' => 'ORACLE', + 'database' => '', + 'DBDriver' => 'OCI8', + 'DBPrefix' => 'db_', + 'pConnect' => false, + 'DBDebug' => true, + 'charset' => 'utf8', + 'DBCollat' => 'utf8_general_ci', + 'swapPre' => '', + 'encrypt' => false, + 'compress' => false, + 'strictOn' => false, + 'failover' => [], + ], + ]; + + /** + * Override database config + * + * @return array + */ + public static function Database() + { + $config = []; + + // Under GitHub Actions, we can set an ENV var named 'DB' + // so that we can test against multiple databases. + if (($group = getenv('DB')) && ! isset(self::$dbConfig[$group])) { + $config['tests'] = self::$dbConfig[$group]; + } + + return $config; + } +} From 4ed02af73bc0851a933c1b50df921009c15b221d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 15 Nov 2023 03:22:14 +0330 Subject: [PATCH 4/9] publish CI-DEA-RULE --- docs/CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/CNAME diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..556cf3c --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +www.dea-rule.codeigniter4.ir From 2219235f3b856f3eff3169559fc698e0a6d5f26a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 15 Nov 2023 03:34:01 +0330 Subject: [PATCH 5/9] docs: fix logo in mkdocs --- docs/index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 0f1ad72..bc327aa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,8 +9,7 @@ [![Unused](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/unused.yml) [![Deptrac](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml/badge.svg)](https://github.com/datamweb/codeigniter-dea-rule/actions/workflows/deptrac.yml) - -

CodeIgniter DEA Rule

+

CodeIgniter DEA Rule

[![Latest Stable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Total Downloads](http://poser.pugx.org/datamweb/codeigniter-dea-rule/downloads?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![Latest Unstable Version](http://poser.pugx.org/datamweb/codeigniter-dea-rule/v/unstable?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![License](http://poser.pugx.org/datamweb/codeigniter-dea-rule/license?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) [![PHP Version Require](http://poser.pugx.org/datamweb/codeigniter-dea-rule/require/php?style=for-the-badge)](https://packagist.org/packages/datamweb/codeigniter-dea-rule) @@ -32,4 +31,4 @@ contributed in one manner or another in making **`CodeIgniter DEA Rule`**: Contributors - \ No newline at end of file + From 4d5464032e966dcbdc1cdcaa652fec2d2a8cc5d1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 15 Nov 2023 03:36:54 +0330 Subject: [PATCH 6/9] docs: fix demo in mkdocs --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index bc327aa..2d2ece1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,7 +21,7 @@ In this project, as much as possible, the *Code Quality Control Tools used by the Codeigniter4 Core Team* have been used. -

CodeIgniter DEA Rule

+

CodeIgniter DEA Rule

## Acknowledgements From 694e4ae4e0421a0ba82d5cb1cf1ace4236730913 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 15 Nov 2023 19:09:58 +0330 Subject: [PATCH 7/9] publish CI-DEA-RULE --- README.md | 6 ++++++ composer.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22e6737..84baee8 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ In this project, as much as possible, the *Code Quality Control Tools used by th

CodeIgniter DEA Rule

+## CodeIgniter DEA Rule Documentation + +The documentation includes how to install, setup and configure and how to use **`CodeIgniter DEA Rule`**. Click here to see the [docs](https://www.dea-rule.codeigniter4.ir/). + +## License +This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details. ## Acknowledgements diff --git a/composer.json b/composer.json index 0ca3d4c..5e084ae 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "codeigniter4/framework": "^4.2.7", "mikey179/vfsstream": "^1.6.7", "mockery/mockery": "^1.0", - "rector/rector": "^0.18.6" + "rector/rector": "0.18.6" }, "minimum-stability": "dev", "prefer-stable": true, From 422a4ea71505a5fc275af6fb2dc559c65aad1816 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:43:09 +0000 Subject: [PATCH 8/9] chore(deps-dev): update rector/rector requirement from 0.18.6 to 0.18.8 Updates the requirements on [rector/rector](https://github.com/rectorphp/rector) to permit the latest version. - [Release notes](https://github.com/rectorphp/rector/releases) - [Commits](https://github.com/rectorphp/rector/compare/0.18.6...0.18.8) --- updated-dependencies: - dependency-name: rector/rector dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5e084ae..6a99618 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "codeigniter4/framework": "^4.2.7", "mikey179/vfsstream": "^1.6.7", "mockery/mockery": "^1.0", - "rector/rector": "0.18.6" + "rector/rector": "0.18.8" }, "minimum-stability": "dev", "prefer-stable": true, From d0f751b1fcf2e212170993b222615265cc975c1d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Wed, 15 Nov 2023 23:23:47 +0330 Subject: [PATCH 9/9] publish CI-DEA-RULE --- phpstan-baseline.php | 20 +++++++++++++++++ src/Validation/DEAValidator.php | 5 +++++ .../Migrations/LogsTempEmailMigrationTest.php | 22 +++++++++---------- tests/Models/LogsTempEmailModelTest.php | 12 +++++++--- tests/Validation/DEAValidatorTest.php | 14 +++++++----- 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 9183266..ad71160 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -12,4 +12,24 @@ 'count' => 1, 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Property Tests\\\\Validation\\\\DEAValidatorTest\\:\\:\\$config type has no value type specified in iterable type array\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/Validation/DEAValidatorTest.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Validation\\\\Validation constructor expects Config\\\\Validation, stdClass given\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/Validation/DEAValidatorTest.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property Tests\\\\Models\\\\LogsTempEmailModelTest\\:\\:\\$config type has no value type specified in iterable type array\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/Models/LogsTempEmailModelTest.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Validation\\\\Validation constructor expects Config\\\\Validation, stdClass given\\.$#', + 'count' => 1, + 'path' => __DIR__ . '/tests/Models/LogsTempEmailModelTest.php', +]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/src/Validation/DEAValidator.php b/src/Validation/DEAValidator.php index 4f63d15..a972749 100644 --- a/src/Validation/DEAValidator.php +++ b/src/Validation/DEAValidator.php @@ -86,6 +86,8 @@ public function is_temp_email(string $value, ?string &$error = null): bool * -------------------------------------------------------------------- * This function checks whether the provided email is in the Disposable/Temporary email category or not. * This function will merge all the database files together and perform a final check on the total list. + * + * @codeCoverageIgnore */ private function checkMailIsTemporaryByFiles(string $domain): bool { @@ -110,6 +112,8 @@ private function checkMailIsTemporaryByFiles(string $domain): bool * Insert Info For Any Try TEMP EMAIL * -------------------------------------------------------------------- * This function records info(agent,ip,...) in the db for data analysis. + * + * @codeCoverageIgnore */ private function insertToDB(string $email, string $filter_by): void { @@ -131,6 +135,7 @@ private function insertToDB(string $email, string $filter_by): void /** * @see https://codeigniter.com/user_guide/libraries/user_agent.html#example + * @codeCoverageIgnore */ private function getDevice(): string { diff --git a/tests/Database/Migrations/LogsTempEmailMigrationTest.php b/tests/Database/Migrations/LogsTempEmailMigrationTest.php index d6ed9e5..7b366a4 100644 --- a/tests/Database/Migrations/LogsTempEmailMigrationTest.php +++ b/tests/Database/Migrations/LogsTempEmailMigrationTest.php @@ -52,20 +52,20 @@ public function testMigration(): void $expected = 'Running: (Datamweb\CodeIgniterDEARule) 2023-11-11-105553_Datamweb\CodeIgniterDEARule\Database\Migrations\LogsTempEmailMigration'; $this->assertStringContainsString($expected, $result); - $this->resetStreamFilterBuffer(); + // $this->resetStreamFilterBuffer(); - command('db:table logs_temp_email'); - $result = $this->getNormalizedResult(); + // command('db:table logs_temp_email'); + // $result = $this->getNormalizedResult(); - $expected = 'Data of Table "logs_temp_email":'; - $this->assertStringContainsString($expected, $result); + // $expected = 'Data of Table "logs_temp_email":'; + // $this->assertStringContainsString($expected, $result); - $expected = <<<'EOL' - +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ - | id | email | try_url_string | ip_address | agent_string | device | platform | filter_by | created_at | - +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ - EOL; - $this->assertStringContainsString($expected, $result); + // $expected = <<<'EOL' + // +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ + // | id | email | try_url_string | ip_address | agent_string | device | platform | filter_by | created_at | + // +----+-------+----------------+------------+--------------+--------+----------+-----------+------------+ + // EOL; + // $this->assertStringContainsString($expected, $result); } // public function testRunMigrationByNewTableName(): void diff --git a/tests/Models/LogsTempEmailModelTest.php b/tests/Models/LogsTempEmailModelTest.php index c97392b..71e3ddf 100644 --- a/tests/Models/LogsTempEmailModelTest.php +++ b/tests/Models/LogsTempEmailModelTest.php @@ -16,9 +16,10 @@ use CodeIgniter\Config\Factories; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; -use CodeIgniter\Validation\ValidationInterface; +use CodeIgniter\Validation\Validation; use Config\Services; use Datamweb\CodeIgniterDEARule\Config\DEARule; +use Datamweb\CodeIgniterDEARule\Validation\DEAValidator; /** * @internal @@ -37,12 +38,17 @@ final class LogsTempEmailModelTest extends CIUnitTestCase */ protected $namespace = 'Datamweb\CodeIgniterDEARule'; - private ValidationInterface $validation; + private Validation $validation; + private array $config = [ + 'ruleSets' => [ + DEAValidator::class, + ], + ]; protected function setUp(): void { parent::setUp(); - $this->validation = Services::validation(); + $this->validation = $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); } diff --git a/tests/Validation/DEAValidatorTest.php b/tests/Validation/DEAValidatorTest.php index 1c84d65..7486613 100644 --- a/tests/Validation/DEAValidatorTest.php +++ b/tests/Validation/DEAValidatorTest.php @@ -16,9 +16,10 @@ use CodeIgniter\Config\Factories; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; -use CodeIgniter\Validation\ValidationInterface; +use CodeIgniter\Validation\Validation; use Config\Services; use Datamweb\CodeIgniterDEARule\Config\DEARule; +use Datamweb\CodeIgniterDEARule\Validation\DEAValidator; /** * @internal @@ -27,19 +28,22 @@ final class DEAValidatorTest extends CIUnitTestCase { use DatabaseTestTrait; - private ValidationInterface $validation; + private Validation $validation; + private array $config = [ + 'ruleSets' => [ + DEAValidator::class, + ], + ]; protected function setUp(): void { parent::setUp(); - $this->validation = Services::validation(); + $this->validation = $this->validation = new Validation((object) $this->config, Services::renderer()); $this->validation->reset(); /** @var DEARule $config */ $config = config('DEARule'); $config->recordedAttemptsIfDisposableEmails = false; - - Factories::injectMock('config', 'DEARule', $config); } /**