Skip to content

Load the CMS code cache by its declared class instead of with require_once - #1570

Merged
LukeTowers merged 3 commits into
wintercms:wip/1.3from
austinderrick:fix/cms-codeparser-rebuild-require
Oct 16, 2026
Merged

LukeTowers merged 3 commits into
wintercms:wip/1.3from
austinderrick:fix/cms-codeparser-rebuild-require

Conversation

@austinderrick

@austinderrick austinderrick commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Cms\Classes\CodeParser writes the generated class for a page's PHP code section to a fixed path, but gives the class a new random name on every rebuild. Both rebuild() and source() loaded that file with require_once, which keys on the path, so a process that had already loaded the path skipped every later version of the file and the page failed:

Error: Class "Cms<hash>Class" not found

The later version can come from the same process or from another one. With several long-running workers (Laravel Octane, or queue workers rendering pages), worker B's rebuild is skipped by worker A, whose handleCorruptCache() then deletes and rebuilds the file, which invalidates worker B in turn. The workers keep rebuilding each other after every edit, and a third worker can hit the file while it is missing.

All three paths now load the file through requireClassFile(), which reads the class name the file declares and uses require only when that class is not loaded yet. require therefore never redeclares a class, and a new version of the file is always loaded. PHP-FPM behavior does not change, since each request starts with nothing loaded.

Split out of #1511 so it can be reviewed on its own.

Testing

modules/cms/tests/classes/CodeParserRebuildTest.php covers two rebuilds in one process and a rebuild written by another process (same path, new class name) that source() must load. Both fail without the change. The full CMS module suite passes (221 tests).

CodeParser::rebuild() writes the generated class to a fixed path, but gives the class a new random name on every rebuild. require_once keys on the path, so after the first rebuild of an object in a process, later rebuilds left their class undeclared and the page failed with "Class Cms...Class not found". This also defeated handleCorruptCache(), which rebuilds and then loads the result. require cannot redeclare anything, because each rebuild's class name is unique.
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a4563ac9-e329-4265-875c-93a826892b24

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

…er a rebuild

source() still loaded the cache file with require_once, so a process that had loaded the path before skipped a rebuild written by another process. handleCorruptCache() then deleted and rebuilt the file, which invalidated the other process in turn. rebuild(), source() and handleCorruptCache() now share requireClassFile(), which requires the file only when the class it declares is not loaded yet, so require can never redeclare a class.
@austinderrick austinderrick changed the title Load each CMS code cache rebuild with require instead of require_once Load the CMS code cache by its declared class instead of with require_once Oct 15, 2026
@LukeTowers
LukeTowers merged commit 02417ee into wintercms:wip/1.3 Oct 16, 2026
13 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