PluginProbe ʕ •ᴥ•ʔ
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / trunk
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz vtrunk
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 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8 0.0.9 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.1.2 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.12.3 1.13.0 1.13.1 1.13.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.8.0 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.0 2.5.2 2.6.0
sureforms / inc / gutenberg-hooks.php
sureforms / inc Last commit date
abilities 3 weeks ago admin 3 months ago ai-form-builder 1 month ago blocks 2 months ago compatibility 3 weeks ago database 3 weeks ago email 3 weeks ago fields 3 weeks ago global-settings 1 month ago lib 1 month ago migrator 2 months ago page-builders 3 weeks ago payments 3 weeks ago single-form-settings 2 months ago traits 2 months ago activator.php 1 year ago admin-ajax.php 2 months ago background-process.php 9 months ago create-new-form.php 3 months ago duplicate-form.php 3 months ago entries.php 3 weeks ago events-scheduler.php 2 years ago export.php 3 months ago field-validation.php 3 weeks ago form-restriction.php 2 months ago form-styling.php 1 month ago form-submit.php 5 days ago forms-data.php 5 months ago frontend-assets.php 5 days ago generate-form-markup.php 1 week ago gutenberg-hooks.php 1 week ago helper.php 5 days ago learn.php 4 months ago onboarding.php 2 months ago post-types.php 1 week ago rest-api.php 1 week ago smart-tags.php 5 days ago submit-token.php 4 months ago translatable.php 1 month ago updater-callbacks.php 3 weeks ago updater.php 3 weeks ago
gutenberg-hooks.php
361 lines
1 <?php
2 /**
3 * Gutenberg Hooks Manager Class.
4 *
5 * @package sureforms.
6 */
7
8 namespace SRFM\Inc;
9
10 use SRFM\Inc\Traits\Get_Instance;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly.
14 }
15
16 /**
17 * Gutenberg hooks handler class.
18 *
19 * @since 0.0.1
20 */
21 class Gutenberg_Hooks {
22 use Get_Instance;
23 /**
24 * Block patterns to register.
25 *
26 * @var array<mixed>
27 */
28 protected $patterns = [];
29
30 /**
31 * Class constructor.
32 *
33 * @return void
34 * @since 0.0.1
35 */
36 public function __construct() {
37 // Setting Form default patterns.
38 $this->patterns = [
39 'blank-form',
40 'contact-form',
41 'newsletter-form',
42 'support-form',
43 'feedback-form',
44 'event-rsvp-form',
45 'subscription-form',
46 ];
47
48 // Initializing hooks.
49 add_action( 'enqueue_block_editor_assets', [ $this, 'form_editor_screen_assets' ] );
50 add_action( 'enqueue_block_editor_assets', [ $this, 'block_editor_assets' ] );
51 add_filter( 'block_categories_all', [ $this, 'register_block_categories' ], 10, 2 );
52 add_filter( 'allowed_block_types_all', [ $this, 'disable_forms_wrapper_block' ], 10, 2 );
53 add_action( 'save_post_sureforms_form', [ $this, 'update_field_slug' ], 10, 2 );
54 add_action( 'load-post.php', [ $this, 'maybe_migrate_form_stylings' ] );
55 }
56
57 /**
58 * Disable Sureforms_Form Block and allowed only sureforms block inside Sureform CPT editor.
59 *
60 * @param bool|array<string> $allowed_block_types Array of block types.
61 * @param \WP_Block_Editor_Context $editor_context The current block editor context.
62 * @return array<mixed>|bool
63 * @since 0.0.1
64 */
65 public function disable_forms_wrapper_block( $allowed_block_types, $editor_context ) {
66 if ( ! empty( $editor_context->post->post_type ) && 'sureforms_form' === $editor_context->post->post_type ) {
67 $allow_block_types = [
68 'srfm/input',
69 'srfm/email',
70 'srfm/textarea',
71 'srfm/number',
72 'srfm/checkbox',
73 'srfm/gdpr',
74 'srfm/phone',
75 'srfm/address',
76 'srfm/dropdown',
77 'srfm/multi-choice',
78 'srfm/url',
79 'srfm/separator',
80 'srfm/icon',
81 'srfm/image',
82 'srfm/advanced-heading',
83 'srfm/inline-button',
84 'srfm/payment',
85 ];
86 // Apply a filter to the $allow_block_types types array.
87 return apply_filters( 'srfm_allowed_block_types', $allow_block_types, $editor_context );
88 }
89
90 // Return the default $allowed_block_types value.
91 return $allowed_block_types;
92 }
93
94 /**
95 * Register our custom block category.
96 *
97 * @param array<mixed> $categories Array of categories.
98 * @param \WP_Block_Editor_Context $block_editor_context The current block editor context.
99 * @return array<mixed>
100 * @since 0.0.1
101 */
102 public function register_block_categories( $categories, $block_editor_context ) {
103
104 $post_type = $block_editor_context->post->post_type ?? '';
105
106 if ( $post_type && SRFM_FORMS_POST_TYPE === $post_type ) {
107 $title = esc_html__( 'General Fields', 'sureforms' );
108 } else {
109 $title = esc_html__( 'SureForms', 'sureforms' );
110 }
111
112 $custom_categories = [
113 [
114 'slug' => 'sureforms',
115 'title' => $title,
116 ],
117 [
118 'slug' => 'sureforms-pro',
119 'title' => esc_html__( 'Advanced Fields', 'sureforms' ),
120 ],
121 ];
122
123 return array_merge( $custom_categories, $categories );
124 }
125
126 /**
127 * Add Form Editor Scripts.
128 *
129 * @return void
130 * @since 0.0.1
131 */
132 public function form_editor_screen_assets() {
133 $form_editor_script = '-formEditor';
134
135 $screen = get_current_screen();
136 $post_types = [ SRFM_FORMS_POST_TYPE ];
137
138 if ( is_null( $screen ) || ! in_array( $screen->post_type, $post_types, true ) ) {
139 return;
140 }
141
142 $script_asset_path = SRFM_DIR . 'assets/build/formEditor.asset.php';
143 $script_info = file_exists( $script_asset_path )
144 ? include $script_asset_path
145 : [
146 'dependencies' => [],
147 'version' => SRFM_VER,
148 ];
149
150 wp_enqueue_script( SRFM_SLUG . $form_editor_script, SRFM_URL . 'assets/build/formEditor.js', $script_info['dependencies'], $script_info['version'], true );
151 wp_localize_script( SRFM_SLUG . $form_editor_script, 'scIcons', [ 'path' => SRFM_URL . 'assets/build/icon-assets' ] );
152
153 // Deep-link (#3030): the "Finish setting up" Thank You notice CTA opens this
154 // editor with ?srfm_focus=… to auto-open a settings tab. Gutenberg strips
155 // unrecognised query args client-side before the editor bundle can read them,
156 // so surface the value from the server — where it is never stripped — as a
157 // global the bundle reads at evaluation time. Validated to a known allowlist.
158 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only deep-link hint on an authenticated editor screen; no state change.
159 $srfm_focus = isset( $_GET['srfm_focus'] ) ? sanitize_key( wp_unslash( $_GET['srfm_focus'] ) ) : '';
160 if ( in_array( $srfm_focus, [ 'thankyou', 'notifications' ], true ) ) {
161 wp_add_inline_script( SRFM_SLUG . $form_editor_script, 'window.srfmDeepLinkFocus = ' . wp_json_encode( $srfm_focus ) . ';', 'before' );
162 }
163
164 // Enqueue the code editor for the Custom CSS Editor in SureForms.
165 wp_enqueue_code_editor( [ 'type' => 'text/css' ] );
166 wp_enqueue_script( 'wp-theme-plugin-editor' );
167 wp_enqueue_style( 'wp-codemirror' );
168
169 wp_localize_script(
170 SRFM_SLUG . $form_editor_script,
171 SRFM_SLUG . '_block_data',
172 [
173 'plugin_url' => SRFM_URL,
174 'admin_email' => get_option( 'admin_email' ),
175 'pro_plugin_name' => defined( 'SRFM_PRO_VER' ) && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'free',
176 ]
177 );
178
179 Helper::register_script_translations( SRFM_SLUG . $form_editor_script );
180 }
181
182 /**
183 * Register all editor scripts.
184 *
185 * @return void
186 * @since 0.0.1
187 */
188 public function block_editor_assets() {
189 $all_screen_blocks = '-blocks';
190 $screen = get_current_screen();
191
192 $blocks_asset_path = SRFM_DIR . 'assets/build/blocks.asset.php';
193 $blocks_info = file_exists( $blocks_asset_path )
194 ? include $blocks_asset_path
195 : [
196 'dependencies' => [],
197 'version' => SRFM_VER,
198 ];
199 wp_enqueue_script( SRFM_SLUG . $all_screen_blocks, SRFM_URL . 'assets/build/blocks.js', $blocks_info['dependencies'], SRFM_VER, true );
200
201 Helper::register_script_translations( SRFM_SLUG . $all_screen_blocks );
202
203 $site_url = Helper::get_string_value( wp_parse_url( esc_url( get_site_url() ), PHP_URL_HOST ) );
204 $site_url = preg_replace( '/^www\./', '', $site_url );
205
206 wp_localize_script(
207 SRFM_SLUG . $all_screen_blocks,
208 SRFM_SLUG . '_block_data',
209 [
210 'template_picker_url' => admin_url( '/admin.php?page=add-new-form' ),
211 'plugin_url' => SRFM_URL,
212 'admin_email' => get_option( 'admin_email' ),
213 'post_url' => admin_url( 'post.php' ),
214 'current_screen' => $screen,
215 'smart_tags_array' => Smart_Tags::smart_tag_list(),
216 'smart_tags_array_email' => Smart_Tags::email_smart_tag_list(),
217 // No srfm_form_markup nonce: the generate-form-markup route is gated by a
218 // capability check, not by holding a nonce. It used to be minted here for
219 // every editor user and read from the query string, which is precisely how
220 // that route ended up with no real authorization (#2995).
221 'get_form_markup_url' => 'sureforms/v1/generate-form-markup',
222 'is_pro_active' => Helper::has_pro(),
223 'srfm_default_dynamic_block_option' => wp_parse_args( Helper::get_array_value( get_option( 'srfm_default_dynamic_block_option', [] ) ), Helper::default_dynamic_block_option() ),
224 'form_selector_nonce' => Helper::current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
225 'is_admin_user' => Helper::current_user_can(),
226 'site_url' => $site_url,
227 'is_suremails_active' => is_plugin_active( 'suremails/suremails.php' ),
228 'upgrade_url' => add_query_arg(
229 [ 'utm_medium' => 'embed_styling_upgrade' ],
230 Helper::get_sureforms_website_url( 'pricing' )
231 ),
232 'default_translations' => [
233 'gdpr_label' => __( 'I consent to have this website store my submitted information so they can respond to my inquiry.', 'sureforms' ),
234 'dropdown_placeholder' => __( 'Select an option', 'sureforms' ),
235 ],
236 ]
237 );
238
239 // Localizing the field preview image links.
240 wp_localize_script(
241 SRFM_SLUG . $all_screen_blocks,
242 SRFM_SLUG . '_fields_preview',
243 apply_filters(
244 'srfm_block_preview_images',
245 [
246 'input_preview' => SRFM_URL . 'images/field-previews/input.svg',
247 'email_preview' => SRFM_URL . 'images/field-previews/email.svg',
248 'url_preview' => SRFM_URL . 'images/field-previews/url.svg',
249 'textarea_preview' => SRFM_URL . 'images/field-previews/textarea.svg',
250 'multi_choice_preview' => SRFM_URL . 'images/field-previews/multi-choice.svg',
251 'checkbox_preview' => SRFM_URL . 'images/field-previews/checkbox.svg',
252 'number_preview' => SRFM_URL . 'images/field-previews/number.svg',
253 'phone_preview' => SRFM_URL . 'images/field-previews/phone.svg',
254 'dropdown_preview' => SRFM_URL . 'images/field-previews/dropdown.svg',
255 'address_preview' => SRFM_URL . 'images/field-previews/address.svg',
256 'sureforms_preview' => SRFM_URL . 'images/field-previews/sureforms.svg',
257 'payment_preview' => SRFM_URL . 'images/field-previews/payment.svg',
258 ]
259 )
260 );
261
262 wp_localize_script(
263 SRFM_SLUG . $all_screen_blocks,
264 SRFM_SLUG . '_blocks_info',
265 [
266 'font_awesome_5_polyfill' => [],
267 'collapse_panels' => 'enabled',
268 'is_site_editor' => $screen ? $screen->id : null,
269 ]
270 );
271 }
272
273 /**
274 * This function generates slug for sureforms blocks.
275 * Generates slug only if slug attribute of block is empty.
276 * Ensures that all sureforms blocks have unique slugs.
277 *
278 * @param int $post_id current sureforms form post id.
279 * @param \WP_Post $post SureForms post object.
280 * @since 0.0.2
281 * @return void
282 */
283 public function update_field_slug( $post_id, $post ) {
284 $blocks = parse_blocks( $post->post_content );
285
286 if ( empty( $blocks ) ) {
287 return;
288 }
289
290 $updated = false;
291
292 /**
293 * List of slugs already taken by processed blocks.
294 * used to maintain uniqueness of slugs.
295 */
296 $slugs = [];
297
298 [ $blocks, $slugs, $updated ] = Helper::process_blocks( $blocks, $slugs, $updated );
299
300 // Process and store block configurations for form fields.
301 Field_Validation::add_block_config( $blocks, $post_id );
302
303 if ( ! $updated ) {
304 return;
305 }
306
307 $post_content = serialize_blocks( $blocks );
308
309 // Use wp_slash() to preserve unicode escapes (like \u003c for <) in block attributes.
310 // Without this, wp_update_post() calls wp_unslash() which corrupts these escapes.
311 wp_update_post(
312 [
313 'ID' => $post_id,
314 'post_content' => wp_slash( $post_content ),
315 ]
316 );
317 }
318
319 /**
320 * Migrate the background type and associated values from
321 * instant form settings to form styling meta.
322 *
323 * @since 1.4.4
324 * @return void
325 */
326 public function maybe_migrate_form_stylings() {
327 $post_id = isset( $_GET['post'] ) ? Helper::get_integer_value( sanitize_text_field( wp_unslash( $_GET['post'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['post'] does not provide nonce.
328 if ( empty( $post_id ) || ! Helper::current_user_can() ) {
329 return;
330 }
331
332 $post_type = get_post_type( $post_id );
333 if ( SRFM_FORMS_POST_TYPE !== $post_type ) {
334 return;
335 }
336
337 $instant_form_settings = get_post_meta( $post_id, '_srfm_instant_form_settings', true );
338 if ( ! is_array( $instant_form_settings ) ) {
339 return;
340 }
341
342 $form_styling = get_post_meta( $post_id, '_srfm_forms_styling', true );
343 if ( ! is_array( $form_styling ) ) {
344 $form_styling = [];
345 }
346
347 $migrated = false;
348 $keys = [ 'bg_type', 'bg_color', 'bg_image', 'bg_image_id' ];
349
350 foreach ( $keys as $key ) {
351 if ( ! isset( $form_styling[ $key ] ) && isset( $instant_form_settings[ $key ] ) ) {
352 $form_styling[ $key ] = $instant_form_settings[ $key ];
353 $migrated = true;
354 }
355 }
356 if ( $migrated ) {
357 update_post_meta( $post_id, '_srfm_forms_styling', $form_styling );
358 }
359 }
360 }
361