Skip to content

test: ACF parity with @contentrain/wp-import (shared fixture) - #34

Merged
ABB65 merged 26 commits into
mainfrom
test/acf-parity
Sep 25, 2026
Merged

ABB65 merged 26 commits into
mainfrom
test/acf-parity

Conversation

@ABB65

@ABB65 ABB65 commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

The Bridge side of the ACF parity fixture from @contentrain/wp-import (ai #295, t7).

  • Fixture: tests/fixtures/acf-parity.json is copied unchanged. tests/fixtures/acf-parity.pin records the source commit. It is pinned to the PR head for now and will be re-pinned to the merged main commit.
  • Test: tests/acf-parity.php runs from tests/integration.php. It passes every case through Acf::field(..., inline: true), as a collection entry writes it. The fixture's layouts object is converted to ACF's list form. It compares:
    • the definition: type, options, fields (order-free), items and required
    • the stored value: canonical JSON, compared strictly, because true == 1 is true in PHP
    • dropped: the count of acf-choice-not-in-options warnings

Draft.

Status: CI is green. All 38 cases of ai #295 @7f33809 pass, including date-times in the case's site zone (Istanbul, and Berlin in summer and winter) and a link with an empty target.

Bridge change found by the fixture: a select whose stored value is outside its choices now still declares its field, with no value. The callers (Models::post, the Options Page) write no key for a field with no content. Before, the field was not declared at all, which differed from wp-import.

acf-parity.pin will be re-pinned to the merged main commit of ai #295.

Reviewer: t6 · coordination: t7

A page_link stores the linked post's ID, and Bridge modelled it as a
URL, so the validator rejected the entry and the whole export stopped
("Invalid value or missing relation: wp-project.acf_landing_page").
The ID now casts to the post's permalink. A draft, private,
password-protected or missing target has no public address: its value
is left out with an acf-page-link-target-not-public warning, and the
field is never required, so the field keeps one type across entries
(a fallback would make the model inconsistent and fail the export
again). A multiple page_link takes the structured fallback.
SCALARS mapped link to url, so a link sub-field in a group, repeater or
flexible_content row kept only its URL and silently dropped the label
and target ("Contact"). A link is no longer a scalar: a row holding one
falls back to structured values whole, with the existing
acf-shape-not-modelled warning, so nothing is lost. A top-level link is
still modelled with its label and target; an empty one exports nothing.
Modelling a link as an object is B3.
Policy::sensitive() is built for unknown post meta and matches any
name containing email, ip or user_agent, so a public ACF field such as
contact_email was dropped as sensitive-field. ACF fields and sub-fields
now use Policy::secret_name(): the password type and credential names
(password, secret, token, credential, api key, private key,
authorization, cookie, session) never leave; an email field the owner
built is exported. Unknown meta keeps the broad rule, and values are
still scanned for credential patterns. Planted ACF secrets are added to
the secret-scan canaries.
…port

Review N1 from t6 on #32: the unbounded pattern dropped content fields
such as passage, session_title and cookie_recipe. secret_name() now
splits camelCase and hyphens and matches whole words — the rule
@contentrain/wp-import's ACF reader uses (ai #289) — so user_pass,
apiKey and access_token stay secret and passage stays content.
Review N from t6 on #30: an attachment's status is inherit, and its
permalink carries the parent's slug, so a file attached to a draft
would leak the draft's address. The parent must be published and
unprotected too.
… as object/array fields

In a collection or singleton entry an ACF group is an object, a
repeater an array of objects, flexible content an array of objects
with a required layout select (every layout in the schema, sorted)
over the union of the layouts' fields, a link {url,title,target}, a
google_map {address,lat,lng,zoom}, a checkbox or multi-select an array
of select. Definitions come from the field schema alone, so every
entry agrees; containers nest at most two deep, and anything with no
value type (a reference, deeper nesting) takes the structured fallback
whole. A document's frontmatter has no nested values, so posts keep
the collection models. A stored choice the field no longer offers is
left out with acf-choice-not-in-options instead of failing the export.
The validator checks object, array and decimal values recursively.
Same table as @contentrain/wp-import's ACF reader (ai #289).
…ir values

The schema of a page's and an Options Page's ACF fields was still
cleaned with the broad meta rule, so contact_email lost its schema and
fell back to structured values (the acceptance check caught it).
# Conflicts:
#	includes/class-contentrain-bridge-acf.php
#	tests/integration.php
…ed fixture through Acf::field

tests/fixtures/acf-parity.json is copied unchanged from Contentrain/ai
(the commit in acf-parity.pin); tests/acf-parity.php runs each case as a
collection entry writes it and compares the definition (type, options,
fields order-free, items, required), the stored value (canonical JSON,
strictly) and how many values were dropped outside the choices.
…d a link with an empty target

The fixture now states the site's time zone (top level, per case); the
test sets timezone_string to it for the case, so a date-time is written
with that zone's offset at that moment, summer time included, and puts
the site's own zone back afterwards.
Parity with wp-import (shared fixture): the field is the schema's, so
it is declared even when this entry's value is left out as outside the
choices; the entry just has no value for it. Callers write no key for a
field with no content.
@ABB65
ABB65 marked this pull request as ready for review September 25, 2026 16:55
@ABB65

ABB65 commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

t6 QA — Bridge #34 (40a7060): ONAY, re-pin koşuluyla

  • Fixture: ai #295 birleşti (01c0065). Buradaki acf-parity.json main'deki dosyayla bayt bayt aynı. Birleşmeden önce yalnız acf-parity.pin satırının 7f33809 → 01c0065b29054a71cdd05551f763dd4274c3880e olarak güncellenmesi gerekiyor. İçerik değişmediği için ayrıca bakmam gerekmiyor.
  • Davranış değişikliği: Seçenek dışı bir select değeri artık alanı tanımlıyor, ama değer yazmıyor. Acf::field'in iki çağıranı da (Models::post, options_page) null içerikte anahtar yazmıyor; mağazaya null girmiyor. Sızıntı açısından nötr: değer zaten düşüyordu, şimdi yalnız şema tamamlanıyor.
  • Test: 38 vaka, saat dilimli date-time vakaları, true == 1 tuzağına karşı canonical JSON ile katı karşılaştırma. CI yeşil (PHP 7.4 ve 8.3, acceptance).

@ABB65
ABB65 merged commit 7d8dbea into main Sep 25, 2026
9 checks passed
@ABB65
ABB65 deleted the test/acf-parity branch September 25, 2026 21:52
@ABB65 ABB65 mentioned this pull request Sep 27, 2026
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