Skip to content

feat(moduletools): provide standalone PHP 8.4 library with API 1.1 - #1

Merged
mambax7 merged 22 commits into
XOOPS:masterfrom
mambax7:feat/standalone-library-1.5
Sep 21, 2026
Merged

mambax7 merged 22 commits into
XOOPS:masterfrom
mambax7:feat/standalone-library-1.5

Conversation

@mambax7

@mambax7 mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Makes xoops/moduletools a self-contained Composer package (PHP 8.4+) that installs, tests and analyses on its own while still running inside xoops_lib/vendor on XOOPS 2.8. Reconciles the 1.4.0 Core tree with the 1.5.0 consolidated cut, fixes a dozen runtime defects found on the way, and adds user documentation.

Motivation

The repository held the 1.4.0 source only: the runtime language catalog, the gate scripts and the API snapshots were missing, the test bootstrap required an autoloader three directories up, CI called a composer analyse script that did not exist, and phpstan.neon was copied from another package. Separately, two 1.5.0 trees existed with different contents (the site path repo vs. the consolidated cut with DirectoryChecker::handleRequest()), which is what broke Quotes on a fresh site.

Approach

  • Standalone: tests/bootstrap.php and the package scripts resolve the local vendor/autoload.php, falling back to Core's. Gate artifacts moved to resources/gate (export-ignored); the site-specific consumer audit is optional.
  • Dependencies: php ^8.4; xoops/xmf ^1.3 — every XMF class and method the library calls was checked against 1.3.1. No hardcoded version; sites pin it on their path repository.
  • Quality gate (composer qa): phpcs PSR-12 → PHPStan level 6 with stubs/xoops-core.stub generated from a real 2.8 core (baseline of 164 typing findings, no logic findings) → Rector PHP 8.4 + xoops/rector-xoops (applied) → API-surface/compat, destination-matrix, layer and legacy-global checks → PHPUnit. The API generator now records promoted constructor properties. CI on PHP 8.4 and 8.5.
  • Reconciliation with the 1.5.0 cut: DirectoryChecker::handleRequest() + action forms (with a fail-closed CSRF check), FileChecker constant names and catalog fallback, Blocksadmin _MI_* title tokens, the Cloner logo font, the Cloner/DirectoryChecker tests. Admin\Table and Common\Highlighter restored from the path-repo build.
  • Fixes: Helper::getDirname() (no such method in any XMF) → dirname() at all call sites; DynamicObject::setErrors(); Blocksadmin undefined $newid / double render(); Cloner sprintf on placeholder-less constants and silent partial clones; Db::cloneRecord() fetchArray arity; fputcsv escape (8.4 deprecation); VersionChecks by-ref assignment and dead fallbacks; strict-type mismatches in Confirm/Output/ObjectFormBuilder; LetterChoice Smarty 5 setCaching(); UpdateChecker repository parameter + github_repo manifest entry; consumer-constant precedence in ModuleFeedback/ServerStats.
  • Docs: docs/getting-started.md, docs/migrating-a-module.md, docs/compatibility-policy.md.

Testing

  • composer qa green on PHP 8.4.25: 61 tests / 269 assertions (15 skip unless the package sits inside a XOOPS tree).
  • Installed on a XOOPS 2.8.0-Alpha1 site (PHP 8.5) via the path repository; Quotes admin index, quote list, blocks admin, clone, feedback, about, migrate and the front page render with 0 errors / 0 deprecations in the XOOPS logger.
  • Public API: 4 symbols added, handleRequest() and one optional parameter added, no removals (composer api:compat).

Checklist

  • PSR-12 passes (composer cs)
  • PHPStan passes (composer analyse)
  • PHPUnit passes (composer test)
  • No BC break: minimum PHP raised to 8.4 (documented in CHANGELOG); public 1.x API retained

Turn the Core-bundled 1.4.0 tree into a self-contained Composer package
that installs, tests and analyses on its own while still running inside
xoops_lib/vendor on a XOOPS 2.8 site.

Package
- Ship resources/ (language catalog, Cloner font); scripts and tests
  resolve the package-local vendor/autoload.php, falling back to Core's.
- Require PHP ^8.4; widen xoops/xmf to ^1.3 (every API used exists in
  1.3.1). Drop the hardcoded version; sites pin it on the path repo.
- Quality gate: phpcs (PSR-12), PHPStan level 6 with stubs generated from
  a real XOOPS 2.8 core, Rector (PHP 8.4 + xoops/rector-xoops) applied,
  package-local API/matrix/layer/global checks, PHPUnit. CI on 8.4/8.5.
- Gate artifacts live in resources/gate (export-ignored); site-specific
  audits are no longer required.

Reconcile the 1.5.0 consolidated cut
- DirectoryChecker::handleRequest() with create/chmod action forms,
  fail-closed CSRF check, catalog fallback; FileChecker constant names;
  Blocksadmin _MI_* title-token handling; Cloner/DirectoryChecker tests.
- Restore Admin\Table and Common\Highlighter from the path-repo build.

Fixes
- Xmf\Module\Helper::getDirname() does not exist; use dirname() at every
  call site (Blocksadmin, Cloner, Confirm, LetterChoice, Testdata*).
- DynamicObject::setErrors() called a non-existent setError().
- Blocksadmin: undefined $newid on failed store(); render() echoed twice.
- Cloner: sprintf on placeholder-less constants; partial clones now throw.
- Db::cloneRecord() passed a second argument to fetchArray().
- Export: fputcsv escape argument (PHP 8.4 deprecation).
- VersionChecks: by-reference assignment from a call, dead fallbacks.
- Strict-type mismatches in Confirm, Output, ObjectFormBuilder.
- LetterChoice: setCaching(CACHING_OFF) instead of a Smarty property write.
- UpdateChecker accepts a repository and honours the github_repo manifest
  entry; ModuleFeedback and ServerStats resolve consumer constants first.
Getting started covers install, Helper/ModuleContext, install hooks,
version guards, admin CRUD, DynamicObject forms, front-end helpers,
permissions, sample data and language-constant resolution. The migration
guide walks a module off copied Common classes or the mTools module in
independently shippable steps. The compatibility policy states what the
1.x line keeps and the conditions for any removal.
Copilot AI lite review requested due to automatic review settings September 21, 2026 07:27

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @mambax7, your pull request is larger than the review limit of 150,000 diff characters

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 158 files, which is 58 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c2061db6-0dc9-405d-ad52-04c82f14909b

📥 Commits

Reviewing files that changed from the base of the PR and between 404a40e and 3792bea.

⛔ Files ignored due to path filters (1)
  • resources/fonts/VeraBd.ttf is excluded by !**/*.ttf
📒 Files selected for processing (158)
  • .coderabbit.yaml
  • .editorconfig
  • .gitattributes
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/dependabot.yml
  • .github/workflows/ci.yml
  • .github/workflows/code-coverage.yml
  • .github/workflows/dependency-review.yml
  • .gitignore
  • .scrutinizer.yml
  • CHANGELOG.md
  • CODEOWNERS
  • CONTRIBUTING.md
  • LICENSE
  • README.md
  • SECURITY.md
  • SUPPORT.md
  • composer.json
  • docs/compatibility-policy.md
  • docs/getting-started.md
  • docs/migrating-a-module.md
  • index.php
  • phpcs.xml
  • phpstan-baseline.neon
  • phpstan-bootstrap.php
  • phpstan.neon
  • phpunit.xml.dist
  • rector.php
  • resources/gate/api-surface-allowlist.json
  • resources/gate/api-surface-baseline.json
  • resources/gate/api-surface.json
  • resources/gate/destination-matrix.json
  • resources/gate/destination-matrix.md
  • resources/gate/promotion-backlog.md
  • resources/language/english/common.php
  • resources/migration/class-reuse-decisions.php
  • resources/migration/destination-decisions.php
  • scripts/check-api-compat.php
  • scripts/check-destination-matrix.php
  • scripts/check-global-accessors.php
  • scripts/check-layers.php
  • scripts/generate-api-surface.php
  • scripts/generate-destination-matrix.php
  • scripts/lint-php.php
  • sonar-project.properties
  • src/Admin/Export.php
  • src/Admin/ObjectColumn.php
  • src/Admin/ObjectController.php
  • src/Admin/ObjectRow.php
  • src/Admin/ObjectTable.php
  • src/Admin/SingleView.php
  • src/Admin/Table.php
  • src/Admin/TreeTable.php
  • src/Admin/Utility.php
  • src/Bootstrap.php
  • src/Common/Blocksadmin.php
  • src/Common/Breadcrumb.php
  • src/Common/Cloner.php
  • src/Common/Configurator.php
  • src/Common/Confirm.php
  • src/Common/Db.php
  • src/Common/DbInterface.php
  • src/Common/DirectoryChecker.php
  • src/Common/FileChecker.php
  • src/Common/FilesManagement.php
  • src/Common/Highlighter.php
  • src/Common/ImageResizerInterface.php
  • src/Common/LetterChoice.php
  • src/Common/Media/MediaUploadRequest.php
  • src/Common/Migrate.php
  • src/Common/ModuleConfig.php
  • src/Common/ModuleFeedback.php
  • src/Common/ModuleStats.php
  • src/Common/ObjectTree.php
  • src/Common/Output.php
  • src/Common/PaginationState.php
  • src/Common/PaginationStateInterface.php
  • src/Common/Paginator.php
  • src/Common/ResizeRequest.php
  • src/Common/ResizeResult.php
  • src/Common/Resizer.php
  • src/Common/ServerStats.php
  • src/Common/SocialBookmarks.php
  • src/Common/StandardConfig.php
  • src/Common/SysUtility.php
  • src/Common/TestdataButtons.php
  • src/Common/TestdataSample.php
  • src/Common/Text.php
  • src/Common/TextInterface.php
  • src/Common/UpdateChecker.php
  • src/Common/VersionChecks.php
  • src/Constants.php
  • src/Form/ObjectFormBuilder.php
  • src/Internal/Confirmation/ConfirmationModel.php
  • src/Internal/Confirmation/ConfirmationResolver.php
  • src/Internal/Installation/InstallationPlan.php
  • src/Internal/PackageLanguage.php
  • src/Internal/Presentation/ObjectValuePresenter.php
  • src/Internal/Presentation/SortControlBuilder.php
  • src/Internal/Presentation/SortControlResult.php
  • src/Internal/Tools/ConsumerBridgeGenerator.php
  • src/Internal/Update/VersionUpdatePolicy.php
  • src/Module/ConsumerRuntime.php
  • src/Module/Dependency.php
  • src/Module/Installer.php
  • src/Module/ModuleContext.php
  • src/Module/NamespaceAutoloader.php
  • src/Object/DynamicObject.php
  • src/Object/SeoObject.php
  • src/Permission/ItemPermission.php
  • src/Permission/PermissionGatewayInterface.php
  • src/Permission/XoopsPermissionGateway.php
  • src/Persistence/PersistableHandler.php
  • src/Persistence/PersistableHandler2.php
  • src/Utility.php
  • src/legacy_aliases.php
  • stubs/xoops-constants.php
  • stubs/xoops-core.stub
  • tests/Admin/ExportTest.php
  • tests/Admin/ObjectControllerTest.php
  • tests/Admin/UtilityTest.php
  • tests/ApiSurfaceTest.php
  • tests/BootstrapTest.php
  • tests/Common/ClonerTest.php
  • tests/Common/DbQueriesTest.php
  • tests/Common/DbTest.php
  • tests/Common/DirectoryCheckerTest.php
  • tests/Common/FileCheckerTest.php
  • tests/Common/HighlighterTest.php
  • tests/Common/ModuleConfigTest.php
  • tests/Common/ModuleStatsTest.php
  • tests/Common/ObjectTreeTest.php
  • tests/Common/PaginatorTest.php
  • tests/Common/ServerStatsTest.php
  • tests/Common/TextTest.php
  • tests/Common/UpdateCheckerTest.php
  • tests/Common/VersionChecksTest.php
  • tests/ExtcalConsumerTest.php
  • tests/Form/ObjectFormBuilderTest.php
  • tests/Internal/PackageLanguageTest.php
  • tests/Internal/Presentation/ObjectValuePresenterTest.php
  • tests/Internal/SemanticServicesTest.php
  • tests/Migration/FilesystemDelegationTest.php
  • tests/Migration/MigrateDelegationTest.php
  • tests/Migration/ModuleContextDelegationTest.php
  • tests/Migration/PaginationNonParityTest.php
  • tests/Module/NamespaceAutoloaderTest.php
  • tests/Permission/ItemPermissionTest.php
  • tests/QuotesConsumerTest.php
  • tests/SmartModulesConsumerTest.php
  • tests/Support/FakeObject.php
  • tests/Tools/ApiCompatibilityGateTest.php
  • tests/Tools/ConsumerBridgeGeneratorTest.php
  • tests/bootstrap.php
  • tests/fixtures/core-stubs.php

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gitar-bot

gitar-bot Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Gitar is working

Gitar

CodeRabbit skips pull requests above 100 files. Exclude generated gate
artifacts, stubs, the PHPStan baseline, docs, tests, scripts and repo
metadata so src/ and the tool configuration get reviewed.
@mambax7

mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review skipped: 142 files exceed the limit of 100.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mambax7

mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review skipped: 142 files exceed the limit of 100.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Critical CSRF vulnerabilities and multiple unresolved runtime, compatibility, and tooling defects remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 High severity · 5 Medium severity · 1 Low severity

Open (9)
What changed in this PR

This PR makes xoops/moduletools a standalone PHP 8.4+ Composer library while preserving XOOPS compatibility.

Changes:

  • Adds Composer packaging, CI, QA, API, and migration tooling.
  • Adds module, admin, persistence, permission, filesystem, and presentation APIs.
  • Adds compatibility tests and migration documentation.

Outstanding findings: Critical CSRF gaps remain in src/Admin/ObjectController.php (3 votes), src/Common/Cloner.php (3 votes), and src/Common/TestdataButtons.php (1 vote). Moderate issues remain with missing ext-mbstring (1), embedded autoloader fallbacks in three scripts and tests/bootstrap.php (1 each), ObjectTable filtering/actions (3 and 2), clone cleanup (1), database failure handling (3), text truncation (1), update-cache keys (2), persistence-handler argument forwarding (1), and SmartModules test skipping (2). The security-template link is a nit (2 votes).

File Summary
tests/​Tools/​ConsumerBridgeGeneratorTest.php Reviewed consumer bridge coverage.
tests/​SmartModulesConsumerTest.php Reviewed module consumer coverage; skip-condition issue noted.
tests/​QuotesConsumerTest.php Reviewed Quotes integration coverage.
tests/​Permission/​ItemPermissionTest.php Reviewed permission tests.
tests/​Module/​NamespaceAutoloaderTest.php Reviewed namespace autoloading tests.
tests/​Migration/​PaginationNonParityTest.php Reviewed pagination migration coverage.
tests/​Migration/​ModuleContextDelegationTest.php Reviewed module-context delegation tests.
tests/​Migration/​MigrateDelegationTest.php Reviewed migration delegation tests.
tests/​Migration/​FilesystemDelegationTest.php Reviewed filesystem delegation tests.
tests/​Internal/​SemanticServicesTest.php Reviewed semantic service tests.
tests/​Internal/​PackageLanguageTest.php Reviewed package-language tests.
tests/​fixtures/​core-stubs.php Reviewed Core test fixtures.
tests/​ExtcalConsumerTest.php Reviewed Extcal consumer coverage.
tests/​Common/​ServerStatsTest.php Reviewed server-stat tests.
tests/​Common/​ModuleStatsTest.php Reviewed module-stat tests.
tests/​Common/​ModuleConfigTest.php Reviewed module-config tests.
tests/​Common/​DirectoryCheckerTest.php Reviewed directory-checker tests.
tests/​Common/​ClonerTest.php Reviewed cloner tests.
tests/​BootstrapTest.php Reviewed bootstrap tests.
tests/​bootstrap.php Reviewed test bootstrap; embedded fallback issue noted.
tests/​ApiSurfaceTest.php Reviewed API-surface tests.
tests/​Admin/​UtilityTest.php Reviewed admin utility tests.
SUPPORT.md Reviewed support documentation.
stubs/​xoops-constants.php Reviewed analysis constants.
src/​Utility.php Reviewed utility facade.
src/​Persistence/​PersistableHandler2.php Reviewed persistence compatibility wrapper.
src/​Persistence/​PersistableHandler.php Reviewed handler forwarding; argument-contract issue noted.
src/​Permission/​XoopsPermissionGateway.php Reviewed XOOPS permission gateway.
src/​Permission/​PermissionGatewayInterface.php Reviewed permission interface.
src/​Permission/​ItemPermission.php Reviewed item-permission API.
src/​Object/​SeoObject.php Reviewed SEO object support.
src/​Module/​NamespaceAutoloader.php Reviewed namespace autoloading.
src/​Module/​ModuleContext.php Reviewed module context.
src/​Module/​Installer.php Reviewed module installer.
src/​Module/​Dependency.php Reviewed dependency handling.
src/​Module/​ConsumerRuntime.php Reviewed consumer runtime.
src/​legacy_aliases.php Reviewed legacy aliases.
src/​Internal/​Update/​VersionUpdatePolicy.php Reviewed update policy.
src/​Internal/​Presentation/​SortControlResult.php Reviewed sort-control result.
src/​Internal/​Presentation/​SortControlBuilder.php Reviewed sort-control builder.
src/​Internal/​PackageLanguage.php Reviewed package language service.
src/​Internal/​Installation/​InstallationPlan.php Reviewed installation plan.
src/​Internal/​Confirmation/​ConfirmationResolver.php Reviewed confirmation resolver.
src/​Internal/​Confirmation/​ConfirmationModel.php Reviewed confirmation model.
src/​Form/​ObjectFormBuilder.php Reviewed object form builder.
src/​Constants.php Reviewed shared constants.
src/​Common/​VersionChecks.php Reviewed version checks.
src/​Common/​UpdateChecker.php Reviewed update checker; repository cache-key issue noted.
src/​Common/​TextInterface.php Reviewed text interface.
src/​Common/​Text.php Reviewed text helpers; short-length truncation issue noted.
src/​Common/​StandardConfig.php Reviewed standard configuration.
src/​Common/​SocialBookmarks.php Reviewed social-bookmark support.
src/​Common/​ServerStats.php Reviewed server statistics.
src/​Common/​ResizeResult.php Reviewed resize result.
src/​Common/​ResizeRequest.php Reviewed resize request.
src/​Common/​PaginationStateInterface.php Reviewed pagination interface.
src/​Common/​PaginationState.php Reviewed pagination state.
src/​Common/​Output.php Reviewed output handling.
src/​Common/​ObjectTree.php Reviewed object tree.
src/​Common/​ModuleStats.php Reviewed module statistics.
src/​Common/​ModuleFeedback.php Reviewed module feedback.
src/​Common/​ModuleConfig.php Reviewed module configuration.
src/​Common/​Migrate.php Reviewed migration helper.
src/​Common/​Media/​MediaUploadRequest.php Reviewed media upload request.
src/​Common/​ImageResizerInterface.php Reviewed image-resizer interface.
src/​Common/​Highlighter.php Reviewed highlighter.
src/​Common/​DbInterface.php Reviewed database interface.
src/​Common/​Confirm.php Reviewed confirmation helper.
src/​Common/​Breadcrumb.php Reviewed breadcrumb helper.
src/​Bootstrap.php Reviewed runtime bootstrap.
src/​Admin/​Utility.php Reviewed admin utilities.
src/​Admin/​TreeTable.php Reviewed tree-table support.
src/​Admin/​Table.php Reviewed admin table base.
src/​Admin/​SingleView.php Reviewed single-view support.
src/​Admin/​ObjectTable.php Reviewed object table; filtering and bulk-action issues noted.
src/​Admin/​ObjectRow.php Reviewed object rows.
src/​Admin/​ObjectController.php Reviewed controller; fail-closed CSRF issue noted.
src/​Admin/​ObjectColumn.php Reviewed object columns.
src/​Admin/​Export.php Reviewed export support.
sonar-project.properties Reviewed Sonar configuration.
SECURITY.md Reviewed security policy.
scripts/​lint-php.php Reviewed PHP lint script.
scripts/​generate-destination-matrix.php Reviewed destination-matrix generation.
scripts/​check-layers.php Reviewed layer gate; embedded fallback issue noted.
scripts/​check-global-accessors.php Reviewed global-accessor gate; embedded fallback issue noted.
scripts/​check-destination-matrix.php Reviewed destination-matrix gate.
scripts/​check-api-compat.php Reviewed API compatibility gate.
resources/​migration/​class-reuse-decisions.php Reviewed migration decisions.
resources/​gate/​api-surface-allowlist.json Reviewed API allowlist.
rector.php Reviewed Rector configuration.
README.md Reviewed package documentation.
phpunit.xml.dist Reviewed PHPUnit configuration.
phpstan.neon Reviewed PHPStan configuration.
phpstan-bootstrap.php Reviewed PHPStan bootstrap.
phpcs.xml Reviewed PHPCS configuration.
index.php Reviewed direct-access guard.
docs/​compatibility-policy.md Reviewed compatibility policy.
CONTRIBUTING.md Reviewed contribution guidance.
composer.json Reviewed package requirements; ext-mbstring declaration issue noted.
CODEOWNERS Reviewed ownership configuration.
CHANGELOG.md Reviewed change history.
.scrutinizer.yml Reviewed Scrutinizer configuration.
.gitignore Reviewed ignore rules.
.github/​workflows/​dependency-review.yml Reviewed dependency workflow.
.github/​workflows/​code-coverage.yml Reviewed coverage workflow.
.github/​workflows/​ci.yml Reviewed CI workflow.
.github/​PULL_REQUEST_TEMPLATE.md Reviewed pull-request template.
.github/​ISSUE_TEMPLATE/​feature_request.yml Reviewed feature template.
.github/​ISSUE_TEMPLATE/​config.yml Reviewed issue configuration; security-link nit noted.
.github/​ISSUE_TEMPLATE/​bug_report.yml Reviewed bug template.
.github/​dependabot.yml Reviewed Dependabot configuration.
.gitattributes Reviewed export attributes.
.editorconfig Reviewed editor configuration.
.coderabbit.yaml Reviewed review configuration.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Admin/ObjectController.php Outdated
Comment thread src/Common/Cloner.php
Comment thread src/Common/TestdataButtons.php Outdated
Comment thread src/Admin/ObjectTable.php
Comment thread src/Admin/ObjectTable.php
Comment thread src/Common/Db.php Outdated
Comment thread src/Common/UpdateChecker.php Outdated
Comment thread tests/SmartModulesConsumerTest.php Outdated
Comment thread .github/ISSUE_TEMPLATE/config.yml Outdated
…w findings

Copilot's review of XOOPS#1 found two more fail-open token checks and a set
of pre-existing defects; all are addressed here.

Security
- ObjectController::storeFromDefaultForm()/handleObjectDeletion() and
  Cloner::handleAdminRequest() now reject the request when no security
  service (or its check()) is available, as DirectoryChecker already did.
- TestdataButtons: the load/save/clear links carry the XOOPS token in
  both renderers, not only the hide/show toggle.

Fixes
- ObjectTable::addFilter() now renders a select per filter (options from
  the handler method) and applies the chosen value to the criteria,
  preserving sort/order/limit/start/group-by; an explicit "All" clears a
  configured default.
- ObjectTable::addWithSelectedActions() renders a checkbox column and a
  "with selected" form posting op, <keyName>[] ids and the token.
- Db::cloneRecord() returns false after a failed source lookup instead of
  continuing with a non-array.
- UpdateChecker: the cache key includes the repository so the optional
  $repository argument is not shadowed by an earlier result.
- SmartModulesConsumerTest skips unless all four module trees exist.
- Issue template: security contact link points at this repository.
@mambax7

mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review skipped: 142 files exceed the limit of 100.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved security and correctness issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (9)
Previously missed (1)

In code that hasn't changed since last review

Medium severity ObjectRow rendering ignores headers, classes, actions, and row options

src/​Admin/​SingleView.php:35

ObjectRow::$header and $class are part of the public row contract but are discarded here, so header rows and custom CSS classes always render as an ordinary <dt>/<dd> pair. The constructor's $actions and $headerAsRow options are likewise ignored, making callers receive incorrect detail-view markup instead of the requested configuration.

Comment thread src/Common/Output.php Outdated
Comment thread src/Internal/Tools/ConsumerBridgeGenerator.php Outdated
…leView rows

Second Copilot pass on XOOPS#1.

- Output::selectSorting(): the REQUEST_URI form action, sort hrefs, icon
  URLs and label are escaped at emission; SortControlBuilder encodes the
  sort key and normalises start to an integer.
- SingleView honours ObjectRow header/class and the constructor's actions
  and headerAsRow, which were accepted but ignored.
- ConsumerBridgeGenerator converts boolean columns with a numeric
  comparison instead of a bool cast.
@mambax7

mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review skipped: 142 files exceed the limit of 100.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved critical and moderate defects must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 6 High severity

Open (6)
Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Initialize extra and fix suffix condition

src/​Common/​LetterChoice.php:88

$this->extra is never initialized when the default empty $extra_arg is used, so render() later reads an undefined property. Also, the || condition is always true for a non-empty string, so already-suffixed arguments get another &amp; prefix; initialize the property and require both suffix checks to pass.

Medium severity Handle unresolved modules before permission checks

src/​Object/​DynamicObject.php:181

PersistableHandler::getModuleInfo() is declared to return object|false; when the module cannot be resolved, passing that false value to ItemPermission::forModule(object $module) raises a TypeError instead of making accessGranted() return its advertised boolean result. Check the module object before constructing the permission service.

Comment thread src/Admin/ObjectController.php
Comment thread src/Common/Blocksadmin.php Outdated
Comment thread src/Form/ObjectFormBuilder.php Outdated
Comment thread src/Internal/Tools/ConsumerBridgeGenerator.php
Comment thread src/Internal/Tools/ConsumerBridgeGenerator.php Outdated
Comment thread src/Permission/ItemPermission.php Outdated
- ObjectController: return after the not-found redirect in handleObjectDeletion
- Blocksadmin: escape the raw block title in the hidden oldtitle input
- ObjectFormBuilder: read control options only when the control is an array
- ConsumerBridgeGenerator: allowlist criteria operators and connectors in the
  generated whereClause; skip the UPDATE for key-only tables
- ItemPermission::replace: restore the previous grants when an add fails
- LetterChoice: initialise $extra and require both suffix checks to fail
- DynamicObject::accessGranted: return false when the module cannot be resolved
…te audit

The consumer audit under docs/internal is never committed, so CI regenerated
the matrix with every symbol marked unused and reported the committed
artifacts as stale. When the audit is absent, carry consumer usage over from
the committed destination-matrix.json instead.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Critical security and correctness issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 4 High severity

Open (4)
Resolved since last review (6)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Missing module result is dereferenced without validation

src/​Common/​VersionChecks.php:36

XoopsModule::getByDirname() returns XoopsModule|false when the consumer module cannot be resolved (the Core stub documents that contract), but this path immediately calls getVar() on the result. A missing/invalid module therefore throws instead of returning the documented boolean failure; guard the resolved value with instanceof \XoopsModule before dereferencing it.

This issue also appears on line 65 of the same file.

Comment thread src/Admin/Export.php Outdated
Comment thread src/Common/Confirm.php Outdated
Comment thread src/Form/ObjectFormBuilder.php Outdated
Comment thread src/legacy_aliases.php

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Final review comments identify unresolved security, correctness, and compatibility issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 4 High severity

Open (4)
Resolved since last review (6)
Previously missed (1)

In code that hasn't changed since last review

Medium severity ENUM and SET values are parsed incorrectly

src/​Common/​Db.php:166

This extracts only the first character/value from COLUMN_TYPE (substr(..., 5, -6)); for a normal enum('a','b') it returns just a, and SET columns are also parsed incorrectly. enumerate() therefore loses allowed values for the documented ENUM/SET contract. Parse the enum(...)/set(...) body and split the quoted values instead.

Comment thread src/Common/Db.php Outdated
Comment thread src/Common/Paginator.php Outdated
Comment thread src/Common/TestdataSample.php
Comment thread src/Permission/XoopsPermissionGateway.php
- TestdataSample::loadData()/saveData()/clearData() require an administrator session and a valid XOOPS token (TestdataButtons::isAuthorizedRequest()), so a consumer's testdata/index.php cannot run them unguarded
- Paginator HTML-escapes the generated page links; PHP_SELF and urlOther could break out of the href attribute
- Db::enumerate() validates the table name like its siblings; Db::enumValues() parses ENUM/SET column types correctly instead of returning a fragment of the first value

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (4)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Escape search terms consistently before regex matching

src/​Common/​Highlighter.php:26

The regex is built from raw search terms but applied to $escaped text. Terms containing & (for example R&D) therefore never match, and a term exactly & matches only the start of &amp;, producing broken output such as <mark>&</mark>amp;. Escape each term with the same HTML settings before preg_quote() so matching preserves the rendered text.

Medium severity Allow autoloading before installing XOOPS class stubs

tests/​fixtures/​core-stubs.php:21

These guards suppress autoloading with the second false argument. In an embedded XOOPS run, the real core classes may be registered but not loaded yet, so this test defines empty stubs and permanently shadows the core definitions; later consumers then miss core methods or hit redeclaration errors. Let class_exists() autoload the real class first, or only install these stubs when no XOOPS runtime is available.

Comment thread src/Common/Blocksadmin.php
Comment thread src/Common/Blocksadmin.php Outdated
- Blocksadmin::isBlockCloned() casts request-supplied module and group ids before building the INSERT statements; updateBlock() deletes only the block's own block_read rows instead of every permission row sharing the item id
- Highlighter matches on the raw text and escapes each piece afterwards, so R&D, quotes and angle brackets are found and a term such as amp can no longer split an entity
- test core stubs let class_exists() autoload the real XOOPS class before installing an empty stand-in

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Unresolved compatibility, security, filesystem traversal, migration, and URL-handling issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 5 High severity

Open (5)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity URL-encode query values to preserve embedded ampersands

tests/​Common/​PaginatorTest.php:35

The expected href preserves the decoded value q=a&b as q=a&amp;b, but the browser decodes &amp; before parsing the URL, turning this into two query parameters (q=a and b). That loses the original q=a%26b value; URL-encode the parsed query values before HTML-escaping and assert %26 here.

"symbols/Xoops\\ModuleTools\\Persistence\\PersistableHandler/methods/setGrantedObjectsCriteria/documented_false_or_null:value-changed",
"symbols/Xoops\\ModuleTools\\Common\\VersionChecks/methods/checkVerPhp/parameters/0/type:value-changed",
"symbols/Xoops\\ModuleTools\\Common\\VersionChecks/methods/checkVerXoops/parameters/0/type:value-changed",
"symbols/Xoops\\ModuleTools\\Common\\ObjectTree/methods/makeSelBox:removed",
Comment thread src/Admin/Export.php Outdated
Comment thread src/Common/DirectoryChecker.php
Comment thread src/Common/FileChecker.php
Comment thread src/Common/Paginator.php Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comment thread src/Common/Db.php Outdated
Comment thread src/Common/Db.php Outdated
Comment thread src/Common/Text.php Outdated
Comment thread src/Common/UpdateChecker.php Outdated
Comment thread src/Internal/Update/VersionUpdatePolicy.php

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The dependency-review workflow cannot resolve its action ref, the API gate misses stale allowlist removals, and CSV formula protection omits line-feed-prefixed payloads.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 3 High severity · 1 Medium severity

Open (4)
Resolved since last review (4)

Comment thread scripts/check-api-compat.php
Comment thread src/Admin/Export.php Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

HTML entity truncation is currently incorrect, and the API version does not reflect the newly added public surface.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (3)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Bump API version for newly added public symbols

src/​Bootstrap.php:16

API_VERSION remains 1.0.0 even though this release adds public symbols, while the new compatibility policy says this value changes when a minor release adds API. Consumers therefore cannot use ConsumerRuntime::guard() to distinguish the newly expanded API from the previous 1.0 surface. Bump the API version and update the generated snapshots, allowlist, and tests consistently.

Medium severity Count rendered characters when checking short HTML input

src/​Common/​Text.php:54

The short-input check counts the encoded spelling instead of the rendered character. For example, truncateHtml('&amp;', 1, '...', true) currently returns the malformed &am... rather than the unchanged one-character text. Normalize entities in this length check just as the loop below does.

@mambax7
mambax7 requested a balanced review from Copilot September 21, 2026 22:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

Review effort: Balanced
Findings: 1 High severity

Open (1)

@mambax7

mambax7 commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed in cfb2947: makeSelBox() retains its original signature and options-array return contract, delegating to makeOptionsArray(). Regression coverage confirms this behavior.

@mambax7 mambax7 changed the title feat(moduletools): make xoops/moduletools a standalone PHP 8.4 library feat(moduletools): provide standalone PHP 8.4 library with API 1.1 Sep 21, 2026
@mambax7
mambax7 merged commit 45707bd into XOOPS:master Sep 21, 2026
5 checks passed
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.

2 participants