From 84568ad46adfa6a57f3b80b044660318e12c4d75 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 26 May 2026 08:35:25 +0000
Subject: [PATCH 1/2] chore: add php quality workflow and migration docs
Agent-Logs-Url: https://github.com/iForumModule/iforum/sessions/dbcaa461-e0be-4886-b4aa-59aa69d7b84a
Co-authored-by: fiammybe <3736946+fiammybe@users.noreply.github.com>
---
.github/workflows/php-quality.yml | 38 +++++++++++++++++
docs/art-ipf-migration-matrix.md | 19 +++++++++
docs/index.md | 3 ++
docs/phased-refactor-roadmap.md | 27 ++++++++++++
docs/php8-compatibility-checklist.md | 23 ++++++++++
phpcs.xml.dist | 11 +++++
phpstan.neon.dist | 7 ++++
src/include/bootstrap.php | 63 ++++++++++++++++++++++++++++
tools/phpstan-bootstrap.php | 25 +++++++++++
9 files changed, 216 insertions(+)
create mode 100644 .github/workflows/php-quality.yml
create mode 100644 docs/art-ipf-migration-matrix.md
create mode 100644 docs/phased-refactor-roadmap.md
create mode 100644 docs/php8-compatibility-checklist.md
create mode 100644 phpcs.xml.dist
create mode 100644 phpstan.neon.dist
create mode 100644 src/include/bootstrap.php
create mode 100644 tools/phpstan-bootstrap.php
diff --git a/.github/workflows/php-quality.yml b/.github/workflows/php-quality.yml
new file mode 100644
index 0000000..0d49f2b
--- /dev/null
+++ b/.github/workflows/php-quality.yml
@@ -0,0 +1,38 @@
+name: PHP quality checks
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ quality:
+ name: PHP ${{ matrix.php-version }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php-version: ['8.2', '8.3', '8.4', '8.5']
+
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v4
+
+ - name: Set up PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ coverage: none
+ tools: parallel-lint, phpcs, phpstan
+
+ - name: Lint PHP sources
+ run: parallel-lint --exclude .git --exclude vendor src
+
+ - name: Check coding standards
+ run: phpcs --standard=phpcs.xml.dist
+
+ - name: Run static analysis
+ run: phpstan analyse --no-progress --configuration=phpstan.neon.dist
diff --git a/docs/art-ipf-migration-matrix.md b/docs/art-ipf-migration-matrix.md
new file mode 100644
index 0000000..bdf16d5
--- /dev/null
+++ b/docs/art-ipf-migration-matrix.md
@@ -0,0 +1,19 @@
+# Art → IPF migration matrix
+
+This module still mixes legacy Art-based persistence patterns with newer ImpressCMS conventions. The matrix below captures the intended migration target without changing runtime behavior in this PR.
+
+| Legacy area | Current responsibility | IPF-oriented target | Notes for follow-up |
+| --- | --- | --- | --- |
+| `src/class/art/object.php` and related Art base classes | Shared object lifecycle, validation, and persistence helpers | Replace with IPF object and handler base classes | Start with low-risk handlers that already map cleanly to one table each |
+| `src/class/forum.php`, `src/class/topic.php`, `src/class/post.php` | Module domain objects and handler logic | Move table mapping and CRUD concerns into dedicated IPF handlers | Keep public method names stable while adapters are introduced |
+| `src/include/functions.ini.php` config loading | Module-wide config bootstrap | Route shared module/config access through the new bootstrap helper first | This reduces repeated dirname lookups before broader refactors |
+| Direct `icms_getmodulehandler()` calls throughout `src/` | Per-file handler lookup | Centralize lookup behind helper functions | Lets later refactors swap implementations in one place |
+| Install and update hooks in `src/include/module.php` | Schema/bootstrap orchestration | Move schema-aware logic behind dedicated service-style helpers | Leave hook entry points intact for compatibility |
+| Template-facing utility functions in `src/include/functions.php` | Mixed rendering and data access helpers | Separate presentation helpers from persistence access | Tackle after handler loading is consolidated |
+
+## Migration guardrails
+
+- Preserve the current module entry points and install/update hooks until handler migrations are complete.
+- Refactor one handler family at a time so existing forum, topic, and post behavior stays unchanged.
+- Prefer adding adapters and compatibility layers before deleting Art-based code.
+- Expand CI coverage alongside each phase so new IPF-oriented code is checked on all supported PHP versions.
diff --git a/docs/index.md b/docs/index.md
index d4ed6ff..3cbd76b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,3 +1,6 @@
iForum is a full-featured discussion forum for ImpressCMS.
[Templates](templates.md)
+[Art → IPF migration matrix](art-ipf-migration-matrix.md)
+[PHP 8 compatibility checklist](php8-compatibility-checklist.md)
+[Phased refactor roadmap](phased-refactor-roadmap.md)
diff --git a/docs/phased-refactor-roadmap.md b/docs/phased-refactor-roadmap.md
new file mode 100644
index 0000000..ffdf4a4
--- /dev/null
+++ b/docs/phased-refactor-roadmap.md
@@ -0,0 +1,27 @@
+# Phased refactor roadmap
+
+This roadmap describes the intended migration path while keeping the module installable and behaviorally stable.
+
+## Phase 1: Developer safety nets
+
+- Add CI coverage for PHP linting, coding standards, and static analysis.
+- Document the Art → IPF migration path and PHP 8 review expectations.
+- Introduce a shared bootstrap helper for module lookup and handler loading without wiring it into runtime paths yet.
+
+## Phase 2: Shared access consolidation
+
+- Replace duplicated module dirname and handler lookup code in low-risk files with the shared helper.
+- Keep existing public entry points, hook signatures, and handler names unchanged.
+- Add narrowly scoped validation to each migrated slice before widening coverage.
+
+## Phase 3: Persistence layer migration
+
+- Migrate one handler family at a time from Art-based patterns to IPF-friendly structures.
+- Add adapters where needed so existing call sites keep working during the transition.
+- Separate persistence concerns from presentation helpers as handlers move over.
+
+## Phase 4: Cleanup and expansion
+
+- Broaden coding standards and static analysis coverage once migrated areas are stable.
+- Retire duplicate compatibility wrappers only after all call sites move to the shared abstractions.
+- Update developer documentation as each migration phase lands.
diff --git a/docs/php8-compatibility-checklist.md b/docs/php8-compatibility-checklist.md
new file mode 100644
index 0000000..f5c900f
--- /dev/null
+++ b/docs/php8-compatibility-checklist.md
@@ -0,0 +1,23 @@
+# PHP 8 compatibility checklist
+
+Use this checklist when touching legacy iForum code while PHP 8.2 through PHP 8.5 remain supported in CI.
+
+## Baseline checks
+
+- Keep `parallel-lint` green across the full `src/` tree.
+- Keep coding standards and static analysis green for the shared bootstrap helper and any newly added developer-facing files.
+- Avoid introducing dynamic properties, removed functions, or deprecated string/array access patterns.
+
+## Review checklist for changes
+
+- Confirm `include_once` and `require_once` paths still resolve correctly when dirname helpers are touched.
+- Check for implicit `null` to scalar conversions and loose comparisons that become noisier on newer PHP versions.
+- Prefer explicit return values over relying on legacy truthy/falsy behavior.
+- Avoid adding new references to removed PHP extensions or incompatible third-party tooling.
+- Keep legacy global state access (`icms::$module`, config arrays, handler factories) wrapped behind helper functions where possible.
+
+## Before merging refactors
+
+- Re-run the PHP quality workflow on PHP 8.2, 8.3, 8.4, and 8.5.
+- Verify install/update hooks still load through `src/icms_version.php` and `src/include/module.php`.
+- Confirm helper-only refactors do not alter templates, routes, or persisted data.
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..3cf7e6f
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,11 @@
+
+
+ Coding standards coverage for the shared bootstrap helper added in this refactor slice.
+
+
+
+
+ src/include/bootstrap.php
+
+
+
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..070ba61
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,7 @@
+parameters:
+ level: 0
+ paths:
+ - src/include/bootstrap.php
+ bootstrapFiles:
+ - tools/phpstan-bootstrap.php
+ tmpDir: /tmp/phpstan-iforum
diff --git a/src/include/bootstrap.php b/src/include/bootstrap.php
new file mode 100644
index 0000000..75ef220
--- /dev/null
+++ b/src/include/bootstrap.php
@@ -0,0 +1,63 @@
+getVar('dirname', 'n') === iforum_get_module_dirname()) {
+ $module = icms::$module;
+
+ return $module;
+ }
+
+ $moduleHandler = icms::handler('icms_module');
+ $module = $moduleHandler->getByDirname(iforum_get_module_dirname());
+
+ return $module;
+}
+
+function &iforum_get_handler($handlerName)
+{
+ $handler = icms_getmodulehandler($handlerName, iforum_get_module_dirname(), 'iforum');
+
+ return $handler;
+}
diff --git a/tools/phpstan-bootstrap.php b/tools/phpstan-bootstrap.php
new file mode 100644
index 0000000..41e659f
--- /dev/null
+++ b/tools/phpstan-bootstrap.php
@@ -0,0 +1,25 @@
+
Date: Tue, 26 May 2026 08:38:54 +0000
Subject: [PATCH 2/2] fix: make php quality checks pass locally
Agent-Logs-Url: https://github.com/iForumModule/iforum/sessions/dbcaa461-e0be-4886-b4aa-59aa69d7b84a
Co-authored-by: fiammybe <3736946+fiammybe@users.noreply.github.com>
---
phpcs.xml.dist | 1 +
src/class/art/functions.locale.php | 2 +-
src/include/bootstrap.php | 7 ++++++-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 3cf7e6f..aa2eac1 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -4,6 +4,7 @@
+
src/include/bootstrap.php
diff --git a/src/class/art/functions.locale.php b/src/class/art/functions.locale.php
index d367c6f..69e5a97 100644
--- a/src/class/art/functions.locale.php
+++ b/src/class/art/functions.locale.php
@@ -44,7 +44,7 @@ function xoops_local($func)
$msg = "The locale version is too old. Please copy
XOOPS/Frameworks/compat/language/english/local.php, local.class.php to XOOPS/language/english/";
if (icms::$config->getConfig("language") != "english") {
if (is_dir(ICMS_ROOT_PATH."/Frameworks/compat/language/".icms::$config->getConfig("language")."/")) {
- $msg .= "
XOOPS/Frameworks/compat/language/".icms::$config->getConfig("language")."/local.php to XOOPS/language/".icms::$config->getConfig("language"]."/";
+ $msg .= "
XOOPS/Frameworks/compat/language/".icms::$config->getConfig("language")."/local.php to XOOPS/language/".icms::$config->getConfig("language")."/";
} else {
$msg .= "
And modify XOOPS/language/".icms::$config->getConfig("language")."/local.php according to XOOPS/language/english/local.php";
}
diff --git a/src/include/bootstrap.php b/src/include/bootstrap.php
index 75ef220..0adf5bc 100644
--- a/src/include/bootstrap.php
+++ b/src/include/bootstrap.php
@@ -1,4 +1,5 @@
getVar('dirname', 'n') === iforum_get_module_dirname()) {
+ if (
+ isset(icms::$module)
+ && is_object(icms::$module)
+ && icms::$module->getVar('dirname', 'n') === iforum_get_module_dirname()
+ ) {
$module = icms::$module;
return $module;