Memory Wiki

Untitled Session

2026-06-01 03:01 UTC · 89 messages · cli

You2026-06-01 03:04 UTC
Find where PMPro signup/checkout form fields are defined — look at the PMPro plugin source code to identify which files define, render, and process the form fields on the membership signup/checkout page.
Donna2026-06-01 03:04 UTC
I'll start by exploring the PMPro plugin structure and running the initial checks you asked for.
Tool2026-06-01 03:04 UTC
{"output": "CHANGELOG.txt\nadminpages\nblocks\nclasses\ncss\nimages\nincludes\njs\nlanguages\nlicense.txt\nlogs\npages\npaid-memberships-pro-banner.png\npaid-memberships-pro.php\npreheaders\nreadme.txt\nservices\nshortcodes\nuninstall.php", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "", "exit_code": 1, "error": null, "exit_code_meaning": "No matches found (not an error)"}
Tool2026-06-01 03:04 UTC
{"output": "", "exit_code": 1, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "Error: YIKES! It looks like you're running this as root. You probably meant to run this as the user that your WordPress installation exists under.\n\nIf you REALLY mean to run this as root, we won't stop you, but just bear in mind that any code on this site will then have full control of...
Tool2026-06-01 03:04 UTC
{"output": "Error: YIKES! It looks like you're running this as root. You probably meant to run this as the user that your WordPress installation exists under.\n\nIf you REALLY mean to run this as root, we won't stop you, but just bear in mind that any code on this site will then have full control of...
Tool2026-06-01 03:04 UTC
{"output": "", "exit_code": 1, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "paid-memberships-pro\tactive\tnone\t3.7.4\t\toff\npmpro-signup-shortcode\tactive\tnone\t1.2\t\toff\npmpro-update-manager\tactive\tnone\t1.0.1\t\toff", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "Notice: Function _load_textdomain_just_in_time was called <strong>incorrectly</strong>. Translation loading for the <code>buddypress-share</code> domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be lo...
Donna2026-06-01 03:04 UTC
Good — `pmpro-signup-shortcode` is active! Let me now explore both the PMPro plugin and the shortcode plugin.
Tool2026-06-01 03:04 UTC
{"output": "LICENSE.md\nblocks\nlanguages\npackage-lock.json\npmpro-signup-shortcode.php\nreadme.txt", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "checkout_button.php\nmembership.php\npmpro_account.php\npmpro_login.php\npmpro_member.php\npmpro_member_profile_edit.php", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "account.php\nbilling.php\ncancel.php\ncheckout.php\nconfirmation.php\ninvoice.php\nlevels.php\nlogin.php\nmember_profile_edit.php", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "abandoned-signups.php\naddons.php\nadmin.php\nadminpages.php\navatars.php\nblocks.php\ncapabilities.php\ncheckout.php\ncleanup.php\ncloudflare-turnstile.php\ncompatibility\ncompatibility.php\ncontent.php\ncountries.php\ncrons.php\ncurrencies.php\ndeprecated.php\nemail-logging.php\nemail-...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"content": "", "total_lines": 0, "file_size": 0, "truncated": false, "is_binary": false, "is_image": false, "error": "File not found: /var/www/html/wp-content/plugins/pmpro-signup-shortcode/pmpro-signup-shortcode.php"}
Tool2026-06-01 03:04 UTC
{"content": "", "total_lines": 0, "file_size": 0, "truncated": false, "is_binary": false, "is_image": false, "error": "File not found: /var/www/html/wp-content/plugins/paid-memberships-pro/includes/fields.php"}
Tool2026-06-01 03:04 UTC
{"content": "", "total_lines": 0, "file_size": 0, "truncated": false, "is_binary": false, "is_image": false, "error": "File not found: /var/www/html/wp-content/plugins/paid-memberships-pro/pages/checkout.php"} [Tool loop warning: same_tool_failure_warning; count=3; read_file has failed 3 times this...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "drwxr-xr-x 4 www-data www-data 4096 Jun 1 02:11 pmpro-signup-shortcode\ndrwxr-xr-x 5 www-data www-data 4096 May 31 00:11 pmpro-update-manager", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "/usr/local/bin/wp\ntotal 676\ndrwxr-xr-x 4 www-data www-data 4096 Jun 1 02:11 .\ndrwxr-xr-x 9 www-data www-data 4096 Jun 1 02:11 ..\n-rw-r--r-- 1 www-data www-data 35149 Jun 1 02:11 LICENSE.md\ndrwxr-xr-x 3 www-data www-data 4096 Jun 1 02:11 blocks\ndrwxr-xr-x 2 www-data www-d...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "drwxr-xr-x 15 www-data www-data 4096 May 31 00:53 paid-memberships-pro", "exit_code": 0, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "-rw-r--r-- 1 www-data www-data 40939 May 31 00:53 /var/www/html/wp-content/plugins/paid-memberships-pro/includes/fields.php\n-rw-r--r-- 1 www-data www-data 42261 May 31 00:53 /var/www/html/wp-content/plugins/paid-memberships-pro/pages/checkout.php\ntotal 60\ndrwxr-xr-x 2 www-data www-da...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"content": "", "total_lines": 0, "file_size": 0, "truncated": false, "is_binary": false, "is_image": false, "error": "File not found: /root/../var/www/html/wp-content/plugins/paid-memberships-pro/includes/fields.php"} [Tool loop warning: same_tool_failure_warning; count=4; read_file has failed 4 t...
Donna2026-06-01 03:04 UTC
The files are inside a Docker container — `read_file` can't reach them directly. I'll use `docker exec` to read the contents.
Tool2026-06-01 03:04 UTC
{"output": "<?php \n/**\n * Check if a variable is a PMPro_Field.\n * Also checks for PMProRH_Field.\n */\nfunction pmpro_is_field( $var ) {\n if ( is_a( $var, 'PMPro_Field' ) || is_a( $var, 'PMProRH_Field' ) ) {\n return true;\n } else {\n return false;\n }\n}\n\n/**\n * Add ...
Tool2026-06-01 03:04 UTC
{"output": "<?php\r\n/**\r\n * Plugin Name: Paid Memberships Pro - Signup Shortcode & Block\r\n * Plugin URI: https://www.paidmembershipspro.com/add-ons/pmpro-signup-shortcode/\r\n * Description: Embed signup forms anywhere on your WordPress site. Designed to simplify membership registration, especi...
Donna2026-06-01 03:04 UTC
Now let me dig deeper into the core files.
Tool2026-06-01 03:04 UTC
{"output": "1243", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "591", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "645 /var/www/html/wp-content/plugins/paid-memberships-pro/pages/checkout.php\n 733 /var/www/html/wp-content/plugins/paid-memberships-pro/preheaders/checkout.php\n 346 /var/www/html/wp-content/plugins/paid-memberships-pro/includes/checkout.php\n 1724 total", "exit_code": 0, "error": nul...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "<?php\n/**\n * Template: Checkout\n * Version: 3.6.3\n *\n * See documentation for how to override the PMPro templates.\n * @link https://www.paidmembershipspro.com/documentation/templates/\n *\n * @version 3.6.3\n *\n * @author Paid Memberships Pro\n */\n\nglobal $gateway, $pmpro_review...
Tool2026-06-01 03:04 UTC
{"output": "<?php\r\nglobal $post, $gateway, $wpdb, $besecure, $discount_code, $discount_code_id, $pmpro_level, $pmpro_msg, $pmpro_msgt, $pmpro_review, $skip_account_fields, $pmpro_paypal_token, $pmpro_show_discount_code, $pmpro_error_fields, $pmpro_required_billing_fields, $pmpro_required_user_fiel...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "class-deny-network-activation.php\nclass-pmpro-action-scheduler.php\nclass-pmpro-addons.php\nclass-pmpro-admin-activity-email.php\nclass-pmpro-discount-code-list-table.php\nclass-pmpro-discount-codes.php\nclass-pmpro-exports.php\nclass-pmpro-field-group.php\nclass-pmpro-field.php\nclass-...
Tool2026-06-01 03:04 UTC
{"output": ")\n\t\t);\n\t}\n}\nadd_action( 'pmpro_checkout_boxes', 'pmpro_checkout_boxes_fields' );\n\n//after_pricing_fields\nfunction pmpro_checkout_after_pricing_fields() {\n\tpmpro_display_fields_in_group( 'after_pricing_fields', 'checkout' );\n}\nadd_action( 'pmpro_checkout_after_pricing_fields...
Tool2026-06-01 03:04 UTC
{"output": "// Build the list of levels for multi-level mode and identify which ones the current user already holds.\r\n\t$pmpro_levels = array();\r\n\t$held_level_ids = array();\r\n\tif ( $levels !== null ) {\r\n\t\t$all_levels = pmpro_sort_levels_by_order( pmpro_getAllLevels( false, true ) );\r\n\...
Donna2026-06-01 03:04 UTC
Let me now examine the field classes and the membership shortcode that loads the checkout page.
Tool2026-06-01 03:04 UTC
{"output": "557 /var/www/html/wp-content/plugins/paid-memberships-pro/classes/class-pmpro-field-group.php\n 1960 /var/www/html/wp-content/plugins/paid-memberships-pro/classes/class-pmpro-field.php\n 2517 total", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "<?php\n/**\n * Note: One goal of this class is to abstract all uses of the global $pmpro_field_groups and $pmpro_user_fields arrays.\n * In the next major release, we will likely remove these globals and store field groups and fields in this class\n * instead to prevent confl...
Tool2026-06-01 03:04 UTC
{"output": "<?php\n/*\n\tShortcode to hide/show content based on membership level\n*/\nfunction pmpro_shortcode_membership($atts, $content=null, $code=\"\")\n{\n\t// $atts ::= array of attributes\n\t// $content ::= text within enclosing form of shortcode element\n\t// $code ::= the shortcode f...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "102:\tpublic static function get_all() {\n120:\tpublic static function get( $name ) {\n194:\tpublic function add_field( $field ) {\n253:\tpublic function get_fields_to_display( $args = array() ) {\n322:\tpublic function display( $args = array() ) {\n533:\tpublic function save_fields( $ar...
Tool2026-06-01 03:04 UTC
{"output": "661:\tfunction save_field_for_user( int $user_id ) {\n864:\tfunction display( $value = NULL ) {\n1478:\tfunction displayAtCheckout()\n1553:\tfunction displayInProfile($user_id, $edit = NULL)\n1594:\tfunction displayValue( $value, $echo = true ) {\n1898:\tfunction was_filled_if_needed() {...
Tool2026-06-01 03:04 UTC
{"output": "", "exit_code": 0, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "/var/www/html/wp-content/plugins/paid-memberships-pro/includes/init.php:88:\t\t\t\tadd_shortcode(\"pmpro_\" . $pmpro_page_name, \"pmpro_pages_shortcode\");\n/var/www/html/wp-content/plugins/paid-memberships-pro/shortcodes/pmpro_account.php:470:add_shortcode('pmpro_account', 'pmpro_shortc...
Tool2026-06-01 03:04 UTC
{"output": "65:\tdo_action( 'pmpro_checkout_before_form', $pmpro_level );\n186:\t\t\t\t\t\tdo_action( 'pmpro_checkout_after_level_cost', $pmpro_level );\n221:\t\t\tdo_action( 'pmpro_checkout_after_pricing_fields', $pmpro_level );\n259:\t\t\t\t\t\t\t\t\t<?php do_action( 'pmpro_checkout_after_username...
Tool2026-06-01 03:04 UTC
{"output": "", "exit_code": 1, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "82:\t\t\t\tfunction pmpro_pages_shortcode($atts, $content=null, $code=\"\")", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "add_shortcode(\"pmpro_\" . $pmpro_page_name, \"pmpro_pages_shortcode\");\n\t\t\t\tbreak;\t//only the first page found gets a shortcode replacement\n\t\t\t}\n\t\t\telseif(!empty($pmpro_page_id) && is_page($pmpro_page_id))\n\t\t\t{\n\t\t\t\t//add class to body\n\t\t\t\t$pmpro_body_classes[...
Tool2026-06-01 03:04 UTC
{"output": "public static function get_all() {\n\t\tglobal $pmpro_field_groups;\n\n\t\tif ( empty( $pmpro_field_groups ) ) {\n\t\t\t$pmpro_field_groups = array();\n\t\t}\n\n\t\treturn $pmpro_field_groups;\n\t}\n\n\t/**\n\t * Get an added field group by name.\n\t *\n\t * @since 3.4\n\t *\n\t * @param...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "function pmpro_pages_shortcode($atts, $content=null, $code=\"\")\n\t\t\t\t{\n\t\t\t\t\tglobal $pmpro_page_name;\n\t\t\t\t\t$temp_content = pmpro_loadTemplate($pmpro_page_name, 'local', 'pages');\n\t\t\t\t\treturn apply_filters(\"pmpro_pages_shortcode_\" . $pmpro_page_name, $temp_content)...
Tool2026-06-01 03:04 UTC
{"output": "public function display( $args = array() ) {\n\t\t$default_args = array(\n\t\t\t'markup' => 'card', // The markup to use for the field group. Can be 'card', 'div' or 'table'.\n\t\t\t'scope' => 'profile', // The scope of the fields to show. Can be 'profile' or 'checkout'.\n\t\t\t'show_gro...
Donna2026-06-01 03:04 UTC
Now let me check the checkout block and the admin settings for user fields, then check for the pmpro_pages option.
Tool2026-06-01 03:04 UTC
{"output": "build\nsrc", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "field-settings.php\ngroup-settings.php", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "864:\tfunction display( $value = NULL ) {\n1478:\tfunction displayAtCheckout()", "exit_code": 0, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "<?php\n#[AllowDynamicProperties]\nclass PMPro_Field {\n\t/**\n\t * The name of the field.\n\t *\n\t * This is the name attribute of the input field and may be automatically prefixed if needed.\n\t *\n\t * @since 2.9\n\t *\n\t * @var string\n\t */\n\tprivate $name = '';\n\n\t/**\n\t * The...
Tool2026-06-01 03:04 UTC
{"output": "function displayAtCheckout()\n\t{\n\t\t_deprecated_function( __METHOD__, '3.4', 'PMPro_Field_Group::display()' );\n\t\tglobal $current_user;\n\n\t\tif( null !== $this->get_value_from_request() ) {\n\t\t\t$value = $this->get_value_from_request();\n\t\t} elseif(!empty($current_user->ID) &&...
Donna2026-06-01 03:04 UTC
Let me check for the checkout block and also look at the pmpro_pages option more carefully to see what page IDs are set.
Tool2026-06-01 03:04 UTC
{"output": "account-invoices-section\naccount-links-section\naccount-membership-section\naccount-page\naccount-profile-section\nbilling-page\ncancel-page\ncheckout-button\ncheckout-page\ncomponent-content-visibility\nconfirmation-page\ninvoice-page\nlevels-page\nlogin\nmember-profile-edit\nmembershi...
Tool2026-06-01 03:04 UTC
{"output": "build", "exit_code": 0, "error": null}
Tool2026-06-01 03:04 UTC
{"output": "Notice: Function _load_textdomain_just_in_time was called <strong>incorrectly</strong>. Translation loading for the <code>buddypress-share</code> domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be lo...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "option_name\toption_value", "exit_code": 0, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "active_plugins\ta:7:{i:0;s:50:\"buddypress-activity-share-pro/buddypress-share.php\";i:1;s:45:\"buddypress-reactions/buddypress-reactions.php\";i:2;s:24:\"buddypress/bp-loader.php\";i:3;s:45:\"paid-memberships-pro/paid-memberships-pro.php\";i:4;s:49:\"pmpro-signup-shortcode/pmpro-signup-...
Donna2026-06-01 03:04 UTC
Let me check how the pmpro_signup shortcode handles form submission processing.
Tool2026-06-01 03:04 UTC
{"output": "310:\tdo_action( 'pmpro_checkout_preheader', $pmpro_level );\r\n368:\t\t\t\t\t\t\t<input type=\"hidden\" id=\"pmpro_signup_shortcode\" name=\"pmpro_signup_shortcode\" value=\"1\" />\r\n524:\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"submit-checkout\" value=\"1\" />\r\n525:\t\t\t\t\t\...
Tool2026-06-01 03:04 UTC
{"output": "/var/www/html/wp-content/plugins/paid-memberships-pro/includes/functions.php:4050: function pmpro_was_checkout_form_submitted() {", "exit_code": 0, "error": null}
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "function pmpro_was_checkout_form_submitted() {\n\t // Default to false.\n\t $submit = false;\n\n\t // Basic check for a field called submit-checkout.\n\t if ( isset( $_REQUEST['submit-checkout'] ) ) {\n\t \t$submit = true;\n\t }\n\n\t // _x stuff in case they clicked on the image button ...
Tool2026-06-01 03:04 UTC
{"output": "128:function pmpro_url( $page = null, $querystring = '', $scheme = null ) {\n176:\t$url = apply_filters( 'pmpro_url', $url, $page, $querystring, $scheme );\n2185:\t$sr_replace = array( pmpro_implodeToEnglish( $level_names ), urlencode( site_url( esc_url_raw( $_SERVER['REQUEST_URI'] ) ) )...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "function pmpro_url( $page = null, $querystring = '', $scheme = null ) {\n\tglobal $besecure;\n\t$besecure = apply_filters( 'besecure', $besecure );\n\n\tif ( ! $scheme && $besecure ) {\n\t\t$scheme = 'https';\n\t} elseif ( ! $scheme ) {\n\t\t$scheme = 'http';\n\t}\n\n\tif ( ! $page ) {\n...
Donna2026-06-01 03:04 UTC
Tool2026-06-01 03:04 UTC
{"output": "27:define( 'PMPRO_DIR', dirname( __FILE__ ) );\n30:require_once( PMPRO_DIR . '/classes/class-deny-network-activation.php' ); // stop PMPro from being network activated\n31:require_once( PMPRO_DIR . '/includes/sessions.php' ); \t\t// start/close PHP session vars\n33:requir...
Donna2026-06-01 03:04 UTC
Now I have all the information. Here's the comprehensive report: --- ## PMPro Signup/Checkout Form Fields — Complete Analysis ### 1. Active Plugins (related to PMPro) | Plugin | Status | Version | |--------|--------|---------| | `paid-memberships-pro` | Active | 3.7.4 | | `pmpro-signup-shortcode` | Active | 1.2 | | `pmpro-update-manager` | Active | 1.0.1 | `pmpro_pages` option does not exist yet (PMPro pages may not have been set up via the PMPro settings wizard). --- ### 2. How the Checkout Page is Rendered The checkout page can be loaded in three ways: **A. PMPro Page Shortcode** (`[pmpro_checkout]`) - **File:** `/var/www/html/wp-content/plugins/paid-memberships-pro/includes/init.php` (line 82-95) - Function `pmpro_pages_shortcode()` dynamically handles ALL `[pmpro_*]` shortcodes including `[pmpro_checkout]` - Loads the preheader first: `preheaders/checkout.php` - Then renders the template: `pages/checkout.php` - The preheader does all the processing logic (form validation, user creation, order processing) - The template just outputs the HTML form **B. pmpro_signup Shortcode (pmpro-signup-shortcode plugin)** - **File:** `/var/www/html/wp-content/plugins/pmpro-signup-shortcode/pmpro-signup-shortcode.php` - Function `pmprosus_signup_shortcode()` (line ~200) - Registers via `add_shortcode('pmpro_signup', 'pmprosus_signup_shortcode')` - This is a **self-contained form** that renders its own fields and submits to the standard `pmpro_url("checkout")` URL - Calls `do_action('pmpro_checkout_preheader', $pmpro_level)` to trigger the standard checkout preheader processing - Supports attributes: `level`, `levels` (multi-level), `short`, `intro`, `submit_button`, `login`, `redirect`, `hidelabels`, `custom_fields`, `confirm_email`, `confirm_password`, `title` **C. Checkout Block** - `/var/www/html/wp-content/plugins/paid-memberships-pro/blocks/src/checkout-page/` --- ### 3. Form Fields — Definition and Field Names #### Core fields in `pages/checkout.php` (standard checkout template): | Section | Field Name (HTML ID/Name) | Label | Type | |---------|--------------------------|-------|------| | **Pricing Fields** | `pmpro_level` (hidden) | Membership level ID | hidden | | | `pmpro_discount_code` | Discount code | hidden/text | | | `pmpro_other_discount_code` | Discount Code | text | | **Account Information** | `username` | Username | text | | | `password` | Password | password | | | `password2` | Confirm Password | password | | | `bemail` | Email Address | email/text | | | `bconfirmemail` | Confirm Email Address | email/text | | | `fullname` (honeypot) | Full Name | text (hidden) | | **Billing Address** | `bfirstname` | First Name | text | | | `blastname` | Last Name | text | | | `baddress1` | Address 1 | text | | | `baddress2` | Address 2 | text | | | `bcity` | City | text | | | `bstate` | State | text | | | `bzipcode` | Postal Code | text | | | `bcountry` | Country | select | | | `bphone` | Phone | text | | **Payment Information** | `CardType` | Card Type | hidden | | | `AccountNumber` | Card Number | text | | | `ExpirationMonth` | Expiration Month | select | | | `ExpirationYear` | Expiration Year | select | | | `CVV` | Security Code (CVC) | text | | **Form Meta** | `pmpro_checkout_nonce` | Nonce | hidden | | | `submit-checkout` | Submit trigger | hidden | #### pmpro_signup shortcode fields (`pmpro-signup-shortcode.php`, function `pmprosus_signup_shortcode`): | Field Name | Label | Notes | |-----------|-------|-------| | `level` (hidden or select) | Membership Level | Hidden for single-level, select for multi-level | | `username` | Username | Hidden when `short='emailonly'` | | `password` | Password | Hidden when `short='emailonly'` | | `password2` | Confirm Password | Skipped when `short` or `!confirm_password` | | `bemail` | E-mail Address | Always shown | | `bconfirmemail` | Confirm E-mail | Skipped when `short` or `!confirm_email` | | `fullname` (honeypot) | Full Name | Hidden | | `pmprosus_referrer` | Referrer URL | Hidden | | `redirect_to` | Redirect after signup | Hidden | | `pmpro_signup_shortcode` | Flag | Hidden, value `1` | | `submit-checkout` | Submit trigger | Hidden | --- ### 4. Action Hooks for Adding Custom Fields These hooks are fired inside `pages/checkout.php` (standard checkout template): | Hook Name | Position in Form | When it fires | |-----------|-----------------|---------------| | `pmpro_checkout_before_form` | Before `<form>` tag | With `$pmpro_level` param | | `pmpro_checkout_after_level_cost` | After pricing cost display | With `$pmpro_level` param | | `pmpro_checkout_after_pricing_fields` | After pricing section | With `$pmpro_level` param | | `pmpro_checkout_after_username` | After username field | No params | | `pmpro_checkout_after_password` | After password field | No params | | `pmpro_checkout_after_email` | After email field | No params | | `pmpro_checkout_after_user_fields` | After account info section | No params | | `pmpro_checkout_boxes` | After user fields, before billing | With `$pmpro_level` param | | `pmpro_checkout_after_billing_fields` | After billing address | No params | | `pmpro_checkout_after_payment_information_fields` | After payment info | With `$pmpro_level` param | | `pmpro_checkout_before_submit_button` | Before submit button | With `$pmpro_level` param | | `pmpro_checkout_after_form` | After closing `</form>` | With `$pmpro_level` param | The pmpro_signup shortcode fires these additional hooks: | Hook Name | Position | |-----------|----------| | `pmpro_signup_form_before_fields` | Before field wrapper | | `pmpro_signup_form_before_submit` | Before submit button (inside fields wrapper) | | `pmpro_signup_form_after_submit` | After submit button | | `pmpro_signup_form_after_form` | After closing `</form>` | --- ### 5. Custom Fields System (PMPro 3.4+) #### Architecture **Files:** - `/var/www/html/wp-content/plugins/paid-memberships-pro/classes/class-pmpro-field.php` — `PMPro_Field` class (1960 lines) - `/var/www/html/wp-content/plugins/paid-memberships-pro/classes/class-pmpro-field-group.php` — `PMPro_Field_Group` class (557 lines) - `/var/www/html/wp-content/plugins/paid-memberships-pro/includes/fields.php` — Functions for field management (1243 lines) **Key Classes:** - `PMPro_Field` — Represents a single field with properties: `name`, `type`, `label`, `required`, `hint`, `levels`, `profile`, `options`, `class`, `divclass`, `meta_key`, `showmainlabel`, `showrequired` - `PMPro_Field_Group` — Groups fields together. Supports methods: `add()`, `get()`, `get_all()`, `get_field()`, `add_field()`, `display()`, `save_fields()`, `get_fields_to_display()` **Field Types supported by PMPro_Field:** text, textarea, email, number, password, checkbox, checkbox_grouped, radio, select, select2, multiselect, date, file, url, phone, html, hidden #### Predefined Field Groups (where custom fields can be added) These are the `$where` locations used with `pmpro_add_user_field()`: | Group Name | Hook Location | Description | |-----------|---------------|-------------| | `after_username` | `pmpro_checkout_after_username` | Shown after username field | | `after_password` | `pmpro_checkout_after_password` | Shown after password field | | `after_email` | `pmpro_checkout_after_email` | Shown after email field | | `after_captcha` | `pmpro_checkout_before_submit_button` | Shown before submit (captcha area) | | `after_pricing_fields` | `pmpro_checkout_after_pricing_fields` | After pricing section | | `after_billing_fields` | `pmpro_checkout_after_billing_fields` | After billing section | | `before_submit_button` | `pmpro_checkout_before_submit_button` | Before submit button | | `after_tos_fields` | `pmpro_checkout_before_submit_button` (priority 6) | Before submit, after other fields | | `checkout_boxes` (and custom names) | `pmpro_checkout_boxes` | Shown as cards between user fields and billing | #### How custom fields are registered and rendered Programmatic API (using `includes/fields.php` functions): ```php // Add a field group (optional) pmpro_add_field_group('my_group', 'My Group Label', 'Description'); // Add a field to a group pmpro_add_user_field('after_email', new PMPro_Field( 'my_field_name', 'text', array( 'label' => 'My Field', 'required' => true, 'profile' => true, 'levels' => array(1, 2), // Only show for levels 1 and 2 ) )); ``` UI-based (stored in WordPress option `pmpro_user_fields_settings`): - Loaded by `pmpro_load_user_fields_from_settings()` hooked into `init` at priority 1 - File: `/var/www/html/wp-content/plugins/paid-memberships-pro/adminpages/user-fields/` #### How fields are rendered at checkout 1. `includes/fields.php` hooks `pmpro_checkout_*` action hooks to function `pmpro_display_fields_in_group()` which calls `PMPro_Field_Group::display()` 2. `PMPro_Field_Group::display()` iterates over fields and calls `$field->display($value)` for each 3. `PMPro_Field::display()` outputs the HTML for the specific field type #### How fields are saved at checkout 1. **User creation fields** (`after_username`, `after_password`, `after_email`): Saved via `pmpro_checkout_before_user_auth_save_fields()` hooked into `pmpro_checkout_before_user_auth` 2. **Other checkout fields**: Saved via `pmpro_after_checkout_save_fields()` hooked into `pmpro_after_checkout` 3. Validation via `pmpro_checkout_user_creation_checks_user_fields()` and `pmpro_registration_checks_for_user_fields()` --- ### 6. Processing Pipeline (preheaders/checkout.php) **File:** `/var/www/html/wp-content/plugins/paid-memberships-pro/preheaders/checkout.php` (733 lines) Key processing steps: 1. Detects token orders from URL 2. Sets `$pmpro_level` via `pmpro_getLevelAtCheckout()` 3. Determines if billing is required (`$pmpro_requirebilling`) 4. Fires `do_action('pmpro_checkout_preheader', $pmpro_level)` 5. Reads all field values from `$_REQUEST` into globals (`$username`, `$password`, `$bemail`, `$bfirstname`, etc.) 6. Sets required field arrays (`$pmpro_required_billing_fields`, `$pmpro_required_user_fields`) 7. Checks nonce via `wp_verify_nonce()` 8. Validates required fields 9. Creates user via `wp_insert_user()` (if not logged in) 10. Creates order via `new MemberOrder()` 11. Processes payment via `$pmpro_review->process()` 12. On success: calls `pmpro_complete_checkbox()` and redirects to confirmation **Filter hooks for validation/middleware:** - `pmpro_skip_account_fields` — Skip account fields if user is logged in - `pmpro_checkout_confirm_password` — Show/hide confirm password field - `pmpro_checkout_confirm_email` — Show/hide confirm email field - `pmpro_include_billing_address_fields` — Show/hide billing address - `pmpro_include_payment_information_fields` — Show/hide payment info - `pmpro_require_billing` — Force billing fields - `pmpro_checkout_checks` — Custom checkout validation - `pmpro_registration_checks` — Legacy registration checks - `pmpro_checkout_user_creation_checks` — User creation checks - `pmpro_checkout_order_creation_checks` — Order creation checks - `pmpro_required_billing_fields` — Filter required billing fields array - `pmpro_required_user_fields` — Filter required user fields array - `pmpro_checkout_new_user_array` — Filter user data before creation --- ### 7. pmpro-signup-shortcode Plugin Summary **File:** `/var/www/html/wp-content/plugins/pmpro-signup-shortcode/pmpro-signup-shortcode.php` (591 lines) Key features: - Shortcode `[pmpro_signup]` with attributes: `level`, `levels` (multi-level dropdown), `short`, `intro`, `submit_button`, `login`, `redirect`, `hidelabels`, `custom_fields`, `confirm_email`, `confirm_password`, `title` - Automatically copies email to username when no username field (using `pmpro_generateUsername()`) - Automatically generates password when no password field - Stores auto-generated password in session for email confirmation - Saves referrer data in user meta - Supports `redirect_to` / `pmprosus_referrer` for post-signup redirect - Fires `pmpro_checkout_preheader` action so standard PMPro hooks work - Includes a Block Editor block in `blocks/build/pmpro-signup-block/` - Uses `pmprosus_skip_username_password()` on `init` to auto-populate username/password from bemail