PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.8
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.8
2.12.8 2.12.7 2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 All 98 releases
← All changes | inc/post-types.php +77 -18 2.8.0 → 2.12.8 View file →
@@ -35,9 +35,8 @@
35 35 add_action( 'init', [ $this, 'register_post_types' ] );
36 36 add_action( 'init', [ $this, 'register_post_metas' ] );
37 37 add_shortcode( 'sureforms', [ $this, 'forms_shortcode' ] );
38 38 add_action( 'manage_posts_extra_tablenav', [ $this, 'maybe_render_blank_form_state' ] );
39 - add_action( 'admin_bar_menu', [ $this, 'remove_admin_bar_menu_item' ], 80, 1 );
40 39 add_action( 'template_redirect', [ $this, 'srfm_instant_form_redirect' ] );
41 40 add_action( 'template_redirect', [ $this, 'disable_sureforms_archive_page' ], 9 );
42 41 add_action( 'load-edit.php', [ $this, 'redirect_forms_listing_page' ] );
43 42
@@ -42,8 +41,9 @@
42 41 add_action( 'load-edit.php', [ $this, 'redirect_forms_listing_page' ] );
43 42
44 43 add_filter( 'rest_prepare_sureforms_form', [ $this, 'sureforms_normalize_meta_for_rest' ], 10, 2 );
45 44 add_action( 'admin_bar_menu', [ $this, 'add_edit_form_to_admin_bar_menu' ], 100 );
45 + add_action( 'admin_bar_menu', [ $this, 'add_new_form_to_admin_bar_menu' ], 100 );
46 46 }
47 47
48 48 /**
49 49 * Redirect the forms listing page to the updated forms page.
@@ -103,8 +103,47 @@
103 103 );
104 104 }
105 105
106 106 /**
107 + * Add a "Form" shortcut to the admin bar "+ New" menu (#3026).
108 + *
109 + * Mirrors how core post types appear under "+ New", but added manually rather
110 + * than via `show_in_admin_bar` so it does not also register a second front-end
111 + * "Edit" node alongside the custom one in add_edit_form_to_admin_bar_menu().
112 + * Gated on the form CPT's own create capability (manage_options for this CPT),
113 + * so it only shows for users who can actually create a form.
114 + *
115 + * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
116 + * @since 2.12.4
117 + * @return void
118 + */
119 + public function add_new_form_to_admin_bar_menu( $wp_admin_bar ) {
120 + if ( ! is_admin_bar_showing() || ! $wp_admin_bar instanceof WP_Admin_Bar ) {
121 + return;
122 + }
123 +
124 + $post_type = get_post_type_object( SRFM_FORMS_POST_TYPE );
125 +
126 + if ( ! $post_type || empty( $post_type->cap->create_posts ) || ! current_user_can( $post_type->cap->create_posts ) ) {
127 + return;
128 + }
129 +
130 + // Core registers the "+ New" (new-content) group at priority 70, so running at
131 + // 100 places this node inside it. If core skipped the group (the user can create
132 + // nothing else), WP_Admin_Bar::_bind() drops this orphan node silently.
133 + // name_admin_bar is the label core uses for "+ New" children; escaped because
134 + // WP_Admin_Bar echoes node titles unescaped.
135 + $wp_admin_bar->add_node(
136 + [
137 + 'id' => 'new-' . SRFM_FORMS_POST_TYPE,
138 + 'parent' => 'new-content',
139 + 'title' => esc_html( $post_type->labels->name_admin_bar ),
140 + 'href' => esc_url( admin_url( 'post-new.php?post_type=' . SRFM_FORMS_POST_TYPE ) ),
141 + ]
142 + );
143 + }
144 +
145 + /**
107 146 * Remove this method in the future once _srfm_form_confirmation meta is updated.
108 147 * Normalize the _srfm_form_confirmation meta before it's sent to the REST API.
109 148 * Ensures the meta data is type-safe and includes necessary defaults like `hide_copy`.
110 149 *
@@ -114,22 +153,43 @@
114 153 * @return WP_REST_Response Modified REST response with normalized meta.
115 154 * @since 1.7.3
116 155 */
117 156 public function sureforms_normalize_meta_for_rest( $response, $post ) {
118 - $meta_raw = get_post_meta( $post->ID, '_srfm_form_confirmation', true );
119 - $form_confirmation = maybe_unserialize( is_string( $meta_raw ) ? $meta_raw : '' );
157 + $meta_raw = get_post_meta( $post->ID, '_srfm_form_confirmation', true );
158 + // Meta may be a PHP array (new forms stored via update_post_meta with an array)
159 + // or a serialized/JSON string (legacy forms). Handle both.
160 + $form_confirmation = is_array( $meta_raw ) ? $meta_raw : maybe_unserialize( is_string( $meta_raw ) ? $meta_raw : '' );
120 161
121 162 if ( ! is_array( $form_confirmation ) ) {
122 163 return $response;
123 164 }
124 165
166 + // Only normalize keys that extensions (e.g. SureForms Pro) have actually
167 + // declared in the REST schema; otherwise REST PUT validation rejects them
168 + // with "<key> is not a valid property of Object.".
169 + $registered = get_registered_meta_keys( 'post', SRFM_FORMS_POST_TYPE );
170 + $item_properties = $registered['_srfm_form_confirmation']['show_in_rest']['schema']['items']['properties'] ?? [];
171 +
125 172 foreach ( $form_confirmation as $index => $item ) {
126 173 if ( ! is_array( $item ) ) {
127 174 continue;
128 175 }
129 176
130 - $form_confirmation[ $index ]['hide_copy'] = ! empty( $item['hide_copy'] );
131 - $form_confirmation[ $index ]['hide_download_all'] = ! empty( $item['hide_download_all'] );
177 + if ( isset( $item_properties['hide_copy'] ) ) {
178 + $form_confirmation[ $index ]['hide_copy'] = ! empty( $item['hide_copy'] );
179 + }
180 + if ( isset( $item_properties['hide_download_all'] ) ) {
181 + $form_confirmation[ $index ]['hide_download_all'] = ! empty( $item['hide_download_all'] );
182 + }
183 +
184 + // DOMDocument::saveHTML() strips the "data:" prefix from data URIs in src attributes.
185 + // Restore it so the editor displays SVG images correctly.
186 + if ( isset( $item['message'] ) && is_string( $item['message'] ) && false !== strpos( $item['message'], 'src="image/svg+xml;base64' ) ) {
187 + $normalized = preg_replace( '/src="image\/svg\+xml;base64/', 'src="data:image/svg+xml;base64', $item['message'] );
188 + if ( is_string( $normalized ) ) {
189 + $form_confirmation[ $index ]['message'] = $normalized;
190 + }
191 + }
132 192 }
133 193
134 194 $response_data = $response->get_data();
135 195 if ( is_array( $response_data ) ) {
@@ -271,20 +331,8 @@
271 331 }
272 332 }
273 333
274 334 /**
275 - * Remove add new form menu item.
276 - *
277 - * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
278 - *
279 - * @return void
280 - * @since 0.0.1
281 - */
282 - public function remove_admin_bar_menu_item( $wp_admin_bar ) {
283 - $wp_admin_bar->remove_node( 'new-sureforms_form' );
284 - }
285 -
286 - /**
287 335 * Show blank slate styles.
288 336 *
289 337 * @return void
290 338 * @since 0.0.1
@@ -399,8 +447,13 @@
399 447 '_srfm_is_ai_generated' => 'boolean',
400 448 ]
401 449 );
402 450
451 + // NOTE: `_srfm_form_views` is intentionally NOT registered here. It is a
452 + // server-side counter written only by Form_Views (get/add_post_meta + atomic
453 + // SQL). Exposing it to the block editor via show_in_rest let a form save /
454 + // autosave round-trip a stale value and clobber the live count back to 0.
455 +
403 456 // Form Custom CSS meta.
404 457 register_post_meta(
405 458 'sureforms_form',
406 459 '_srfm_form_custom_css',
@@ -801,8 +854,12 @@
801 854 ],
802 855 'instant_form_border_radius_link' => [
803 856 'type' => 'boolean',
804 857 ],
858 + // Disable default SureForms styling.
859 + 'disable_default_styles' => [
860 + 'type' => 'boolean',
861 + ],
805 862 ],
806 863 ],
807 864 ],
808 865 'default' => [
@@ -881,8 +938,10 @@
881 938 'instant_form_border_radius_bottom' => 12,
882 939 'instant_form_border_radius_left' => 12,
883 940 'instant_form_border_radius_unit' => 'px',
884 941 'instant_form_border_radius_link' => true,
942 + // Disable default SureForms styling.
943 + 'disable_default_styles' => false,
885 944 ],
886 945 ]
887 946 );
888 947
@@ -1084,9 +1143,9 @@
1084 1143 'id' => isset( $item['id'] ) ? intval( $item['id'] ) : 0,
1085 1144 'confirmation_type' => isset( $item['confirmation_type'] ) ? sanitize_text_field( $item['confirmation_type'] ) : '',
1086 1145 'page_url' => isset( $item['page_url'] ) ? esc_url_raw( $item['page_url'] ) : '',
1087 1146 'custom_url' => isset( $item['custom_url'] ) ? esc_url_raw( $item['custom_url'] ) : '',
1088 - 'message' => isset( $item['message'] ) ? Helper::strip_js_attributes( $item['message'] ) : '',
1147 + 'message' => isset( $item['message'] ) ? wp_kses_post( $item['message'] ) : '',
1089 1148 'submission_action' => isset( $item['submission_action'] ) ? sanitize_text_field( $item['submission_action'] ) : '',
1090 1149 'enable_query_params' => isset( $item['enable_query_params'] ) ? filter_var( $item['enable_query_params'], FILTER_VALIDATE_BOOLEAN ) : false,
1091 1150 'query_params' => isset( $item['query_params'] ) && is_array( $item['query_params'] )
1092 1151 ? array_map(