Skip to content

Conversation

@mambax7
Copy link
Contributor

@mambax7 mambax7 commented Feb 8, 2026

Summary

  • Fix PHPStan CI failure on PHP 7.4/8.0: The baseline file uses PHPStan 2.x format (message/path singular, identifier, count fields) which PHPStan 1.x (installed on PHP <8.1) does not understand. Static analysis now only runs on PHP ≥8.1 where PHPStan 2.x is available. Tests and lint still run on all PHP versions (7.4–8.5).
  • Add SonarCloud analysis: New sonar-project.properties (org=xoops, projectKey=XOOPS_xmf) and .github/workflows/sonarcloud.yml workflow. Runs tests with coverage then SonarCloud scan on push to master and PRs. Requires SONAR_TOKEN secret.
  • Refine CI workflow: Split test step into coverage/non-coverage to properly generate clover.xml only on the coverage matrix row.
  • Fix Qodana workflow: Checkout ref now falls back to github.sha on push events (was failing on non-PR pushes).
  • Remove legacy files: phpcs.xml.dist (superseded by phpcs.xml) and phpunit10.xml.dist (consolidated into phpunit.xml.dist).
  • Add sonar-project.properties to .gitattributes export-ignore.

Test plan

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Added SonarCloud integration and CI improvements with conditional test/coverage runs and pinned workflow actions.
    • Updated linting/analysis tooling configuration.
    • Minor repository metadata adjustments.
  • Tests

    • Removed an old PHPUnit configuration file.
  • Documentation

    • Updated the changelog with new release entries and reorganized historical notes.

mambax7 and others added 2 commits February 8, 2026 05:53
- Add sonar-project.properties: org=xoops, projectKey=XOOPS_xmf,
  PHP 7.4, coverage from clover.xml
- Add .github/workflows/sonarcloud.yml: runs tests with coverage
  then SonarCloud scan on push to master and PRs
- ci.yml: split test step into coverage/non-coverage to generate
  clover.xml only on coverage row
- qodana.yml: fix checkout ref to fall back to github.sha on push
- Remove legacy phpcs.xml.dist and phpunit10.xml.dist
- Add sonar-project.properties to .gitattributes export-ignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The baseline file uses PHPStan 2.x format (message/path singular,
identifier, count fields) which PHPStan 1.x (installed on PHP 7.4
and 8.0) does not understand. PHPStan 2.x requires PHP 8.1+.

Tests and lint still run on all PHP versions (7.4-8.5).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 8, 2026 11:01
@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'tools'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Adds SonarCloud integration and CI workflow updates, adjusts code-quality configs, removes a PHPUnit config, updates changelog and gitattributes, and pins several GitHub Action references; changes touch workflows, quality/tooling configs, and release notes (no API/interface code changes).

Changes

Cohort / File(s) Summary
SonarCloud integration
\.github/workflows/sonarcloud.yml, sonar-project.properties
Introduces a new SonarCloud GitHub Actions workflow (checkout, PHP 8.3 setup, composer install/update, PHPUnit with Clover coverage, SonarSource scan) and adds SonarQube project config with sources/tests, PHP version, and coverage path.
CI workflows & action pinning
\.github/workflows/ci.yml, \.github/workflows/qodana.yml
Pins several actions to specific commits/hashes, adds conditional test steps (separate coverage vs non-coverage test runs), adds repo gating and checkout ref fallback for Qodana workflow.
Repository exports / metadata
\.gitattributes
Adds export-ignore entries for sonar-project.properties and CHANGELOG.md.
Code quality / tests
phpcs.xml, phpunit10.xml.dist, qodana.yaml
Disables Generic.Files.LineLength rule (severity 0 / removes limits), removes phpunit10.xml.dist file, and updates Qodana image tag to jetbrains/qodana-php:2025.2.
Changelog
CHANGELOG.md
Replaces Unreleased header with versioned release entries (1.2.33, 1.2.33-beta2) and reorganizes historical entries; many bugfix and infra notes added.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant GH as GitHub Actions
    participant Runner as Runner (ubuntu-latest)
    participant Repo as Repository
    participant PHP as PHP runtime (8.3)
    participant Composer as Composer
    participant PHPUnit as PHPUnit
    participant Sonar as SonarCloud

    GH->>Runner: triggered (push/PR)
    Runner->>Repo: checkout (fetch-depth:0, pinned ref)
    Runner->>PHP: setup PHP 8.3 (intl, mbstring, xdebug)
    Runner->>Composer: install/update deps
    Runner->>PHPUnit: run tests + generate Clover (build/logs/clover.xml)
    PHPUnit-->>Runner: clover.xml
    Runner->>Sonar: run SonarSource scan (uses SONAR_TOKEN)
    Sonar-->>Runner: analysis result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding SonarCloud integration, fixing PHPStan on older PHP versions, and refining CI workflows—all core objectives of this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the repository’s CI configuration to integrate SonarCloud and stabilize static analysis across the supported PHP matrix by only running PHPStan on PHP ≥ 8.1, while keeping tests/lint across PHP 7.4–8.5.

Changes:

  • Add SonarCloud configuration + workflow to run coverage and publish analysis.
  • Adjust CI workflow to (a) skip PHPStan on PHP < 8.1 and (b) split coverage vs non-coverage test execution.
  • Update Qodana checkout ref handling and remove legacy PHPCS/PHPUnit config files; add Sonar config to export-ignore.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
sonar-project.properties Adds SonarCloud project configuration (sources/tests/coverage paths).
.github/workflows/sonarcloud.yml New workflow to run PHPUnit with coverage and execute Sonar scan.
.github/workflows/ci.yml Skips PHPStan on older PHP, splits coverage run, uploads Clover to Codecov.
.github/workflows/qodana.yml Fixes checkout ref to work for non-PR push events.
.gitattributes Adds sonar-project.properties to export-ignore.
phpcs.xml.dist Removes PHPCS ruleset file.
phpunit10.xml.dist Removes legacy PHPUnit 10 config file.
Comments suppressed due to low confidence (1)

phpcs.xml.dist:1

  • This PR removes phpcs.xml.dist, but the repo doesn’t appear to contain a replacement phpcs.xml. Without a PHPCS ruleset defining what to scan (e.g., src/) and the custom exclusions/line-length settings, composer lint (phpcs) will likely fail with “You must supply at least one file or directory to process”, and style checks will change behavior. Either keep phpcs.xml.dist or add the intended phpcs.xml replacement in this PR.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @.github/workflows/ci.yml:
- Around line 85-87: The CI step named "Run tests with coverage" currently
invokes the global phpunit binary which can fail; update the step so it calls
the project-local PHPUnit instead (e.g. use vendor/bin/phpunit or run via
composer exec/defined composer script) while keeping the conditional if: ${{
matrix.coverage }} and the same arguments (--colors=always --coverage-clover
build/logs/clover.xml) to ensure the workflow uses the dev dependency bundled
with the repo.

In @.github/workflows/sonarcloud.yml:
- Around line 32-33: The workflow invokes phpunit via the PATH ("phpunit
--colors=always --coverage-clover build/logs/clover.xml"), which is unsafe;
change that command to call the project-local vendor binary
("./vendor/bin/phpunit --colors=always --coverage-clover build/logs/clover.xml")
so the workflow uses the correct phpunit binary, and make the same replacement
for the other identical phpunit invocation elsewhere in the workflows.

In `@sonar-project.properties`:
- Around line 12-13: The Sonar config currently excludes all test files via the
sonar.test.exclusions setting (sonar.test.exclusions=tests/**), which prevents
Sonar from indexing tests and collecting test metrics; update this setting to a
narrower pattern (e.g., exclude only fixtures or specific subfolders such as
tests/fixtures/** or tests/**/generated/**) or remove the sonar.test.exclusions
entry entirely so test files are indexed—modify the sonar.test.exclusions value
accordingly in the file where the symbol sonar.test.exclusions is defined.

- Use ./vendor/bin/phpunit instead of bare phpunit in ci.yml and
  sonarcloud.yml (bare phpunit not on PATH in GitHub Actions)
- Remove sonar.test.exclusions=tests/** which prevented SonarCloud
  from indexing test files and collecting test metrics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (master@3c5c8e3). Learn more about missing BASE report.

Additional details and impacted files
@@            Coverage Diff            @@
##             master     #133   +/-   ##
=========================================
  Coverage          ?   35.18%           
  Complexity        ?      835           
=========================================
  Files             ?       38           
  Lines             ?     2288           
  Branches          ?        0           
=========================================
  Hits              ?      805           
  Misses            ?     1483           
  Partials          ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The phpcs.xml.dist was removed in this PR but the replacement phpcs.xml
was not tracked. Without it, composer lint (phpcs) fails with no config.

Changes from .dist version: line-length check fully excluded instead
of using a high limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/ci.yml:
- Around line 77-79: The workflow step using the PHP gate currently does a
lexicographic comparison ("if: ${{ matrix.php >= '8.1' }}") which breaks for
versions like "8.10"; replace this with an explicit allowlist of exact version
equality checks instead of a string comparison. Update the condition on the "Run
static analysis" step to explicitly check matrix.php equals each supported
version (e.g., replace the single comparison with something like "if: ${{
matrix.php == '8.1' || matrix.php == '8.2' || matrix.php == '8.3' }}" or use a
contains/lookup against a hardcoded list of allowed versions) so future PHP
versions do not mis-order.

In @.github/workflows/sonarcloud.yml:
- Around line 35-38: The SonarCloud Scan step currently unconditionally uses
SONAR_TOKEN which causes failures for forked PRs that lack secrets; update the
SonarCloud Scan step (the job/stage named "SonarCloud Scan" that sets env
SONAR_TOKEN) to include an "if" conditional that only runs the step when the
token exists and when the PR is from the same repo (e.g., check
secrets.SONAR_TOKEN is non-empty and either the event is not a pull_request or
github.repository == github.event.pull_request.head.repo.full_name); this
ensures the step is skipped for forked PRs while still running for same-repo PRs
and non-PR runs.

- qodana.yaml: pin linter to jetbrains/qodana-php:2025.2 (was :latest)
- sonarcloud.yml: pin all actions to full SHA hashes (security best practice)
- sonarcloud.yml: only run on upstream repo (if: github.repository)
- sonarcloud.yml: skip scan step gracefully if SONAR_TOKEN not set

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

phpcs.xml:13

  • This change disables the line-length rule entirely via <exclude-pattern>*</exclude-pattern>, which conflicts with the documented convention that the project uses a 200-character line limit (see .github/copilot-instructions.md:38). Either keep the rule enabled with a 200-char limit, or update the documentation/conventions to match the new behavior.

run: ./vendor/bin/phpunit --colors=always --coverage-clover build/logs/clover.xml

- name: SonarCloud Scan
if: env.SONAR_TOKEN != ''
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if: env.SONAR_TOKEN != '' is evaluated before the step-level env: is applied, so this condition will likely always be false and the scan step will be skipped. Use if: secrets.SONAR_TOKEN != '' (or move SONAR_TOKEN to job/workflow env) so the scan runs when the secret is available and still skips on forks.

Suggested change
if: env.SONAR_TOKEN != ''
if: secrets.SONAR_TOKEN != ''

Copilot uses AI. Check for mistakes.
- Pin all action references to full commit SHA hashes (supply-chain security)
- Fix PHPStan skip condition from lexicographic >= to explicit != exclusion
- Fix SonarCloud token check (secrets context, not env context)
- Add repository guard to Qodana workflow
- Fix CHANGELOG: move Ulid overhaul from v1.2.32 to v1.2.33-beta2 (correct release),
  add missing PRs XOOPS#118/XOOPS#119/XOOPS#122, correct 11 release dates to match GitHub releases
- Improve phpcs.xml: use severity=0 instead of exclude-pattern for line length

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 8, 2026

@mambax7 mambax7 merged commit a40eca3 into XOOPS:master Feb 8, 2026
13 of 15 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/sonarcloud.yml:
- Around line 36-40: The step "SonarCloud Scan" uses a step-level if: ${{
secrets.SONAR_TOKEN != '' }} which is invalid because the secrets context isn't
available in step if-expressions; fix by exposing the secret presence via an
environment variable or moving the condition to job-level: set an env like
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} at the job or workflow level (or add a
prior step that writes a step output/var indicating presence), then change the
step's if to check that env/var (e.g., if: env.SONAR_TOKEN != '' or if:
needs.<step>.outputs.sonar_present == 'true'), keeping the "SonarCloud Scan"
uses and SONAR_TOKEN environment mapping intact.

In `@CHANGELOG.md`:
- Around line 67-95: Add a single blank line immediately after each top-level
section heading to satisfy markdownlint MD022: insert one empty line below the
headings "### Changed", "### Removed", "### Infrastructure", and "### Tests" in
the changelog so each heading is followed by a blank line before the list
content.

Comment on lines +36 to +40
- name: SonarCloud Scan
if: ${{ secrets.SONAR_TOKEN != '' }}
uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 # v7
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix: secrets context is not available in step-level if conditions.

The secrets context cannot be used in step if expressions—only env, github, inputs, job, matrix, needs, runner, steps, strategy, and vars are available. This condition will cause a workflow syntax error.

Use an environment variable to expose the secret's presence, then check that variable:

🐛 Proposed fix using env variable
       - name: SonarCloud Scan
-        if: ${{ secrets.SONAR_TOKEN != '' }}
+        if: ${{ env.SONAR_TOKEN != '' }}
         uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 # v7
         env:
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Alternatively, move the check to job level or use a dedicated step to set an output variable based on secret presence.

🧰 Tools
🪛 actionlint (1.7.10)

[error] 37-37: context "secrets" is not allowed here. available contexts are "env", "github", "inputs", "job", "matrix", "needs", "runner", "steps", "strategy", "vars". see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability for more details

(expression)

🤖 Prompt for AI Agents
In @.github/workflows/sonarcloud.yml around lines 36 - 40, The step "SonarCloud
Scan" uses a step-level if: ${{ secrets.SONAR_TOKEN != '' }} which is invalid
because the secrets context isn't available in step if-expressions; fix by
exposing the secret presence via an environment variable or moving the condition
to job-level: set an env like SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} at the job
or workflow level (or add a prior step that writes a step output/var indicating
presence), then change the step's if to check that env/var (e.g., if:
env.SONAR_TOKEN != '' or if: needs.<step>.outputs.sonar_present == 'true'),
keeping the "SonarCloud Scan" uses and SONAR_TOKEN environment mapping intact.

Comment on lines +67 to +95
### Changed
* Use strict comparison (`===`) instead of loose (`==`) in `FilterInput` attribute filtering and `Database\Tables` column lookups
* Fix `FileStorageTest` namespace from `Xmf\Key` to `Xmf\Test\Key` to match autoload-dev configuration
* Fix trailing semicolons in `@throws` PHPDoc tags in `Jwt\JsonWebToken::create()`
* Update composer.json by @mambax7 in #119
* Update composer, phpstan, phpcs by @mambax7 in #122

### Removed
* Remove redundant `paragonie/random_compat` dependency (native in PHP 7+)

### Infrastructure
* Add PHPStan stub files for XOOPS framework classes to eliminate ~524 false-positive errors
* Configure `phpstan.neon` to scan stubs directory
* Move changelog to `CHANGELOG.md` at repo root; `docs/changelog.md` now redirects
* Simplify `.scrutinizer.yml` to analysis-only; move `stubs/` from `excluded_paths` to `dependency_paths` for constant/class resolution
* Add dedicated PHPStan, PHPCS, and code coverage jobs to GitHub Actions CI workflow
* Generate PHPStan baseline (`phpstan-baseline.neon`) with ~546 existing errors for incremental cleanup
* Add `composer baseline` script with backup/restore safety for PHPStan baseline regeneration
* Update `.gitignore` to exclude `build/` directory (coverage output)
* Update `.gitattributes` with export-ignore for PHPStan, PHPUnit, and stub files
* Add GitHub Copilot custom instructions (`.github/copilot-instructions.md`) and reusable XOOPS template

### Tests
* Add unit tests for `Request::setVar()` ENV and SERVER branches
* Add unit tests for `FilterInput` hex and decimal entity decode
* Add unit test for `Metagen::html2text()` numeric entity conversion
* Add unit test for `IPAddress::normalize()` invalid IP handling
* Add unit tests for `Yaml::read()` and `Yaml::readWrapped()` file size limits

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor: Add blank lines below headings for markdown consistency.

Several section headings (### Changed, ### Removed, ### Infrastructure, ### Tests) are missing the blank line after them that markdownlint expects (MD022). While this doesn't affect rendering in most parsers, it improves consistency with the rest of the file.

📝 Example fix pattern
 ### Changed
+
 * Use strict comparison (`===`) instead of loose (`==`)...

Apply similar blank lines after ### Removed, ### Infrastructure, and ### Tests headings.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Changed
* Use strict comparison (`===`) instead of loose (`==`) in `FilterInput` attribute filtering and `Database\Tables` column lookups
* Fix `FileStorageTest` namespace from `Xmf\Key` to `Xmf\Test\Key` to match autoload-dev configuration
* Fix trailing semicolons in `@throws` PHPDoc tags in `Jwt\JsonWebToken::create()`
* Update composer.json by @mambax7 in #119
* Update composer, phpstan, phpcs by @mambax7 in #122
### Removed
* Remove redundant `paragonie/random_compat` dependency (native in PHP 7+)
### Infrastructure
* Add PHPStan stub files for XOOPS framework classes to eliminate ~524 false-positive errors
* Configure `phpstan.neon` to scan stubs directory
* Move changelog to `CHANGELOG.md` at repo root; `docs/changelog.md` now redirects
* Simplify `.scrutinizer.yml` to analysis-only; move `stubs/` from `excluded_paths` to `dependency_paths` for constant/class resolution
* Add dedicated PHPStan, PHPCS, and code coverage jobs to GitHub Actions CI workflow
* Generate PHPStan baseline (`phpstan-baseline.neon`) with ~546 existing errors for incremental cleanup
* Add `composer baseline` script with backup/restore safety for PHPStan baseline regeneration
* Update `.gitignore` to exclude `build/` directory (coverage output)
* Update `.gitattributes` with export-ignore for PHPStan, PHPUnit, and stub files
* Add GitHub Copilot custom instructions (`.github/copilot-instructions.md`) and reusable XOOPS template
### Tests
* Add unit tests for `Request::setVar()` ENV and SERVER branches
* Add unit tests for `FilterInput` hex and decimal entity decode
* Add unit test for `Metagen::html2text()` numeric entity conversion
* Add unit test for `IPAddress::normalize()` invalid IP handling
* Add unit tests for `Yaml::read()` and `Yaml::readWrapped()` file size limits
### Changed
* Use strict comparison (`===`) instead of loose (`==`) in `FilterInput` attribute filtering and `Database\Tables` column lookups
* Fix `FileStorageTest` namespace from `Xmf\Key` to `Xmf\Test\Key` to match autoload-dev configuration
* Fix trailing semicolons in `@throws` PHPDoc tags in `Jwt\JsonWebToken::create()`
* Update composer.json by `@mambax7` in `#119`
* Update composer, phpstan, phpcs by `@mambax7` in `#122`
### Removed
* Remove redundant `paragonie/random_compat` dependency (native in PHP 7+)
### Infrastructure
* Add PHPStan stub files for XOOPS framework classes to eliminate ~524 false-positive errors
* Configure `phpstan.neon` to scan stubs directory
* Move changelog to `CHANGELOG.md` at repo root; `docs/changelog.md` now redirects
* Simplify `.scrutinizer.yml` to analysis-only; move `stubs/` from `excluded_paths` to `dependency_paths` for constant/class resolution
* Add dedicated PHPStan, PHPCS, and code coverage jobs to GitHub Actions CI workflow
* Generate PHPStan baseline (`phpstan-baseline.neon`) with ~546 existing errors for incremental cleanup
* Add `composer baseline` script with backup/restore safety for PHPStan baseline regeneration
* Update `.gitignore` to exclude `build/` directory (coverage output)
* Update `.gitattributes` with export-ignore for PHPStan, PHPUnit, and stub files
* Add GitHub Copilot custom instructions (`.github/copilot-instructions.md`) and reusable XOOPS template
### Tests
* Add unit tests for `Request::setVar()` ENV and SERVER branches
* Add unit tests for `FilterInput` hex and decimal entity decode
* Add unit test for `Metagen::html2text()` numeric entity conversion
* Add unit test for `IPAddress::normalize()` invalid IP handling
* Add unit tests for `Yaml::read()` and `Yaml::readWrapped()` file size limits
🧰 Tools
🪛 LanguageTool

[uncategorized] ~87-~87: The official name of this software platform is spelled with a capital “H”.
Context: ...Add GitHub Copilot custom instructions (.github/copilot-instructions.md) and reusable ...

(GITHUB)

🪛 markdownlint-cli2 (0.20.0)

[warning] 67-67: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 74-74: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 77-77: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 89-89: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
In `@CHANGELOG.md` around lines 67 - 95, Add a single blank line immediately after
each top-level section heading to satisfy markdownlint MD022: insert one empty
line below the headings "### Changed", "### Removed", "### Infrastructure", and
"### Tests" in the changelog so each heading is followed by a blank line before
the list content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant