agentsclimarketplace

Wcm data model subscriptions link

Skill Lonsdale201/wp-agent-skills/woocommerce/wcm-data-model-subscriptions-link

A community-maintained collection of agent skills for WordPress plugin and theme development.

Install
npx -y skills add Lonsdale201/wp-agent-skills --skill wcm-data-model-subscriptions-link

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

WooCommerce Memberships storage and relationship map for membership plan CPTs, user membership CPTs, post statuses, plan/user membership meta keys, rule storage, profile-field storage, order grant meta, and WooCommerce Subscriptions-linked memberships. Use when code reads or writes wc_membership_plan, wc_user_membership, wcm-* statuses, wc_memberships_rules, _subscription_id, _has_installment_plan, _free_trial_end_date, membership plan access meta, user membership dates, product/order grant meta, or when an agent needs exact Memberships CPT/meta names and the Memberships-Subscriptions relation.

SKILL.md

13.3 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it

WooCommerce Memberships: data model and Subscriptions link

Use this when an integration needs exact storage names. Prefer Memberships public APIs and objects for writes; use these keys for audits, migrations, import/export mapping, and low-level debugging.

Core storage

EntityStorageName/keyNotes
Membership planCPTwc_membership_planRegistered by WC_Memberships_Post_Types. Not public, UI under WooCommerce when possible.
User membershipCPTwc_user_membershipOne post per user-plan membership. Not public.
Plan relationWP post fieldwc_user_membership.post_parentThis is the plan ID. Do not invent _member_plan_id; the installed plugin uses post_parent.
Member relationWP post fieldwc_user_membership.post_authorThis is the member/user ID.
SubscriptionWC order typeshop_subscriptionFrom WooCommerce Subscriptions; use wcs_get_subscription().
Membership rulesOptionwc_memberships_rulesStores serialized rule arrays for all plans. Rules are not CPTs.
Profile field definitionsOptionwc_memberships_profile_fieldsDefinition data keyed by profile field slug.
Profile field valuesUser meta_wc_memberships_profile_field_{slug}Stored by Profile_Field\User_Meta.
Order grant markerWC order meta_wc_memberships_access_grantedArray keyed by user membership ID, with already_granted, granting_order_status, and related details.

Membership statuses

WP post statuses use the wcm- prefix. Object methods usually accept/return unprefixed slugs.

WP statusObject statusMeaning
wcm-activeactiveActive access.
wcm-delayeddelayedMembership exists but access starts later.
wcm-complimentarycomplimentaryAdmin/complimentary access.
wcm-free_trialfree_trialAdded by the Subscriptions integration when a linked subscription is in trial.
wcm-pausedpausedPaused membership.
wcm-expiredexpiredExpired membership.
wcm-cancelledcancelledCancelled membership.

Use wc_memberships_get_user_membership_statuses() for the installed status catalog and wc_memberships()->get_user_memberships_instance()->get_active_access_membership_statuses() for statuses that grant access.

Membership plan meta

These keys are stored on wc_membership_plan posts and exposed by WC_Memberships_Membership_Plan::get_meta_keys().

Meta keyPurpose
_access_methodmanual-only, signup, or purchase access method.
_access_lengthAccess length value, e.g. unlimited, specific, fixed, or an amount/period value depending on method.
_access_start_dateFixed access start datetime.
_access_end_dateFixed access end datetime.
_product_idsProduct or variation IDs that grant access.
_members_area_sectionsEnabled members-area sections.
_email_contentPlan-specific email content settings.

Use plan methods such as get_access_method(), set_access_method(), get_product_ids(), set_product_ids(), get_access_start_date(), and get_access_end_date() rather than direct meta writes.

User membership meta

These keys are stored on wc_user_membership posts and exposed by WC_Memberships_User_Membership::get_meta_keys().

Meta keyPurpose
_start_dateMembership start datetime.
_end_dateMembership end datetime. Empty/unset can mean unlimited.
_cancelled_dateCancellation datetime.
_paused_dateCurrent pause start datetime.
_paused_intervalsHistorical paused intervals.
_product_idProduct or variation ID that granted access.
_order_idOrder ID that granted access.
_previous_ownersPrevious owner user IDs after transfers.
_renewal_login_tokenAuto-login token used for renewal flows.
_lockedOperation lock for race-sensitive flows.

Use wc_memberships_create_user_membership(), wc_memberships_get_user_membership(), and WC_Memberships_User_Membership methods for writes and lifecycle side effects.

Rule storage

Rules are stored in the wc_memberships_rules option, not as posts. Rule type values:

Rule typePurposeImportant fields
content_restrictionRestricts posts, pages, CPTs, or terms.content_type, content_type_name, object_ids, access_schedule, access_schedule_exclude_trial.
product_restrictionRestricts product viewing or purchase.Same fields plus access_type (view or purchase).
purchasing_discountApplies member discounts.discount_type, discount_amount, active.

Common rule fields are id, membership_plan_id, active, rule_type, content_type, content_type_name, object_ids, discount_type, discount_amount, access_type, access_schedule, access_schedule_exclude_trial, and meta_data.

Use wc_memberships()->get_rules_instance()->get_rules(), get_plan_rules(), add_rules(), update_rules(), or delete_rules() instead of editing the option directly.

Memberships 1.29.0 adds a safer admin/editor layer for per-post content restriction rules. PostRestrictionRulesSerializer reads the same wc_memberships_rules store and returns both direct and inherited rules, while SetPostRules replaces only direct post-specific content_restriction rows for one post. If you consume the GET result, filter to rows where editable === true before sending an update; inherited rules must be edited at the plan/post-type/taxonomy source.

Memberships to Subscriptions relation

WooCommerce Memberships links to WooCommerce Subscriptions by adding extra meta to the wc_user_membership post. The subscription itself is still a WCS shop_subscription.

User membership metaPurpose
_subscription_idLinked shop_subscription ID. This is the primary relation key from membership to subscription.
_has_installment_planFlag/value used when the linked subscription is treated as an installment plan. The code stores the subscription ID when it auto-detects the flag.
_free_trial_end_dateTrial end datetime mirrored from the linked subscription trial.

Public helpers:

$integration = wc_memberships()->get_integrations_instance()->get_subscriptions_instance();
$subscription = $integration ? $integration->get_subscription_from_membership( $user_membership ) : null;
$memberships = $integration ? $integration->get_memberships_from_subscription( $subscription ) : array();

$is_linked = wc_memberships_is_user_membership_linked_to_subscription( $user_membership );

Do not assume a reverse meta key on the subscription. Reverse lookup queries wc_user_membership posts with _subscription_id = {subscription_id}.

Subscription-linked lifecycle

When Subscriptions is active, Memberships may return WC_Memberships_Integration_Subscriptions_User_Membership for linked memberships.

Important behavior:

  • Linking calls WC_Memberships_Integration_Subscriptions_User_Membership::set_subscription_id() and fires wc_memberships_user_membership_linked_to_subscription.
  • Unlinking deletes _subscription_id and fires wc_memberships_user_membership_unlinked_from_subscription.
  • Subscription trial dates can set membership status to free_trial and write _free_trial_end_date.
  • Subscription date/status changes can update linked membership dates/statuses.
  • If a plan is granted by subscription products, Memberships checks whether the subscription product grants the plan and may keep access tied to subscription activity.
  • Installment plan behavior differs: completion can unlink the subscription while keeping membership access according to the plan rules.

Gifting and Memberships

WooCommerce Subscriptions Gifting changes who receives membership access when the gifted subscription product grants a Memberships plan.

Storage bridge:

  • Gifted subscription stores recipient user on subscription meta _recipient_user after recipient account resolution.
  • Parent order item stores wcsg_recipient = wcsg_recipient_id_{user_id}.
  • Memberships grant filtering uses wcsg_recipient to grant access to recipient users instead of the purchaser for gifted items.
  • The membership still stores the linked subscription in _subscription_id.

If an order has the same membership-granting product for several recipients, do not pick the first subscription in the order. Use the WCSG/Memberships integration logic or query recipient subscriptions before assigning _subscription_id.

REST and directory data boundaries

Memberships REST records are API projections, not storage contracts. The v4 directory endpoint deliberately returns less than the full user membership record:

  • It requires a page_id containing a Memberships Directory block and optionally a matching block_instance_id.
  • It validates the viewer's access to that page/block context.
  • It whitelists response keys to id, customer_data, plan_name, profile_fields, and meta_data.
  • It blanks meta_data, filters profile_fields to the block's configured slugs, and removes REST links.

Do not use /wc/v4/memberships/members/directory as an admin export or integration source. Use the admin-gated Memberships REST endpoints, public PHP APIs, or the Abilities API for privileged automation.

Safe query patterns

// Memberships for a subscription.
$memberships = get_posts( array(
    'post_type'      => 'wc_user_membership',
    'post_status'    => wc_memberships_get_user_membership_statuses( false ),
    'fields'         => 'ids',
    'posts_per_page' => -1,
    'meta_query'     => array(
        array(
            'key'   => '_subscription_id',
            'value' => $subscription_id,
        ),
    ),
) );

// Prefer API for normal code.
$user_membership = wc_memberships_get_user_membership( $user_id, $plan_id );

For "grant access from previous purchase" logic, do not query shop_order posts directly. WooCommerce order storage may be HPOS, while Memberships still stores plans/user memberships as CPTs. Use Memberships grant/order APIs and WooCommerce order APIs so previous-purchase checks work in both CPT and HPOS order storage.

Common mistakes

// WRONG: this key is not the plan relation in the installed plugin.
$plan_id = get_post_meta( $membership_id, '_member_plan_id', true );

// RIGHT: use the object or post_parent.
$membership = wc_memberships_get_user_membership( $membership_id );
$plan_id = $membership ? $membership->get_plan_id() : 0;

// WRONG: raw post status write misses Memberships side effects.
wp_update_post( array( 'ID' => $membership_id, 'post_status' => 'wcm-active' ) );

// RIGHT: use object status API with unprefixed status.
$membership->update_status( 'active' );

Cross-references

  • Use wcm-membership-hooks for lifecycle hooks and REST/webhook extension points.
  • Use wcm-access-discounts for access checks, restrictions, drip timing, and member discounts.
  • Use wcm-abilities-api for Memberships 1.28+ WP Abilities API automation.
  • Use wcs-data-model-switching-gifting for Subscriptions order type, subscription meta, switch data, and gifting data.

References

  • Verified source paths:
    • wp-content/plugins/woocommerce-memberships/src/class-wc-memberships-post-types.php
    • wp-content/plugins/woocommerce-memberships/src/class-wc-memberships-membership-plan.php
    • wp-content/plugins/woocommerce-memberships/src/class-wc-memberships-user-membership.php
    • wp-content/plugins/woocommerce-memberships/src/class-wc-memberships-rules.php
    • wp-content/plugins/woocommerce-memberships/src/functions/wc-memberships-functions-orders.php
    • wp-content/plugins/woocommerce-memberships/src/Data_Stores/Profile_Field/User_Meta.php
    • wp-content/plugins/woocommerce-memberships/src/Data_Stores/Profile_Field_Definition/Option.php
    • wp-content/plugins/woocommerce-memberships/src/API/Controller/User_Memberships.php
    • wp-content/plugins/woocommerce-memberships/src/Helpers/Directory_Block_Validator.php
    • wp-content/plugins/woocommerce-memberships/src/Posts/Actions/SetPostRules.php
    • wp-content/plugins/woocommerce-memberships/src/Posts/Adapters/JsonSerializers/PostRestrictionRulesSerializer.php
    • wp-content/plugins/woocommerce-memberships/src/integrations/subscriptions/class-wc-memberships-integration-subscriptions-user-membership.php
    • wp-content/plugins/woocommerce-memberships/src/integrations/subscriptions/class-wc-memberships-integration-subscriptions.php

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most data backend skills give in ~2.8k tokens

Counted across 229 of the 229 authors here whose files we hold, read 2026-08-07

  • Separate business logic into service layersin 22 of 229, across 15 files
  • Retry failures with exponential backoffin 21 of 229, across 14 files
  • Select only needed database columnsin 20 of 229, across 13 files
  • Abstract data access into repository classesin 19 of 229, across 12 files
  • Use centralized error handlersin 17 of 229, across 10 files
  • Use AsNoTracking for read-only queriesin 16 of 229, across 4 files
  • Use async/await for all I/O operationsin 16 of 229, across 5 files
  • Implement structured loggingin 15 of 229, across 4 files
  • Use dependency injection for all servicesin 14 of 229, across 2 files
  • Use resource-based URLs for REST APIsin 13 of 229, across 7 files
  • Invalidate cache after data changesin 13 of 229, across 9 files
  • Use a dependency injection containerin 12 of 229, across 4 files

Said here and by no other author read

  • prefer public APIs and objects for writes
  • use plan methods for meta access and updates
  • use membership methods for writes and lifecycle
  • use rule API methods instead of editing option directly
  • filter inherited rules before updating post rules
  • use integration helpers for subscription relations

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.