PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / form-builder / form-builder-rest-mirror.php

form-builder-rest-mirror.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 4.0.3, at form-builder/form-builder-rest-mirror.php

210 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Virtual REST flat keys ↔ legacy nested settings. Flat rows deleted after mirror.
4 * Also injects generated block markup into content.raw on REST GET.
5 */
6
7 if ( ! defined( 'ABSPATH' ) ) exit;
8
9 // 1. Meta mirroring (flat -> nested)
10
11 /** Maps virtual flat REST meta keys to legacy nested settings keys. */
12 function wppb_fb_virtual_setting_map( $post_type ) {
13 $base = array(
14 'wppb_fb_redirect' => 'redirect',
15 'wppb_fb_display_messages' => 'display-messages',
16 'wppb_fb_url' => 'url',
17 'wppb_fb_ajax' => 'ajax',
18 );
19 if ( $post_type === 'wppb-rf-cpt' ) {
20 $base['wppb_fb_set_role'] = 'set-role';
21 $base['wppb_fb_automatically_log_in'] = 'automatically-log-in';
22 }
23 return $base;
24 }
25
26 /** The legacy settings meta key for a given post type. */
27 function wppb_fb_settings_meta_key( $post_type ) {
28 return $post_type === 'wppb-rf-cpt' ? 'wppb_rf_page_settings' : 'wppb_epf_page_settings';
29 }
30
31 /** Folds a flat meta write into the legacy nested array, then deletes the flat row. */
32 add_action( 'added_post_meta', 'wppb_fb_mirror_flat_to_nested', 10, 4 );
33 add_action( 'updated_post_meta', 'wppb_fb_mirror_flat_to_nested', 10, 4 );
34 function wppb_fb_mirror_flat_to_nested( $meta_id, $post_id, $meta_key, $meta_value ) {
35 $post_type = get_post_type( $post_id );
36 if ( ! in_array( $post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true ) ) return;
37
38 $map = wppb_fb_virtual_setting_map( $post_type );
39 if ( ! isset( $map[ $meta_key ] ) ) return;
40
41 $nested_key = $map[ $meta_key ];
42 $storage_key = wppb_fb_settings_meta_key( $post_type );
43 $settings = get_post_meta( $post_id, $storage_key, true );
44 if ( ! is_array( $settings ) || empty( $settings[0] ) || ! is_array( $settings[0] ) ) {
45 $settings = array( 0 => array() );
46 }
47
48 $settings[0][ $nested_key ] = $meta_value;
49 update_post_meta( $post_id, $storage_key, $settings );
50
51 // Delete the flat row so wp_postmeta stays clean.
52 delete_post_meta( $post_id, $meta_key );
53 }
54
55 // 2. REST injections. Two filters, so an add-on bridge projecting its own
56 // virtual meta has a published seam: block markup at priority 10, virtual
57 // settings at 11, add-ons at 11+ (where the canonical content is in place).
58
59 add_filter( 'rest_prepare_wppb-rf-cpt', 'wppb_fb_inject_generated_content_block_markup', 10, 3 );
60 add_filter( 'rest_prepare_wppb-epf-cpt', 'wppb_fb_inject_generated_content_block_markup', 10, 3 );
61 add_filter( 'rest_prepare_wppb-rf-cpt', 'wppb_fb_inject_generated_content_virtual_settings', 11, 3 );
62 add_filter( 'rest_prepare_wppb-epf-cpt', 'wppb_fb_inject_generated_content_virtual_settings', 11, 3 );
63
64 /**
65 * Injects the generated block markup into `content.raw` on REST GET (see the file
66 * header — post_content itself is never persisted).
67 */
68 function wppb_fb_inject_generated_content_block_markup( $response, $post, $request ) {
69 if ( ! $response instanceof WP_REST_Response ) return $response;
70 $data = $response->get_data();
71 if ( ! isset( $data['id'] ) ) return $response;
72
73 $post_id = (int) $data['id'];
74 $post_type = $post->post_type;
75
76 $generated = wppb_fb_build_block_markup_for_form( $post_id, $post_type );
77 if ( isset( $data['content'] ) && is_array( $data['content'] ) ) {
78 $data['content']['raw'] = $generated;
79 }
80
81 $response->set_data( $data );
82 return $response;
83 }
84
85 /**
86 * Project legacy nested settings onto virtual flat REST meta keys so the
87 * Document sidebar's `useEntityProp` sees current values.
88 */
89 function wppb_fb_inject_generated_content_virtual_settings( $response, $post, $request ) {
90 if ( ! $response instanceof WP_REST_Response ) return $response;
91 $data = $response->get_data();
92 if ( ! isset( $data['id'] ) ) return $response;
93
94 $post_id = (int) $data['id'];
95 $post_type = $post->post_type;
96
97 $settings = get_post_meta( $post_id, wppb_fb_settings_meta_key( $post_type ), true );
98 $nested = is_array( $settings ) && isset( $settings[0] ) ? $settings[0] : array();
99 foreach ( wppb_fb_virtual_setting_map( $post_type ) as $flat => $nested_key ) {
100 if ( isset( $nested[ $nested_key ] ) ) {
101 $data['meta'][ $flat ] = $nested[ $nested_key ];
102 }
103 }
104
105 // Derived, never stored: no setting-map entry, so the write mirror can't
106 // round-trip it back into storage. See wppb_fb_build_form_shortcode().
107 $data['meta']['wppb_fb_form_shortcode'] = wppb_fb_build_form_shortcode( $post );
108
109 $response->set_data( $data );
110 return $response;
111 }
112
113 /**
114 * True when this form is the configured default (by `wppb_default_form_ids`, not the flag).
115 *
116 * @param int|WP_Post $post
117 * @return bool
118 */
119 function wppb_fb_is_default_form( $post ) {
120 $post = get_post( $post );
121 if ( ! $post instanceof WP_Post ) {
122 return false;
123 }
124 $defaults = get_option( 'wppb_default_form_ids', array() );
125 $type = ( $post->post_type === 'wppb-epf-cpt' ) ? 'edit_profile' : 'register';
126 return ! empty( $defaults[ $type ] ) && (int) $defaults[ $type ] === (int) $post->ID;
127 }
128
129 /**
130 * Embed shortcode for a form (classic metabox). '' until published; defaults omit form_name.
131 */
132 function wppb_fb_build_form_shortcode( $post ) {
133 if ( ! $post instanceof WP_Post || ! class_exists( 'Wordpress_Creation_Kit_PB' ) ) {
134 return '';
135 }
136 if ( $post->post_status !== 'publish' ) {
137 return '';
138 }
139 $tag = ( $post->post_type === 'wppb-epf-cpt' ) ? 'wppb-edit-profile' : 'wppb-register';
140 if ( wppb_fb_is_default_form( $post ) ) {
141 return '[' . $tag . ']';
142 }
143 $slug = trim( Wordpress_Creation_Kit_PB::wck_generate_slug( $post->post_title ) );
144 if ( $slug === '' ) {
145 return '';
146 }
147 return '[' . $tag . ' form_name="' . $slug . '"]';
148 }
149
150 // 3. Virtual meta registration (REST visibility for the editor)
151
152 /** Registers the virtual meta keys so `useEntityProp` can read and write them. */
153 add_action( 'init', 'wppb_fb_register_virtual_meta' );
154 function wppb_fb_register_virtual_meta() {
155 // These are admin-only form settings, so the write boundary is raised to
156 // `manage_options` (the gate the wppb/v1 routes use) rather than the default
157 // `edit_post` meta cap an Editor holds on these CPTs — otherwise an Editor
158 // could REST-write `wppb_fb_set_role=administrator` and escalate every new
159 // registrant to admin.
160 $meta_keys = array(
161 'wppb_fb_redirect' => 'sanitize_text_field',
162 'wppb_fb_display_messages' => 'wppb_fb_sanitize_meta_digits',
163 'wppb_fb_url' => 'esc_url_raw',
164 'wppb_fb_ajax' => 'sanitize_text_field',
165 'wppb_fb_set_role' => 'wppb_fb_sanitize_meta_role',
166 'wppb_fb_automatically_log_in' => 'sanitize_text_field',
167 );
168
169 foreach ( array( 'wppb-rf-cpt', 'wppb-epf-cpt' ) as $post_type ) {
170 foreach ( $meta_keys as $key => $sanitize_cb ) {
171 register_post_meta( $post_type, $key, array(
172 'show_in_rest' => true,
173 'single' => true,
174 'type' => 'string',
175 'sanitize_callback' => $sanitize_cb,
176 'auth_callback' => 'wppb_fb_virtual_meta_auth',
177 ) );
178 }
179 }
180 }
181
182 /**
183 * Write gate for the virtual settings meta: only administrators may set them.
184 */
185 function wppb_fb_virtual_meta_auth() {
186 return current_user_can( 'manage_options' );
187 }
188
189 /**
190 * Sanitizer for `wppb_fb_set_role`: only allow a role slug the current user can
191 * actually assign. Anything unknown collapses to '' so a rejected value can
192 * never escalate a new registrant's role.
193 */
194 function wppb_fb_sanitize_meta_role( $value ) {
195 $value = sanitize_text_field( (string) $value );
196 if ( $value === '' ) {
197 return '';
198 }
199 if ( ! function_exists( 'get_editable_roles' ) ) {
200 require_once ABSPATH . 'wp-admin/includes/user.php';
201 }
202 $editable = get_editable_roles();
203 return array_key_exists( $value, $editable ) ? $value : '';
204 }
205
206 /** Sanitizer for numeric string meta (e.g. `wppb_fb_display_messages` seconds). */
207 function wppb_fb_sanitize_meta_digits( $value ) {
208 return (string) absint( $value );
209 }
210