acf-lint --wpml: check wpml_cf_preferences VALUE by field type (Layers 1-3) - #31
Merged
Conversation
Extends `--wpml` from presence-only to a type -> value check for three layers of certainty, per issue #30's layered proposal: - Layer 1 (plugin fact): `repeater` / `flexible_content` must be `3` — ACFML forcibly overrides both to WPML_COPY_ONCE_CUSTOM_FIELD (= 3) at runtime regardless of the configured value (WRAPPER_FIELDS + field_should_be_set_to_copy_once()). Any other value is dead config. - Layer 2 (project doctrine): `group` should be `3` per gutenberg.md § Key Requirements. ACFML does not force this one, so the message is worded distinctly ("doctrine, not a plugin fact") rather than adding a new severity subsystem for a single rule. - Layer 3: `accordion` / `tab` / `message` (UI pseudo-fields, no translatable value) must be `0` or absent. Layer 4 (leaf value types) is explicitly out of scope and untouched. The four new buckets are disjoint from each other and from image/gallery (the existing 0.7.0 location-context check), so no field can ever be double-reported — verified by test and by construction (pure type-based bucketing). Reuses the existing sub_fields/layouts recursive walker shape rather than building a second one. Real-world validation (read-only, --wpml --strict, never --fix): - eprukaz2025: 19 -> 19 findings (all offending fields were already absent, caught by the pre-existing presence check; messages reworded to be more specific) - pm-a: 5 -> 17 findings (8 new repeater/flexible_content/group fields found wrongly set to 2; manually spot-checked all 8 against the real JSON — confirmed, no false positives) - oekoplan2024: 265 -> 265 findings (same story as eprukaz — all offending fields were already absent)
parisek
marked this pull request as ready for review
July 25, 2026 10:55
This was referenced Sep 4, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the scope of #30 (Layers 1-3 of the layered proposal; Layer 4 explicitly out of scope).
--wpmlcurrently only checks thatwpml_cf_preferencesis present, plus (since 0.7.0) thatimage/gallerycarry the right value for their location context. This extends the same idea to a type -> value check for three more field-type buckets:repeater/flexible_contentmust be3. ACFML forcibly overrides both types toWPML_COPY_ONCE_CUSTOM_FIELD(= 3) at runtime regardless of the configured value — authority:ACFML\Helper\Fields::WRAPPER_FIELDS(acfml/classes/Helper/Fields.php:10) andWPML_ACF_Field_Settings::field_should_be_set_to_copy_once()(acfml/classes/class-wpml-acf-field-settings.php:335-341). Any other configured value is provably dead configuration — the message cites the plugin as authority, not doctrine.groupshould be3pergutenberg.md§ Key Requirements ("3only on group containers whose nested leaves carry their own preference"). ACFML does not force this one — it's a project convention. This linter has no severity/warning-level concept anywhere insrc/(checked before implementing), and adding one for a single rule would be over-engineering, so this stays inside the same--wpmlfindings list — the softer certainty is conveyed entirely through message wording ("doctrine, not a plugin fact") instead of a new mechanism.accordion/tab/messageare ACF UI/layout pseudo-fields holding no translatable value — only0or absent is valid.Layer 4 (leaf value types — text, wysiwyg, image, link, select, url, …) is deliberately untouched. They keep only the pre-existing presence check; the 1-vs-2 split there is genuine author intent this linter doesn't second-guess.
No double-reporting
The four new buckets (
repeater/flexible_content,group,accordion/tab/message) are pairwise disjoint and disjoint fromimage/gallery(the types the existing 0.7.0 location-context check covers) — bucketing is purely by$field['type']. A field can never be flagged by two checks at once. Verified by a dedicated test (test_wpml_image_field_gets_single_finding_not_double_reported, asserts exactly one finding) plus by construction.Implementation
sub_fields/layoutswalker shape as the pre-existingwalkFieldsWpml()— no second walker.wpmlTypeValueFindings()+walkFieldsWpmlTypeValue()inAcfLinter, wired intolintFile()alongside the two existing--wpmlchecks.Tests (TDD)
24 new PHPUnit executions across 15 new test methods (3 of them data-provider-driven with 4 cases each): every Layer-1/2/3 wrong-value + correct-value case, leaf-type non-interference (text w/
1and2stay silent), no-double-report, and a 3-level nestedflexible_content -> group -> repeaterrecursion case.git diff(15 newtest_methods, 3 with 4-case data providers = 15 + 9 = 24 — matches exactly).Real-world validation (read-only,
--wpml --strict, never--fix)repeater/flexible_content/groupfields wrongly set to2)Manually spot-checked all 8 new pm-a findings by opening the real
acf.jsonfiles — every one genuinely hasrepeater/flexible_content/grouptype withwpml_cf_preferences: 2(not3). No false positives found.Per the issue's census (1769
acf.jsonfiles fleet-wide), ~837repeater/flexible_contentfields already carry a value the plugin discards at runtime. Existing projects will very likely surface brand-new findings under--wpml --strict— this is intentional, not a regression (documented in CHANGELOG.md).🤖 Generated with Claude Code