*/ final class ConfigPayload { /** * Posted form key => the option suffix that key is stored under. * * Every key the settings form submits and the contract carries. A key missing * here is silently unsyncable: {@see self::delta()} skips what it cannot map, * so the save publishes nothing, WordPress keeps an edit Actirise never heard * of, and the next inbound push overwrites it. `fastcmp-name` is the one * deliberate absence — the form never posts it, so `publisherName` reaches * Actirise through the seed alone. * * The admin form posts `privacyPolicy` and `headOffice` in camelCase while the * canonical options are `fastcmp-privacypolicy` and `fastcmp-headoffice`; both * spellings resolve to the same row only because MySQL compares `option_name` * case-insensitively. This map is what keeps the projection independent of * that accident. `customStyle` keeps its camelCase on both sides — the option * really is `fastcmp-customStyle`. * * @since 4.3.0 * @var array */ const POSTED_SUFFIXES = array( 'privacyPolicy' => 'privacypolicy', 'headOffice' => 'headoffice', 'targetedaudience' => 'targetedaudience', 'logo' => 'logo', 'customStyle' => 'customStyle', 'excludediabvendors' => 'excludediabvendors', 'excludedgooglevendors' => 'excludedgooglevendors', 'customsVendor' => 'customsvendor', ); /** * Option suffix => the DTO field it travels as, for the values that need no * reshaping. * * The delta's half of {@see self::EFFECTIVE_SCALARS}, which the seed uses; the * two are keyed differently — option suffixes here, effective-view keys there — * so they are spelled out separately rather than derived from one another. They * must cover the same DTO fields all the same: a field the seed can publish and * a save cannot is a value that diverges the moment the publisher edits it. * * @since 4.3.0 * @var array */ const SCALAR_FIELDS = array( 'privacypolicy' => 'policyUrl', 'headoffice' => 'countryCode', 'targetedaudience' => 'jurisdiction', 'logo' => 'publisherLogo', 'customStyle' => 'customCss', ); /** * Option suffix => the DTO field it travels as, for the two vendor-exclusion * lists. The DTO types both `list`, so every entry is cast: a digit * string is storable today and would fail validation. * * @since 4.3.0 * @var array */ const INT_LIST_FIELDS = array( 'excludediabvendors' => 'excludedIabVendors', 'excludedgooglevendors' => 'excludedGoogleVendors', ); /** * Option suffix => the DTO field it travels as, for the publisher's own vendor * list. * * @since 4.3.0 * @var array */ const VENDOR_LIST_FIELDS = array( 'customsvendor' => 'customVendors' ); /** * Posted key (also the option suffix) => the signal it sets in the DTO. * * The seven travel together under `googleConsentMode.defaults`, so they form * one unit as far as the delta is concerned. * * @since 4.3.0 * @var array */ const CONSENT_SIGNALS = array( 'googleAdStorage' => 'adStorage', 'googleAnalyticsStorage' => 'analyticsStorage', 'googlePersonalizationStorage' => 'personalizationStorage', 'googleFunctionalityStorage' => 'functionalityStorage', 'googleSecurityStorage' => 'securityStorage', 'googleAdPersonalization' => 'adPersonalization', 'googleAdUserData' => 'adUserData', ); /** * Stored signal key => the signal it sets in the DTO. * * The region-override code the publisher pastes spells the signals the way * Google does; the DTO spells them the way the rest of the payload does. * * @since 4.3.0 * @var array */ const CONSENT_STORED_SIGNALS = array( 'ad_storage' => 'adStorage', 'analytics_storage' => 'analyticsStorage', 'personalization_storage' => 'personalizationStorage', 'functionality_storage' => 'functionalityStorage', 'security_storage' => 'securityStorage', 'ad_personalization' => 'adPersonalization', 'ad_user_data' => 'adUserData', ); /** * DTO fields validated as a URL. * * A value that is not an absolute URL is left out of the payload rather than * sent and refused: the WordPress form accepts a relative path, the DTO does * not, and a rejected payload now costs the publisher their whole save. An * empty value is left out for the same reason it is ignored server-side — * clearing the policy link or the logo of a live consent banner is not * something a blank field should be able to do. * * @since 4.3.0 * @var string[] */ const URL_FIELDS = array( 'policyUrl', 'publisherLogo' ); /** * DTO fields an empty value is never sent for. * * Both are posted by a `