PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.2
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.2
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 2.0.7 All 340 releases
profile-builder / form-builder / form-builder-init.php

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

291 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Form Builder bootstrap and admin chrome.
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) exit;
7
8 /**
9 * Canonical "form builder is loaded" sentinel for separately distributed integrations.
10 * Test this name — not an arbitrary wppb_fb_* helper (renames would break the guard).
11 *
12 * @return bool Always true; the function's existence is the signal.
13 */
14 function wppb_fb_loaded() {
15 return true;
16 }
17
18 // 1. Core Logic & CPTs
19 include_once( __DIR__ . '/class-field-registry.php' );
20 include_once( __DIR__ . '/form-builder-licensing.php' );
21 include_once( __DIR__ . '/form-builder-editor-mode.php' );
22 include_once( __DIR__ . '/form-builder-cpts.php' );
23 include_once( __DIR__ . '/form-builder-hooks.php' );
24 include_once( __DIR__ . '/form-builder-defaults.php' );
25
26 include_once( __DIR__ . '/form-builder-meta-names.php' );
27 include_once( __DIR__ . '/form-builder-row-projection.php' );
28 include_once( __DIR__ . '/form-builder-rest-mirror.php' );
29 include_once( __DIR__ . '/form-builder-projection.php' );
30 include_once( __DIR__ . '/form-builder-rest-routes.php' );
31 include_once( __DIR__ . '/form-builder-registration.php' );
32 include_once( __DIR__ . '/form-builder-editor-chrome.php' );
33 include_once( __DIR__ . '/form-builder-preview.php' );
34
35 // Integrations ship with the form builder (free vs paid update skew). Separate
36 // plugins (pms.php) load unconditionally — they may init after PB.
37 include_once( __DIR__ . '/integrations/pms.php' );
38
39 /**
40 * Add-on slug => PHP probe (function_exists/defined). Must be long-lived and live
41 * in the same branch that used to load the bridge — never a JS name.
42 *
43 * @return array<string,string> Slug => function or constant name.
44 */
45 function wppb_fb_addon_integrations() {
46 return array(
47 'campaign-monitor' => 'WPPBCMI_IN_PLUGIN_DIR',
48 'edit-profile-approved-by-admin' => 'WPPBEPAA_IN_PLUGIN_DIR',
49 'field-visibility' => 'wppb_in_field_visibility_get_extra_fields',
50 'form-fields-in-columns' => 'wppb_in_ffc_add_meta_boxes',
51 'mailchimp-integration' => 'WPPBMCI_IN_PLUGIN_DIR',
52 'mailpoet-integration' => 'wppb_in_mpi_get_lists',
53 'multi-step-forms' => 'wppb_in_msf_add_meta_boxes',
54 'progress-bar' => 'WPPBPB_PLUGIN_DIR',
55 'woocommerce' => 'wppb_in_woo_get_billing_fields',
56 'custom-css-classes-on-fields' => 'wppb_ccc_scripts',
57 'gdpr-communication-preferences' => 'PBGCP_ADD_ON_DIR',
58 'maximum-character-length' => 'wppb_mcl_scripts',
59 );
60 }
61
62 /**
63 * Whether an integration's add-on is loaded, per its registry probe.
64 *
65 * @param string $slug Add-on slug from wppb_fb_addon_integrations().
66 * @return bool
67 */
68 function wppb_fb_addon_integration_active( $slug ) {
69 $probes = wppb_fb_addon_integrations();
70 if ( ! isset( $probes[ $slug ] ) ) {
71 return false;
72 }
73 $probe = $probes[ $slug ];
74 return function_exists( $probe ) || defined( $probe );
75 }
76
77 /** Include each add-on integration whose probe passes. */
78 function wppb_fb_load_addon_integrations() {
79 $paid = defined( 'WPPB_PAID_PLUGIN_DIR' ) ? WPPB_PAID_PLUGIN_DIR : '';
80
81 foreach ( array_keys( wppb_fb_addon_integrations() ) as $slug ) {
82 if ( ! wppb_fb_addon_integration_active( $slug ) ) {
83 continue;
84 }
85
86 // Skip if paid plugin already ships its own bridge (fatal redeclare otherwise).
87 if ( '' !== $paid && file_exists( $paid . '/add-ons-advanced/' . $slug . '/form-builder-bridge.php' ) ) {
88 continue;
89 }
90
91 include_once( __DIR__ . '/integrations/' . $slug . '.php' );
92 }
93 }
94
95 // plugins_loaded@11: file loads at priority 10 before add-ons; direct call if late.
96 if ( doing_action( 'plugins_loaded' ) || ! did_action( 'plugins_loaded' ) ) {
97 add_action( 'plugins_loaded', 'wppb_fb_load_addon_integrations', 11 );
98 } else {
99 wppb_fb_load_addon_integrations();
100 }
101
102 // require_once: hooks.php registers wppb_change_form_fields unconditionally.
103 require_once( __DIR__ . '/multiple-forms/multiple-forms.php' );
104
105 /**
106 * Forms menu plan from CPT editor modes: unified entry replaces RF auto when modern;
107 * remove EPF auto only when unified can host its tab.
108 *
109 * @param bool $rf_modern RF CPT uses the block editor.
110 * @param bool $epf_modern EPF CPT uses the block editor.
111 * @return array{add_unified:bool,remove_rf_auto:bool,remove_epf_auto:bool}
112 */
113 function wppb_fb_forms_menu_plan( $rf_modern, $epf_modern ) {
114 $add_unified = (bool) $rf_modern;
115 return array(
116 'add_unified' => $add_unified,
117 'remove_rf_auto' => (bool) $rf_modern,
118 'remove_epf_auto' => ( (bool) $epf_modern ) && $add_unified,
119 );
120 }
121
122 add_action( 'admin_menu', 'wppb_fb_register_forms_menu', 15 );
123 function wppb_fb_register_forms_menu() {
124 $plan = wppb_fb_forms_menu_plan(
125 wppb_fb_is_active_for( 'wppb-rf-cpt' ),
126 wppb_fb_is_active_for( 'wppb-epf-cpt' )
127 );
128
129 // Remove before add: Forms reuses the RF list slug.
130 if ( $plan['remove_rf_auto'] ) {
131 remove_submenu_page( 'profile-builder', 'edit.php?post_type=wppb-rf-cpt' );
132 }
133 if ( $plan['remove_epf_auto'] ) {
134 remove_submenu_page( 'profile-builder', 'edit.php?post_type=wppb-epf-cpt' );
135 }
136
137 if ( $plan['add_unified'] ) {
138 add_submenu_page(
139 'profile-builder',
140 __( 'Forms', 'profile-builder' ),
141 __( 'Forms', 'profile-builder' ),
142 'manage_options',
143 'edit.php?post_type=wppb-rf-cpt'
144 );
145 }
146
147 // manage-fields stays in $submenu (CSS-hidden): remove_submenu_page breaks the hookname.
148 }
149
150 add_action( 'admin_menu', 'wppb_fb_reorder_forms_submenu', 999 );
151 function wppb_fb_reorder_forms_submenu() {
152 global $submenu;
153 if ( empty( $submenu['profile-builder'] ) || ! is_array( $submenu['profile-builder'] ) ) {
154 return;
155 }
156
157 $forms_index = null;
158 $basic_info_index = null;
159 foreach ( $submenu['profile-builder'] as $key => $item ) {
160 if ( ! isset( $item[2] ) ) continue;
161 if ( $item[2] === 'edit.php?post_type=wppb-rf-cpt' ) $forms_index = $key;
162 if ( $item[2] === 'profile-builder-basic-info' ) $basic_info_index = $key;
163 }
164 if ( $forms_index === null || $basic_info_index === null ) {
165 return;
166 }
167
168 $forms_entry = $submenu['profile-builder'][ $forms_index ];
169 unset( $submenu['profile-builder'][ $forms_index ] );
170
171 $reordered = array();
172 foreach ( $submenu['profile-builder'] as $item ) {
173 $reordered[] = $item;
174 if ( isset( $item[2] ) && $item[2] === 'profile-builder-basic-info' ) {
175 $reordered[] = $forms_entry;
176 }
177 }
178 $submenu['profile-builder'] = $reordered;
179 }
180
181 /**
182 * Strip slugdiv on classic form CPT screens (slug is internal; editing breaks refs).
183 */
184 add_action( 'add_meta_boxes', 'wppb_fb_remove_slug_metabox_from_form_cpts', 100 );
185 function wppb_fb_remove_slug_metabox_from_form_cpts() {
186 remove_meta_box( 'slugdiv', 'wppb-rf-cpt', 'normal' );
187 remove_meta_box( 'slugdiv', 'wppb-epf-cpt', 'normal' );
188 }
189
190 add_action( 'admin_head', 'wppb_fb_hide_legacy_manage_fields_menu_item' );
191 function wppb_fb_hide_legacy_manage_fields_menu_item() {
192 ?>
193 <style id="wppb-fb-hide-manage-fields-menu">
194 #adminmenu #toplevel_page_profile-builder .wp-submenu a[href$="admin.php?page=manage-fields"],
195 #adminmenu #toplevel_page_profile-builder .wp-submenu a[href$="page=manage-fields"] {
196 display: none;
197 }
198 </style>
199 <?php
200 }
201
202 /** Keep Forms menu highlighted on form CPT screens. */
203 add_filter( 'parent_file', 'wppb_fb_keep_forms_menu_active' );
204 function wppb_fb_keep_forms_menu_active( $parent_file ) {
205 global $submenu_file, $current_screen;
206
207 if ( ! empty( $current_screen ) && in_array( $current_screen->post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true ) ) {
208 $submenu_file = 'edit.php?post_type=wppb-rf-cpt';
209 return 'profile-builder';
210 }
211
212 return $parent_file;
213 }
214
215 /** Whether the current screen is a form CPT list table. */
216 function wppb_fb_is_forms_list_screen() {
217 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
218 return ! empty( $screen )
219 && $screen->base === 'edit'
220 && in_array( $screen->post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true );
221 }
222
223 /**
224 * RF / EPF tabs under the header banner (priority 11, after banner at 10).
225 */
226 add_action( 'in_admin_header', 'wppb_fb_render_forms_tabs', 11 );
227 function wppb_fb_render_forms_tabs() {
228 if ( ! wppb_fb_is_forms_list_screen() ) {
229 return;
230 }
231
232 $screen = get_current_screen();
233 $tabs = array(
234 'wppb-rf-cpt' => __( 'Registration Forms', 'profile-builder' ),
235 'wppb-epf-cpt' => __( 'Edit Profile Forms', 'profile-builder' ),
236 );
237 ?>
238 <nav class="nav-tab-wrapper cozmoslabs-nav-tab-wrapper wppb-forms-header-tabs">
239 <?php foreach ( $tabs as $post_type => $label ) : ?>
240 <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=' . $post_type ) ); ?>" class="nav-tab <?php echo ( $screen->post_type === $post_type ? 'nav-tab-active' : '' ); ?>">
241 <?php echo esc_html( $label ); ?>
242 </a>
243 <?php endforeach; ?>
244 </nav>
245 <?php
246 }
247
248 /** Body class for list-screen reskin CSS. */
249 add_filter( 'admin_body_class', 'wppb_fb_forms_list_body_class' );
250 function wppb_fb_forms_list_body_class( $classes ) {
251 if ( wppb_fb_is_forms_list_screen() ) {
252 $classes .= ' wppb-forms-list-screen';
253 }
254 return $classes;
255 }
256
257 /** "Default" post state on default forms in the list tables. */
258 add_filter( 'display_post_states', 'wppb_fb_forms_default_post_state', 10, 2 );
259 function wppb_fb_forms_default_post_state( $post_states, $post ) {
260 if ( in_array( $post->post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true )
261 && get_post_meta( $post->ID, '_pbform_is_default', true ) === '1' ) {
262 $post_states['wppb_fb_default_form'] = __( 'Default', 'profile-builder' );
263 }
264 return $post_states;
265 }
266
267 /** Remove Quick Edit / bulk Edit (they expose the internal slug). */
268 add_filter( 'post_row_actions', 'wppb_fb_forms_remove_quick_edit', 10, 2 );
269 function wppb_fb_forms_remove_quick_edit( $actions, $post ) {
270 if ( in_array( $post->post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true ) ) {
271 unset( $actions['inline hide-if-no-js'] );
272 }
273 return $actions;
274 }
275
276 add_filter( 'bulk_actions-edit-wppb-rf-cpt', 'wppb_fb_forms_remove_bulk_edit' );
277 add_filter( 'bulk_actions-edit-wppb-epf-cpt', 'wppb_fb_forms_remove_bulk_edit' );
278 function wppb_fb_forms_remove_bulk_edit( $actions ) {
279 unset( $actions['edit'] );
280 return $actions;
281 }
282
283 /** Wrap Published status for list-table reskin CSS. */
284 add_filter( 'post_date_column_status', 'wppb_fb_forms_date_column_status', 10, 2 );
285 function wppb_fb_forms_date_column_status( $status, $post ) {
286 if ( in_array( $post->post_type, array( 'wppb-rf-cpt', 'wppb-epf-cpt' ), true ) && $post->post_status === 'publish' ) {
287 return '<span class="wppb-forms-status-published">' . esc_html( $status ) . '</span>';
288 }
289 return $status;
290 }
291