name: "Continuous Integration"

on:
  - pull_request
  - push

env:
  PHP_EXTENSIONS: "json, curl, opcache, mbstring"
  PHP_INI_VALUES: "opcache.enable=1, opcache.enable_cli=1, opcache.fast_shutdown=0, zend.assertions=1, assert.exception=On"
  COMPOSER_OPTIONS: "--optimize-autoloader --prefer-dist -v"
  TOOLS: "composer:v2"

jobs:
  validate:
    name: "Validate composer"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Validate composer.json"
        run: "composer validate --strict"

  lint:
    name: "Linting"

    needs: "validate"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Lint PHP"
        uses: "overtrue/phplint@9.6"

  install:
    name: "Install dependencies"

    needs: "lint"

    runs-on: "ubuntu-latest"

    continue-on-error: ${{ matrix.experimental }}

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

        dependencies:
          - "lowest"
          - "highest"

        experimental: [false]

        include:
          - php-version: "8.1"
            dependencies: "locked"
            experimental: false
          - php-version: "8.2"
            dependencies: "locked"
            experimental: false
          - php-version: "8.3"
            dependencies: "locked"
            experimental: false
          - php-version: "8.4"
            dependencies: "highest"
            experimental: false
          - php-version: "8.5"
            dependencies: "highest"
            experimental: false

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Install lowest dependencies"
        if: "${{ matrix.dependencies == 'lowest' }}"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Install highest dependencies"
        if: "${{ matrix.dependencies == 'highest' && matrix.experimental == false }}"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Install highest dependencies (Experimental)"
        if: "${{ matrix.dependencies == 'highest' && matrix.experimental == true }}"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable --ignore-platform-reqs"

      - name: "Install locked dependencies"
        if: "${{ matrix.dependencies == 'locked' }}"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }}"

      - name: "Check dependencies with composer"
        run: "composer outdated --direct"

  coding-standards:
    name: "Check Coding Standards with PHPCS"

    needs: "lint"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}, cs2pr"

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Run squizlabs/php_codesniffer"
        run: "vendor/bin/phpcs --report=checkstyle -q | cs2pr"

  static-code-analysis:
    name: "Static Code Analysis with PHPStan"

    needs: "lint"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

        dependencies:
          - "locked"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }}"

      - name: "Run phpstan/phpstan"
        run: "vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=768M --no-progress"

  tests:
    name: "UnitTests with PHPUnit"

    needs: "lint"
      
    runs-on: "ubuntu-latest"
    
    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Run unit tests with phpunit/phpunit"
        run: "vendor/bin/phpunit -c phpunit.xml.dist --no-coverage --colors"

  code-coverage:
    name: "Code Coverage with PHPUnit"

    needs: "tests"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "xdebug"
          tools: "${{ env.TOOLS }}"

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Collect code coverage with Xdebug and phpunit/phpunit"
        run: "vendor/bin/phpunit -c phpunit.xml.dist --exclude-group compare --coverage-clover=coverage.clover --coverage-text --colors"

      - name: "Upload coverage to Codecov"
        uses: "codecov/codecov-action@v5.5.1"
        with:
          file: "coverage.clover"
          flags: "phpunit"
          verbose: false

  comparison-checks:
    name: "Compare results with PHPUnit"

    needs: "tests"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"
          - "8.2"
          - "8.3"
          - "8.4"
          - "8.5"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Download browscap.ini"
        run: |
          wget -q http://browscap.org/stream?q=Full_PHP_BrowsCapINI -O /tmp/browscap.ini
          mkdir -p resources
          cp /tmp/browscap.ini resources/browscap.ini

      - name: "Compare get_browser to browscap-php results"
        run: "vendor/bin/phpunit -c phpunit.xml.dist --no-coverage --group compare --colors"

  roave-backwards-compatibility-check:
    name: "Check for Backward Compatibility breaks"

    needs: "lint"

    runs-on: "ubuntu-latest"

    continue-on-error: false

    strategy:
      fail-fast: false

      matrix:
        php-version:
          - "8.1"

        dependencies:
          - "highest"

    steps:
      - name: "Checkout"
        uses: "actions/checkout@v6"
        with:
          # Disabling shallow clone is recommended for improving relevancy of reporting
          fetch-depth: 0

      - name: "Install PHP"
        uses: "shivammathur/setup-php@2.36.0"
        with:
          php-version: "${{ matrix.php-version }}"
          extensions: "${{ env.PHP_EXTENSIONS }}"
          ini-values: "${{ env.PHP_INI_VALUES }}"
          coverage: "none"
          tools: "${{ env.TOOLS }}"

      - name: "Require Roave/BackwardCompatibilityCheck"
        run: "composer require --no-update --no-interaction --prefer-dist --prefer-stable \"roave/backward-compatibility-check:^8\""

      - name: "Update dependencies with composer"
        uses: "ramsey/composer-install@v3"
        with:
          dependency-versions: "${{ matrix.dependencies }}"
          composer-options: "${{ env.COMPOSER_OPTIONS }} --prefer-stable"

      - name: "Check for BC breaks"
        run: "vendor/bin/roave-backward-compatibility-check --format=markdown"
