Skip to content

docs(tutorials): fact-check against MODX 3.x, rewrite examples, en/ru sync - #654

Merged
Ibochkarev merged 4 commits into
modxorg:3.xfrom
Ibochkarev:docs/tutorials
Oct 15, 2026
Merged

Ibochkarev merged 4 commits into
modxorg:3.xfrom
Ibochkarev:docs/tutorials

Conversation

@Ibochkarev

Copy link
Copy Markdown
Collaborator

Audit of en/extending-modx/tutorials/** against modxcms/revolution 3.x, an editorial pass, and an en/ru sync.

Findings: 132 — 10 PHANTOM, 48 STALE, 9 ORPHAN, 43 UNDOCUMENTED, 22 UNVERIFIABLE. 129 closed; the rest are historical claims that cannot be checked in the working copy.

The section was written for 2.x and no longer ran. Several examples fataled on 3.x, and the CMP described by part 2 was unreachable as written.

Examples that did not run

  • new modPackageBuilder($modx) — no such global class in 3.x, the script dies on line one. Replaced with the Composer-autoloaded MODX\Revolution\Transport\modPackageBuilder; the modx.class.php bootstrap and loadClass() calls are gone.
  • xPDO schema: in the 3.x generator package becomes a PHP namespace and version="1.0" skips PSR-4 registration, so getCollection('Doodle') returned null and count() threw. Rewritten with package="Doodles\Model", version="3.0", namespaced base and related classes, and the model generated into src/Model/.
  • mgr/doodle/getList against a file named getlist.class.php: MODX builds the processor path without lowercasing the case, so it works on macOS and fails on Linux. File names now match the action, with a warning explaining why.
  • The category file resolvers were attached after putVehicle(), which copies the vehicle into the package — they were silently dropped and nothing arrived on install. Reordered, with a warning.

Facts

  • $modx->getService() is deprecated and scheduled for removal; the snippet now takes the service from the container, registered in bootstrap.php.
  • The doodles.core_path / doodles.assets_url system settings chapter is replaced by the Namespace record, which is what bootstrap.php and the resolver read.
  • modAction and the integer ?a=2 routing no longer exist; the menu item plus namespace and action name is the route, and the controller lookup order is documented.
  • Connector auth: the modAuth / HTTP_MODAUTH value is a per-user, per-context session token, not $modx->siteId.
  • Processors use MODX\Revolution\Processors\Model\* and a namespaced $classKey.
  • The build script produces doodles-1.0-beta4.transport.zip; the menu vehicle gained permissions (an empty list leaves the item visible to every manager user) and an HTML icon, and PRESERVE_KEYS is explained as a SQL Server-only flag.
  • custom-manager-fields: OnFormRender does not exist — removed, replaced with the table of manager form events.
  • using-custom-database-tables: field lists match the schema again, xPDO paths corrected, version="3.0" documented, plus warnings for the two silent failures (bootstrap.php running before the Context exists, and Could not load package metadata).

Editorial pass

Prose cut by roughly a third, reference data moved into tables, examples trimmed to what the code actually reads. ru synced: same structure, code and facts.

Illustrations

Ten media briefs were collected. The existing screenshots are from the 2.x manager — "System" menu instead of "Admin", "Create New" instead of "Create", "Permission" instead of "Permissions" — and are listed in .temp/docs-review/media-todo.md for re-shooting.

… sync

The Tutorials section was written for 2.x and no longer ran: several
examples fataled on 3.x and the CMP was unreachable as described.

Fixed against revolution 3.x (reports in .temp/docs-review):

- `new modPackageBuilder($modx)` replaced with the Composer-autoloaded
  `MODX\Revolution\Transport\modPackageBuilder`; `modx.class.php`
  bootstrap and `loadClass()` calls dropped
- xPDO schema rewritten for the 3.x generator: `package="Doodles\Model"`,
  `version="3.0"`, namespaced base classes and related classes,
  `namespacePrefix`, model generated into `src/Model/`
- `$modx->getService()` replaced with `bootstrap.php` + the dependency
  injection container; the "magic path settings" chapter replaced with the
  Namespace record
- CMP routing: `modAction` and `?a=<number>` no longer exist; the menu
  item plus namespace and action name is the route, and the controller
  lookup order is documented
- processor examples use `MODX\Revolution\Processors\Model\*`, a namespaced
  `$classKey`, and file names that match the case of the action — the old
  `getlist.class.php` worked on macOS and failed on Linux
- connector auth token described correctly: a per-user, per-context
  session token, not `$modx->siteId`
- build script: resolvers must be attached before `putVehicle()`, package
  file is `*.transport.zip`, menu gains `permissions` and an HTML icon
- custom-manager-fields: removed the non-existent `OnFormRender`, added the
  table of manager form events
- custom-database-tables: field lists match the schema again, xPDO paths
  corrected, `version="3.0"` documented, two silent-failure warnings added

Editorial pass: prose cut by a third, reference data moved into tables,
examples trimmed to what the code reads. en/ru synced. Missing
illustrations collected in .temp/docs-review/media-todo.md — the existing
screenshots are from the 2.x manager and need re-shooting.
The ru sync left three leftovers: the terminology section still had the
2.x-era subsections instead of the en table, "Дополнительно для любознательных :)"
sat above the bootstrap.php timing warning, and the section index still
introduced the tutorial as a "Компонент" while the pages themselves say Extra.

Also corrected the `initialize('web')` sentence, which ignored
config.context.php, and the InnoDB recommendation, which code does not make.
…ates

The packaged menu set `permissions => 'doodles_view'`, but nothing in the
tutorial creates that permission: in MODX 3 a permission is a row in
`access_permissions` attached to a policy template (modAccessPermission,
core/model/schema/modx.mysql.schema.xml:156), created in Access ->
Permissions, not something a namespace or a system setting produces.

Left as it was, the installed package hid the CMP from every user —
modManagerResponse::checkForMenuPermissions() raises AccessDeniedException
on a direct hit and header.php skips the entry when hasPermission() is false.

The field is now empty, as in part 2, and the section explains both
directions: an empty list means no restriction, and a name in the column has
to exist and be granted before it can hide anything.
CI (Validate markdown, MD007/ul-indent) rejected the nested part list in
the Tutorials index: the project lints unordered list indentation at four
spaces. Rather than nest, the three parts are now top-level entries named
"Developing an Extra, part N" — the grouping is already in the name, and a
flat list needs no indentation rule to hold it.

markdownlint-cli over the whole section is clean.
@Ibochkarev
Ibochkarev merged commit 2bbe59a into modxorg:3.x Oct 15, 2026
2 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.

1 participant