Background
The community-listings plugin registers a community custom post type with a communityMeta field group exposed through WPGraphQL. One of those fields — provider_listings — is a JSON string containing an array of senior care facility listings for each city page.
This data was originally imported from Contentful CMS. Contentful is no longer in use — the WordPress database is now the source of truth. However, provider_listings is currently a hidden programmatic meta field with no admin UI, making it impossible to edit content without running direct database commands via WP-CLI on the production ECS container.
Data Structure
Each city-level community post stores provider_listings as post meta (key: provider_listings). The value is a raw JSON string — an array of provider objects:
[
{
"slug": "palm-coast-fl-facilities",
"provider_name": "Ormond Manor",
"num_rooms": "20",
"room_string": "Private Rooms",
"care_type_string": "Memory Care",
"base_pricing_string": "$4,500/month",
"description": "Ormond Manor is a specialized memory care community...",
"resident_review": "Families are delighted...",
"award": "",
"reviews_string": "4.8 stars (42 reviews)",
"phone_number": "386-555-0100",
"address": "495 Sterthaus Dr., Ormond Beach, FL 32174",
"url": "https://www.memorycare.com/ormond-manor",
"url_display": "memorycare.com/ormond-manor"
}
]
In production, a city page can have up to 19+ providers (~34KB of JSON). This data is consumed by the headless Next.js frontend via WPGraphQL as communityMeta { providerListings }.
Critical: $wpdb->update() Required — NOT update_post_meta()
WordPress's update_metadata() calls wp_unslash() on the input value, which strips backslashes — corrupting the \" escape sequences inside the JSON string. Always use $wpdb->update() directly:
global $wpdb;
$wpdb->update(
$wpdb->postmeta,
[ 'meta_value' => $json_string ],
[ 'post_id' => $post_id, 'meta_key' => 'provider_listings' ],
[ '%s' ],
[ '%d', '%s' ]
);
Goal
Add a WordPress admin meta box to the community post type editor so content editors can view and update provider_listings without CLI access.
Acceptance Criteria
AC1 — Meta box registration
AC2 — View/Edit UI
AC3 — Save behavior
AC4 — Client-side JSON validation
AC5 — Security
AC6 — Individual provider fields (v2, optional)
Implementation Notes
- This change belongs in the
community-listings plugin, not in any theme
- The plugin already registers the
community CPT and the WPGraphQL field providerListings
- Meta key in
wp_postmeta: provider_listings (snake_case) → WPGraphQL field: providerListings (camelCase)
- Applies to all sites using this plugin (memorycare.com, etc.)
- Table prefix for memorycare.com:
wp_memorycare_
Related
- Jira WEB-1072 — Ormond Manor content update on memorycare.com required manual DB editing via WP-CLI + AWS ECS SSH because no admin UI exists for this field
- Downstream consumer:
memory-nextjs headless frontend — community city pages at /communities/[state]/[city]
Background
The
community-listingsplugin registers acommunitycustom post type with acommunityMetafield group exposed through WPGraphQL. One of those fields —provider_listings— is a JSON string containing an array of senior care facility listings for each city page.This data was originally imported from Contentful CMS. Contentful is no longer in use — the WordPress database is now the source of truth. However,
provider_listingsis currently a hidden programmatic meta field with no admin UI, making it impossible to edit content without running direct database commands via WP-CLI on the production ECS container.Data Structure
Each city-level
communitypost storesprovider_listingsas post meta (key:provider_listings). The value is a raw JSON string — an array of provider objects:[ { "slug": "palm-coast-fl-facilities", "provider_name": "Ormond Manor", "num_rooms": "20", "room_string": "Private Rooms", "care_type_string": "Memory Care", "base_pricing_string": "$4,500/month", "description": "Ormond Manor is a specialized memory care community...", "resident_review": "Families are delighted...", "award": "", "reviews_string": "4.8 stars (42 reviews)", "phone_number": "386-555-0100", "address": "495 Sterthaus Dr., Ormond Beach, FL 32174", "url": "https://www.memorycare.com/ormond-manor", "url_display": "memorycare.com/ormond-manor" } ]In production, a city page can have up to 19+ providers (~34KB of JSON). This data is consumed by the headless Next.js frontend via WPGraphQL as
communityMeta { providerListings }.Critical:
$wpdb->update()Required — NOTupdate_post_meta()WordPress's
update_metadata()callswp_unslash()on the input value, which strips backslashes — corrupting the\"escape sequences inside the JSON string. Always use$wpdb->update()directly:Goal
Add a WordPress admin meta box to the
communitypost type editor so content editors can view and updateprovider_listingswithout CLI access.Acceptance Criteria
AC1 — Meta box registration
communitypost type edit screenlisting_typemeta equals'city'). State-level posts do not show it.normalcontext athighpriorityAC2 — View/Edit UI
<textarea>pre-populated with the current JSON value, formatted withJSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE"34,938 bytes")"19 providers")AC3 — Save behavior
save_post, the submitted textarea value is validated as JSON viajson_decode()$wpdb->update()directly to preserve\"escape sequencesAC4 — Client-side JSON validation
AC5 — Security
edit_postscan savewp_create_nonce()and verified withwp_verify_nonce()AC6 — Individual provider fields (v2, optional)
provider_name,description,resident_review,address, etc.)Implementation Notes
community-listingsplugin, not in any themecommunityCPT and the WPGraphQL fieldproviderListingswp_postmeta:provider_listings(snake_case) → WPGraphQL field:providerListings(camelCase)wp_memorycare_Related
memory-nextjsheadless frontend — community city pages at/communities/[state]/[city]