PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.15.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.15.0
2.15.0 2.14.0 2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 All 82 releases
← All changes | includes/ajax/settings.php +845 -0 2.7.4 → 2.15.0 View file →
@@ -1,0 +1,845 @@
1 +<?php
2 +
3 +namespace ABlocks\Ajax;
4 +
5 +if ( ! defined( 'ABSPATH' ) ) {
6 + exit;
7 +}
8 +
9 +use ABlocks\Classes\AbstractAjaxHandler;
10 +use ABlocks\Classes\Sanitizer;
11 +use ABlocks\Classes\Breakpoints;
12 +use ABlocks\Helper;
13 +use ABlocks\Admin\Settings\Base as BaseSettings;
14 +use ABlocks\Permissions\SettingsGuard;
15 +
16 +class Settings extends AbstractAjaxHandler {
17 + public function __construct() {
18 + $this->actions = array(
19 + 'get_blocks_visibility' => array(
20 + 'callback' => array( $this, 'get_blocks_visibility' ),
21 + 'capability' => 'ablocks_manage_settings'
22 + ),
23 + 'save_block_visibility' => array(
24 + 'callback' => array( $this, 'save_block_visibility' ),
25 + 'capability' => 'ablocks_manage_settings',
26 + 'fields' => array(
27 + 'block_name' => 'string',
28 + 'status' => 'boolean',
29 + )
30 + ),
31 + 'save_bulk_block_visibility' => array(
32 + 'callback' => array( $this, 'save_bulk_block_visibility' ),
33 + 'capability' => 'ablocks_manage_settings',
34 + 'fields' => array(
35 + 'blocks' => 'json',
36 + )
37 + ),
38 + 'get_settings' => array(
39 + 'callback' => array( $this, 'get_settings' ),
40 + 'capability' => 'ablocks_access',
41 + ),
42 + 'save_settings' => array(
43 + 'callback' => array( $this, 'save_settings' ),
44 + 'capability' => 'ablocks_save_settings',
45 + 'fields' => array(
46 + 'default_container_width' => 'integer',
47 + 'container_padding' => 'integer',
48 + 'container_element_gap' => 'integer',
49 + 'enabled_assets_file_generation' => 'boolean',
50 + 'enabled_block_copy_paste_style' => 'boolean',
51 + 'lock_global_typography' => 'boolean',
52 + 'lock_global_typography_strict' => 'boolean',
53 + 'lock_global_colors' => 'boolean',
54 + 'enabled_load_google_font_locally' => 'boolean',
55 + 'enabled_only_selected_fonts' => 'boolean',
56 + 'font_metric_fallback' => 'boolean',
57 + 'enabled_coming_soon_page' => 'boolean',
58 + 'coming_soon_page' => 'integer',
59 + 'enabled_maintenance_page' => 'boolean',
60 + 'maintenance_page' => 'integer',
61 + 'login_page' => 'integer',
62 + 'registration_page' => 'integer',
63 + 'forget_password_page' => 'integer',
64 + 'frontend_dashboard_page' => 'string',
65 + 'mailchimp_api_key' => 'string',
66 + 'drip_api_key' => 'string',
67 + 'getresponse_api_key' => 'string',
68 + 'convertkit_api_key' => 'string',
69 + 'mailerlite_api_key' => 'string',
70 + // Performance Suite
71 + 'perf_lazy_images' => 'boolean',
72 + 'perf_lcp_eager_count' => 'integer',
73 + 'perf_image_dimensions' => 'boolean',
74 + 'perf_responsive_images' => 'boolean',
75 + 'perf_preload_lcp' => 'boolean',
76 + 'perf_touch_targets' => 'boolean',
77 + 'perf_inline_css' => 'boolean',
78 + 'perf_async_css' => 'boolean',
79 + 'perf_critical_css' => 'boolean',
80 + 'perf_defer_js' => 'boolean',
81 + 'perf_delay_js' => 'boolean',
82 + 'perf_delay_js_timeout' => 'integer',
83 + 'perf_disable_emojis' => 'boolean',
84 + 'perf_disable_embeds' => 'boolean',
85 + 'perf_disable_dashicons' => 'boolean',
86 + 'perf_disable_jquery_migrate' => 'boolean',
87 + 'perf_control_heartbeat' => 'boolean',
88 + 'perf_heartbeat_frequency' => 'integer',
89 + // Editor paste
90 + 'paste_google_docs' => 'boolean',
91 + 'paste_convert_webp' => 'boolean',
92 + 'paste_webp_quality' => 'integer',
93 + // Responsive breakpoints
94 + 'breakpoint_tablet' => 'integer',
95 + 'breakpoint_mobile' => 'integer',
96 + 'breakpoint_mode' => 'string',
97 + 'breakpoint_custom' => 'json',
98 + // Performance Suite — full-page cache.
99 + 'perf_page_cache' => 'boolean',
100 + 'perf_page_cache_scope' => 'string',
101 + 'perf_page_cache_ttl' => 'integer',
102 + 'perf_page_cache_gzip' => 'boolean',
103 + 'perf_page_cache_prewarm' => 'boolean',
104 + 'perf_page_cache_mobile_variant' => 'boolean',
105 + 'perf_page_cache_crawler' => 'boolean',
106 + 'perf_page_cache_crawl_batch' => 'integer',
107 + 'perf_consolidate_css' => 'boolean',
108 + 'perf_consolidate_css_min' => 'integer',
109 + 'perf_fragment_cache' => 'boolean',
110 + 'perf_fragment_cache_ttl' => 'integer',
111 + 'perf_template_cache' => 'boolean',
112 + 'perf_template_cache_ttl' => 'integer',
113 + 'perf_image_optimize_on_upload' => 'boolean',
114 + 'perf_image_level' => 'string',
115 + 'perf_image_webp' => 'boolean',
116 + 'perf_image_quarantine_autodelete' => 'boolean',
117 + 'perf_image_quarantine_days' => 'integer',
118 + 'perf_image_require_filename' => 'boolean',
119 + 'perf_image_require_alt' => 'boolean',
120 + // Marketing — query param passthrough
121 + 'param_passthrough_enabled' => 'boolean',
122 + 'param_passthrough_keys' => 'string',
123 + 'param_passthrough_match' => 'string',
124 + 'param_passthrough_class' => 'string',
125 + 'param_passthrough_keyword' => 'string',
126 + 'param_passthrough_persist' => 'boolean',
127 + 'param_passthrough_cookie_days' => 'integer',
128 + // global color & typography
129 + 'global_color' => 'json',
130 + 'global_typography' => 'json',
131 + 'global_font_family_fallback' => 'string',
132 + 'global_body_text_color' => 'string',
133 + 'global_body_typography' => 'json',
134 + 'global_body_paragraph_space' => 'json',
135 + 'global_link_color' => 'string',
136 + 'global_link_hover_color' => 'string',
137 + 'global_link_typography' => 'json',
138 + 'global_link_hover_typography' => 'json',
139 + 'global_h1_color' => 'string',
140 + 'global_h1_typography' => 'json',
141 + 'global_h2_color' => 'string',
142 + 'global_h2_typography' => 'json',
143 + 'global_h3_color' => 'string',
144 + 'global_h3_typography' => 'json',
145 + 'global_h4_color' => 'string',
146 + 'global_h4_typography' => 'json',
147 + 'global_h5_color' => 'string',
148 + 'global_h5_typography' => 'json',
149 + 'global_h6_color' => 'string',
150 + 'global_h6_typography' => 'json',
151 + )
152 + ),
153 + 'fetch_posts' => array(
154 + 'callback' => array( $this, 'fetch_posts' ),
155 + 'capability' => 'ablocks_access',
156 + 'fields' => array(
157 + 'postId' => 'integer',
158 + 'postType' => 'string',
159 + 'keyword' => 'string',
160 + )
161 + ),
162 + 'get_fronted_dashboard_pages' => array(
163 + 'callback' => array( $this, 'get_fronted_dashboard_pages' ),
164 + 'capability' => 'ablocks_manage_settings',
165 + ),
166 + 'create_fronted_dashboard_page' => array(
167 + 'callback' => array( $this, 'create_fronted_dashboard_page' ),
168 + 'capability' => 'ablocks_manage_settings',
169 + 'fields' => [
170 + 'label' => 'string',
171 + 'slug' => 'string',
172 + 'icon' => 'string',
173 + 'class_name' => 'string',
174 + 'priority' => 'integer',
175 + 'parent_id' => 'integer',
176 + ]
177 + ),
178 + 'create_fronted_dashboard_link' => array(
179 + 'callback' => array( $this, 'create_fronted_dashboard_link' ),
180 + 'capability' => 'ablocks_manage_settings',
181 + 'fields' => [
182 + 'label' => 'string',
183 + 'link' => 'string',
184 + 'icon' => 'string',
185 + 'class_name' => 'string',
186 + 'priority' => 'integer',
187 + 'parent_id' => 'string',
188 + ]
189 + ),
190 + 'edit_fronted_dashboard_link' => array(
191 + 'callback' => array( $this, 'edit_fronted_dashboard_link' ),
192 + 'capability' => 'ablocks_manage_settings',
193 + 'fields' => [
194 + 'label' => 'string',
195 + 'link' => 'string',
196 + 'icon' => 'string',
197 + 'class_name' => 'string',
198 + 'priority' => 'integer',
199 + 'page_id' => 'string',
200 + ]
201 + ),
202 + 'delete_fronted_dashboard_link' => array(
203 + 'callback' => array( $this, 'delete_fronted_dashboard_link' ),
204 + 'capability' => 'ablocks_manage_settings',
205 + 'fields' => array(
206 + 'page_id' => 'string',
207 + )
208 + ),
209 + 'edit_fronted_dashboard_page' => array(
210 + 'callback' => array( $this, 'edit_fronted_dashboard_page' ),
211 + 'capability' => 'ablocks_manage_settings',
212 + 'fields' => [
213 + 'label' => 'string',
214 + 'slug' => 'string',
215 + 'icon' => 'string',
216 + 'class_name' => 'string',
217 + 'priority' => 'integer',
218 + 'parent_id' => 'integer',
219 + 'page_id' => 'integer',
220 + ]
221 + ),
222 + 'move_fronted_dashboard_page' => array(
223 + 'callback' => array( $this, 'move_fronted_dashboard_page' ),
224 + 'capability' => 'ablocks_manage_settings',
225 + 'fields' => [
226 + 'reordered_items' => 'string',
227 + ]
228 + ),
229 + 'delete_fronted_dashboard_page' => array(
230 + 'callback' => array( $this, 'delete_fronted_dashboard_page' ),
231 + 'capability' => 'ablocks_manage_settings',
232 + 'fields' => array(
233 + 'slug' => 'string',
234 + 'page_id' => 'integer',
235 + )
236 + ),
237 + );
238 + }
239 +
240 + public function get_blocks_visibility() {
241 + global $ablocks_blocks;
242 + wp_send_json_success( $ablocks_blocks );
243 + }
244 +
245 + public function save_block_visibility( $payload ) {
246 + $block_name = $payload['block_name'];
247 + $status = $payload['status'];
248 +
249 + $json_payload = Sanitizer::sanitize_payload([
250 + 'required_plugin' => 'json',
251 + ], $payload);
252 +
253 + $required_plugin = $json_payload['required_plugin'];
254 +
255 + if ( empty( $block_name ) ) {
256 + wp_send_json_error( __( 'Block Name missing', 'ablocks' ) );
257 + }
258 +
259 + if ( $status && $required_plugin ) {
260 + if ( $required_plugin && is_array( $required_plugin ) ) {
261 + foreach ( $required_plugin as $plugin ) {
262 + if ( ! Helper::is_plugin_active( sanitize_text_field( $plugin['plugin_dir_path'] ) ) ) {
263 + $error_message = sprintf( '%s Plugin is required to activate %s block.', $plugin['plugin_name'], $block_name );
264 + wp_send_json_error( $error_message );
265 + }
266 + }
267 + }
268 + }
269 +
270 + // Saved Data
271 + $saved_blocks = (array) json_decode( get_option( ABLOCKS_BLOCKS_VISIBILITY_SETTINGS_NAME ), true );
272 + $saved_blocks[ $block_name ] = $status;
273 + update_option( ABLOCKS_BLOCKS_VISIBILITY_SETTINGS_NAME, wp_json_encode( $saved_blocks ) );
274 + // Fire Addon Action
275 + if ( $status ) {
276 + do_action( "ablocks/block/activated_{$block_name}", $status );
277 + } else {
278 + do_action( "ablocks/block/deactivated_{$block_name}", $status );
279 + }
280 + wp_send_json_success( $saved_blocks );
281 + }
282 + public function save_bulk_block_visibility( $payload ) {
283 + $blocks = wp_list_pluck( \json_decode( $payload['blocks'], true ), 'status', 'block_name' );
284 + $saved_blocks = (array) json_decode( get_option( ABLOCKS_BLOCKS_VISIBILITY_SETTINGS_NAME ), true );
285 + $updated_settings = wp_parse_args( $blocks, $saved_blocks );
286 + update_option( ABLOCKS_BLOCKS_VISIBILITY_SETTINGS_NAME, wp_json_encode( $updated_settings ) );
287 + wp_send_json_success( $updated_settings );
288 + }
289 + public function get_settings() {
290 + $settings = BaseSettings::get_saved_data();
291 + wp_send_json_success( $settings );
292 + }
293 +
294 + public function save_settings( $payload ) {
295 + // The design system, the performance suite and site configuration are
296 + // three separate permissions but one endpoint. Keys this user may not
297 + // change are rewritten back to what is already saved, so the save
298 + // succeeds and simply leaves them alone.
299 + $payload = SettingsGuard::filter_payload( $payload );
300 +
301 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
302 + do_action( 'ablocks/before_save_settings', $payload, 'base' );
303 + $json_payload = Sanitizer::sanitize_payload([
304 + 'selected_fonts' => 'json',
305 + 'perf_page_cache_query_args' => 'json',
306 + 'perf_page_cache_exclusions' => 'json',
307 + 'global_color' => 'json',
308 + 'global_typography' => 'json',
309 + 'global_body_typography' => 'json',
310 + 'global_body_paragraph_space' => 'json',
311 + 'global_link_typography' => 'json',
312 + 'global_link_hover_typography' => 'json',
313 + 'global_h1_typography' => 'json',
314 + 'global_h2_typography' => 'json',
315 + 'global_h3_typography' => 'json',
316 + 'global_h4_typography' => 'json',
317 + 'global_h5_typography' => 'json',
318 + 'global_h6_typography' => 'json',
319 + 'breakpoint_custom' => 'json',
320 + ], $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
321 +
322 + // The JSON fields are read straight from $_POST rather than the sanitized
323 + // payload, so they need the same guard — the global colour and typography
324 + // presets live in here, and they are the design system.
325 + $json_payload = SettingsGuard::filter_payload( $json_payload );
326 +
327 + // Breakpoints are only written when the request carries them, so a save
328 + // that omits them keeps the stored list rather than resetting it.
329 + $breakpoints = [];
330 + foreach ( [ 'breakpoint_tablet', 'breakpoint_mobile' ] as $key ) {
331 + if ( isset( $payload[ $key ] ) && $payload[ $key ] > 0 ) {
332 + $breakpoints[ $key ] = $payload[ $key ];
333 + }
334 + }
335 + if ( isset( $payload['breakpoint_mode'] ) ) {
336 + $breakpoints['breakpoint_mode'] = 'strict' === $payload['breakpoint_mode'] ? 'strict' : 'cascade';
337 + }
338 + if ( isset( $json_payload['breakpoint_custom'] ) && is_array( $json_payload['breakpoint_custom'] ) ) {
339 + $breakpoints['breakpoint_custom'] = Breakpoints::sanitize( $json_payload['breakpoint_custom'] );
340 + }
341 +
342 + $default = BaseSettings::get_default_data();
343 + $is_update = BaseSettings::save_settings( $breakpoints + [
344 + 'default_container_width' => $payload['default_container_width'] ?? $default['default_container_width'],
345 + 'container_padding' => $payload['container_padding'] ?? $default['container_padding'],
346 + 'container_element_gap' => $payload['container_element_gap'] ?? $default['container_element_gap'],
347 + 'enabled_assets_file_generation' => $payload['enabled_assets_file_generation'] ?? $default['enabled_assets_file_generation'],
348 + 'enabled_block_copy_paste_style' => $payload['enabled_block_copy_paste_style'] ?? $default['enabled_block_copy_paste_style'],
349 + 'lock_global_typography' => $payload['lock_global_typography'] ?? $default['lock_global_typography'],
350 + 'lock_global_typography_strict' => $payload['lock_global_typography_strict'] ?? $default['lock_global_typography_strict'],
351 + 'lock_global_colors' => $payload['lock_global_colors'] ?? $default['lock_global_colors'],
352 + 'enabled_load_google_font_locally' => $payload['enabled_load_google_font_locally'] ?? $default['enabled_load_google_font_locally'],
353 + 'enabled_only_selected_fonts' => $payload['enabled_only_selected_fonts'] ?? $default['enabled_only_selected_fonts'],
354 + 'selected_fonts' => $json_payload['selected_fonts'] ?? $default['selected_fonts'],
355 + 'font_metric_fallback' => $payload['font_metric_fallback'] ?? $default['font_metric_fallback'],
356 + // Performance Suite — platform optimizations.
357 + 'perf_disable_emojis' => $payload['perf_disable_emojis'] ?? $default['perf_disable_emojis'],
358 + 'perf_disable_embeds' => $payload['perf_disable_embeds'] ?? $default['perf_disable_embeds'],
359 + 'perf_disable_dashicons' => $payload['perf_disable_dashicons'] ?? $default['perf_disable_dashicons'],
360 + 'perf_disable_jquery_migrate' => $payload['perf_disable_jquery_migrate'] ?? $default['perf_disable_jquery_migrate'],
361 + 'perf_control_heartbeat' => $payload['perf_control_heartbeat'] ?? $default['perf_control_heartbeat'],
362 + 'perf_heartbeat_frequency' => $payload['perf_heartbeat_frequency'] ?? $default['perf_heartbeat_frequency'],
363 + 'perf_delay_js' => $payload['perf_delay_js'] ?? $default['perf_delay_js'],
364 + 'perf_delay_js_timeout' => $payload['perf_delay_js_timeout'] ?? $default['perf_delay_js_timeout'],
365 + 'perf_lazy_images' => $payload['perf_lazy_images'] ?? $default['perf_lazy_images'],
366 + 'perf_lcp_eager_count' => $payload['perf_lcp_eager_count'] ?? $default['perf_lcp_eager_count'],
367 + 'perf_image_dimensions' => $payload['perf_image_dimensions'] ?? $default['perf_image_dimensions'],
368 + 'perf_responsive_images' => $payload['perf_responsive_images'] ?? $default['perf_responsive_images'],
369 + 'perf_preload_lcp' => $payload['perf_preload_lcp'] ?? $default['perf_preload_lcp'],
370 + 'perf_touch_targets' => $payload['perf_touch_targets'] ?? $default['perf_touch_targets'],
371 + 'perf_inline_css' => $payload['perf_inline_css'] ?? $default['perf_inline_css'],
372 + 'perf_async_css' => $payload['perf_async_css'] ?? $default['perf_async_css'],
373 + 'perf_critical_css' => $payload['perf_critical_css'] ?? $default['perf_critical_css'],
374 + 'perf_defer_js' => $payload['perf_defer_js'] ?? $default['perf_defer_js'],
375 + // Editor paste.
376 + 'paste_google_docs' => $payload['paste_google_docs'] ?? $default['paste_google_docs'],
377 + 'paste_convert_webp' => $payload['paste_convert_webp'] ?? $default['paste_convert_webp'],
378 + 'paste_webp_quality' => $payload['paste_webp_quality'] ?? $default['paste_webp_quality'],
379 + // Performance Suite — full-page cache.
380 + 'perf_page_cache' => $payload['perf_page_cache'] ?? $default['perf_page_cache'],
381 + 'perf_page_cache_scope' => $payload['perf_page_cache_scope'] ?? $default['perf_page_cache_scope'],
382 + 'perf_page_cache_ttl' => $payload['perf_page_cache_ttl'] ?? $default['perf_page_cache_ttl'],
383 + 'perf_page_cache_gzip' => $payload['perf_page_cache_gzip'] ?? $default['perf_page_cache_gzip'],
384 + 'perf_page_cache_prewarm' => $payload['perf_page_cache_prewarm'] ?? $default['perf_page_cache_prewarm'],
385 + 'perf_page_cache_mobile_variant' => $payload['perf_page_cache_mobile_variant'] ?? $default['perf_page_cache_mobile_variant'],
386 + 'perf_page_cache_crawler' => $payload['perf_page_cache_crawler'] ?? $default['perf_page_cache_crawler'],
387 + 'perf_page_cache_crawl_batch' => $payload['perf_page_cache_crawl_batch'] ?? $default['perf_page_cache_crawl_batch'],
388 + 'perf_page_cache_query_args' => $json_payload['perf_page_cache_query_args'] ?? $default['perf_page_cache_query_args'],
389 + 'perf_page_cache_exclusions' => $json_payload['perf_page_cache_exclusions'] ?? $default['perf_page_cache_exclusions'],
390 + 'perf_consolidate_css' => $payload['perf_consolidate_css'] ?? $default['perf_consolidate_css'],
391 + 'perf_consolidate_css_min' => $payload['perf_consolidate_css_min'] ?? $default['perf_consolidate_css_min'],
392 + 'perf_fragment_cache' => $payload['perf_fragment_cache'] ?? $default['perf_fragment_cache'],
393 + 'perf_fragment_cache_ttl' => $payload['perf_fragment_cache_ttl'] ?? $default['perf_fragment_cache_ttl'],
394 + 'perf_template_cache' => $payload['perf_template_cache'] ?? $default['perf_template_cache'],
395 + 'perf_template_cache_ttl' => $payload['perf_template_cache_ttl'] ?? $default['perf_template_cache_ttl'],
396 + 'perf_image_optimize_on_upload' => $payload['perf_image_optimize_on_upload'] ?? $default['perf_image_optimize_on_upload'],
397 + 'perf_image_level' => $payload['perf_image_level'] ?? $default['perf_image_level'],
398 + 'perf_image_webp' => $payload['perf_image_webp'] ?? $default['perf_image_webp'],
399 + 'perf_image_quarantine_autodelete' => $payload['perf_image_quarantine_autodelete'] ?? $default['perf_image_quarantine_autodelete'],
400 + 'perf_image_quarantine_days' => $payload['perf_image_quarantine_days'] ?? $default['perf_image_quarantine_days'],
401 + 'perf_image_require_filename' => $payload['perf_image_require_filename'] ?? $default['perf_image_require_filename'],
402 + 'perf_image_require_alt' => $payload['perf_image_require_alt'] ?? $default['perf_image_require_alt'],
403 + // Marketing — query param passthrough
404 + 'param_passthrough_enabled' => $payload['param_passthrough_enabled'] ?? $default['param_passthrough_enabled'],
405 + 'param_passthrough_keys' => $payload['param_passthrough_keys'] ?? $default['param_passthrough_keys'],
406 + 'param_passthrough_match' => $payload['param_passthrough_match'] ?? $default['param_passthrough_match'],
407 + 'param_passthrough_class' => $payload['param_passthrough_class'] ?? $default['param_passthrough_class'],
408 + 'param_passthrough_keyword' => $payload['param_passthrough_keyword'] ?? $default['param_passthrough_keyword'],
409 + 'param_passthrough_persist' => $payload['param_passthrough_persist'] ?? $default['param_passthrough_persist'],
410 + 'param_passthrough_cookie_days' => $payload['param_passthrough_cookie_days'] ?? $default['param_passthrough_cookie_days'],
411 + 'enabled_coming_soon_page' => $payload['enabled_coming_soon_page'] ?? $default['enabled_coming_soon_page'],
412 + 'coming_soon_page' => $payload['coming_soon_page'] ?? $default['coming_soon_page'],
413 + 'enabled_maintenance_page' => $payload['enabled_maintenance_page'] ?? $default['enabled_maintenance_page'],
414 + 'maintenance_page' => $payload['maintenance_page'] ?? $default['maintenance_page'],
415 + 'frontend_dashboard_page' => $payload['frontend_dashboard_page'] ?? $default['frontend_dashboard_page'],
416 + 'login_page' => $payload['login_page'] ?? $default['login_page'],
417 + 'registration_page' => $payload['registration_page'] ?? $default['registration_page'],
418 + 'forget_password_page' => $payload['forget_password_page'] ?? $default['forget_password_page'],
419 +
420 + 'mailchimp_api_key' => $payload['mailchimp_api_key'] ?? '',
421 + 'drip_api_key' => $payload['drip_api_key'] ?? '',
422 + 'getresponse_api_key' => $payload['getresponse_api_key'] ?? '',
423 + 'convertkit_api_key' => $payload['convertkit_api_key'] ?? '',
424 + 'mailerlite_api_key' => $payload['mailerlite_api_key'] ?? '',
425 + // Global Color & Typography
426 + 'global_color' => $json_payload['global_color'] ?? [],
427 + 'global_typography' => $json_payload['global_typography'] ?? [],
428 + 'global_font_family_fallback' => $payload['global_font_family_fallback'] ?? '',
429 + 'global_body_typography' => $json_payload['global_body_typography'] ?? [],
430 + 'global_body_paragraph_space' => $json_payload['global_body_paragraph_space'] ?? [],
431 + 'global_link_typography' => $json_payload['global_link_typography'] ?? [],
432 + 'global_link_hover_typography' => $json_payload['global_link_hover_typography'] ?? [],
433 + 'global_h1_typography' => $json_payload['global_h1_typography'] ?? [],
434 + 'global_h2_typography' => $json_payload['global_h2_typography'] ?? [],
435 + 'global_h3_typography' => $json_payload['global_h3_typography'] ?? [],
436 + 'global_h4_typography' => $json_payload['global_h4_typography'] ?? [],
437 + 'global_h5_typography' => $json_payload['global_h5_typography'] ?? [],
438 + 'global_h6_typography' => $json_payload['global_h6_typography'] ?? [],
439 + 'global_body_text_color' => $payload['global_body_text_color'] ?? '',
440 + 'global_link_color' => $payload['global_link_color'] ?? '',
441 + 'global_link_hover_color' => $payload['global_link_hover_color'] ?? '',
442 + 'global_h1_color' => $payload['global_h1_color'] ?? '',
443 + 'global_h2_color' => $payload['global_h2_color'] ?? '',
444 + 'global_h3_color' => $payload['global_h3_color'] ?? '',
445 + 'global_h4_color' => $payload['global_h4_color'] ?? '',
446 + 'global_h5_color' => $payload['global_h5_color'] ?? '',
447 + 'global_h6_color' => $payload['global_h6_color'] ?? '',
448 + ]);
449 + // phpcs:ignore WordPress.Security.NonceVerification.Missing
450 + do_action( 'ablocks/after_save_settings', $is_update, 'base', $payload );
451 + wp_send_json_success( $is_update );
452 + }
453 +
454 + public function fetch_posts( $payload ) {
455 + $post_type = ( isset( $payload['postType'] ) ? $payload['postType'] : 'page' );
456 + $postId = ( isset( $payload['postId'] ) ? $payload['postId'] : 0 );
457 + $keyword = ( isset( $payload['keyword'] ) ? $payload['keyword'] : '' );
458 +
459 + if ( $postId ) {
460 + $args = array(
461 + 'post_type' => $post_type,
462 + 'p' => $postId,
463 + );
464 + } else {
465 + $args = array(
466 + 'post_type' => $post_type,
467 + 'posts_per_page' => 10,
468 + );
469 + if ( ! empty( $keyword ) ) {
470 + $args['s'] = $keyword;
471 + }
472 + // Anyone who cannot edit other people's posts only picks from their own.
473 + if ( ! current_user_can( 'edit_others_posts' ) ) {
474 + $args['author'] = get_current_user_id();
475 + }
476 + }
477 + $results = array();
478 + $posts = get_posts( $args );
479 + if ( is_array( $posts ) ) {
480 + foreach ( $posts as $post ) {
481 + $results[] = array(
482 + 'label' => $post->post_title,
483 + 'value' => $post->ID,
484 + );
485 + }
486 + }
487 + wp_send_json_success( $results );
488 + }
489 +
490 + public function get_fronted_dashboard_pages() {
491 + $settings = json_decode( get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ), true );
492 + foreach ( $settings as &$item ) {
493 + if ( isset( $item['parent_id'] ) ) {
494 + $item['parent_id'] = 'null' === $item['parent_id'] ? null : $item['parent_id'];
495 + }
496 +
497 + $item['edit_link'] = (
498 + 'link' !== ( $item['type'] ?? '' ) &&
499 + is_numeric( $item['page_id'] )
500 + )
501 + ? str_replace( '&amp;', '&', get_edit_post_link( $item['page_id'] ) )
502 + : null;
503 +
504 + if ( is_array( $item['children'] ?? null ) ) {
505 + foreach ( $item['children'] as &$child_item ) {
506 + if ( isset( $child_item['parent_id'] ) ) {
507 + $child_item['parent_id'] = 'null' === $child_item['parent_id'] ? null : $child_item['parent_id'];
508 +
509 + }
510 +
511 + $child_item['edit_link'] = (
512 + 'link' !== ( $child_item['type'] ?? '' ) &&
513 + is_numeric( $child_item['page_id'] )
514 + )
515 + ? str_replace( '&amp;', '&', get_edit_post_link( $child_item['page_id'] ) )
516 + : null;
517 + }
518 + }
519 + }//end foreach
520 + wp_send_json_success( $settings );
521 + }
522 + public function create_fronted_dashboard_page( $payload ) {
523 + global $wpdb;
524 + // Step 1: Get Frontend Dashboard Page ID
525 + $frontend_dashboard_id = (int) Helper::get_settings( 'frontend_dashboard_page' );
526 + $settings = json_decode( get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ), true );
527 + $root_page_id = 0;
528 + // Step 2: Check if "root" page exists under frontend dashboard
529 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
530 + $root_page = $wpdb->get_row( $wpdb->prepare(
531 + "SELECT ID, post_parent FROM $wpdb->posts WHERE post_parent=%d AND post_name = %s AND post_type = 'page'",
532 + $frontend_dashboard_id,
533 + 'root'
534 + ) );
535 +
536 + $post_parent = ! empty( $payload['parent_id'] ) ? $payload['parent_id'] : $frontend_dashboard_id;
537 +
538 + if ( ! $root_page || (int) $root_page->post_parent !== $frontend_dashboard_id ) {
539 + // Step 3: Create "root" page as child of frontend dashboard page
540 + $root_page_id = wp_insert_post( [
541 + 'post_title' => 'Root',
542 + 'post_name' => 'root',
543 + 'post_status' => 'publish',
544 + 'post_type' => 'page',
545 + 'post_content' => '',
546 + 'post_parent' => $frontend_dashboard_id,
547 + ] );
548 +
549 + $settings[] = [
550 + 'page_id' => $root_page_id,
551 + 'label' => 'Root',
552 + 'slug' => 'root',
553 + 'icon' => '',
554 + 'class_name' => '',
555 + 'priority' => 0,
556 + ];
557 + }
558 +
559 + $insert_page_id = wp_insert_post( [
560 + 'post_title' => $payload['label'],
561 + 'post_name' => $payload['slug'],
562 + 'post_content' => '',
563 + 'post_status' => 'publish',
564 + 'post_type' => 'page',
565 + 'post_parent' => $post_parent,
566 + ] );
567 +
568 + if ( $insert_page_id ) {
569 + $payload['page_id'] = $insert_page_id;
570 +
571 + if ( ! empty( $payload['parent_id'] ) ) {
572 + foreach ( $settings as &$setting ) {
573 + if ( $setting['page_id'] === $post_parent ) {
574 + if ( ! isset( $setting['children'] ) ) {
575 + $setting['children'] = [];
576 + }
577 + $setting['children'][] = $payload;
578 + }
579 + }
580 + unset( $setting ); // important to break reference
581 + } else {
582 + $settings[] = $payload;
583 + }
584 +
585 + update_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, wp_json_encode( $settings ) );
586 + flush_rewrite_rules();
587 + }
588 +
589 + wp_send_json_success( get_post( $insert_page_id ) );
590 + }
591 +
592 + public function create_fronted_dashboard_link( array $payload ) : void {
593 + global $wpdb;
594 +
595 + if ( empty( $payload['link'] ) || empty( $payload['label'] ) ) {
596 + wp_send_json_error( __( 'Link/Label is required.', 'ablocks' ) );
597 + }
598 +
599 + $settings = json_decode(
600 + get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ),
601 + true
602 + );
603 +
604 + $payload['type'] = 'link';
605 + $parent_id = $payload['parent_id'] = $payload['parent_id'] ?? 0;
606 + $payload['page_id'] = 'link_' . time();
607 + // print_r($payload);
608 + // var_dump(( $parent_id ));
609 + if ( empty( $parent_id ) || 'null' === $parent_id ) {
610 + $settings[] = $payload;
611 + } elseif ( ! is_null(
612 + $index = array_search(
613 + $parent_id,
614 + array_column( $settings, 'page_id' )
615 + )
616 + )
617 + ) {
618 + $settings[ $index ]['children'][] = $payload;
619 + } else {
620 + wp_send_json_error( __( 'Invalid parent id.', 'ablocks' ) );
621 + }
622 +
623 + update_option(
624 + ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME,
625 + wp_json_encode( array_values( $settings ) )
626 + );
627 +
628 + wp_send_json_success( $payload );
629 + }
630 +
631 + public function edit_fronted_dashboard_link( array $payload ) : void {
632 + global $wpdb;
633 +
634 + if ( empty( $payload['page_id'] ) ||
635 + empty( $payload['link'] ) ||
636 + empty( $payload['label'] )
637 + ) {
638 + wp_send_json_error( __( 'Link/Label/ID is required.', 'ablocks' ) );
639 + }
640 +
641 + $settings = json_decode(
642 + get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ),
643 + true
644 + );
645 +
646 + $page_id = $payload['page_id'] = $payload['page_id'] ?? 0;
647 +
648 + foreach ( $settings as &$items ) {
649 + // echo $items['page_id'],"\n";
650 + // var_dump($page_id , $items['page_id']);
651 + if ( $page_id === $items['page_id'] ) {
652 + $items['label'] = $payload['label'] ?: $items['label'];
653 + $items['link'] = $payload['link'] ?: $items['link'];
654 + $items['class_name'] = $payload['class_name'] ?: $items['class_name'];
655 + $items['icon'] = $payload['icon'] ?: $items['icon'];
656 + break;
657 + } elseif ( ! empty( $items['children'] ) ) {
658 + foreach ( $items['children'] as &$c_items ) {
659 + if ( $page_id === $c_items['page_id'] ) {
660 + $c_items['label'] = $payload['label'] ?: $c_items['label'];
661 + $c_items['link'] = $payload['link'] ?: $c_items['link'];
662 + $c_items['class_name'] = $payload['class_name'] ?: $c_items['class_name'];
663 + $c_items['icon'] = $payload['icon'] ?: $c_items['icon'];
664 + break 2;
665 + }
666 + }
667 + }
668 + }//end foreach
669 +
670 + update_option(
671 + ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME,
672 + wp_json_encode( array_values( $settings ) )
673 + );
674 +
675 + wp_send_json_success( $payload );
676 + }
677 +
678 + public function delete_fronted_dashboard_link( array $payload ) : void {
679 + global $wpdb;
680 + // print_r($payload);
681 + if ( empty( $payload['page_id'] )
682 + ) {
683 + wp_send_json_error( __( 'ID is required.', 'ablocks' ) );
684 + }
685 +
686 + $settings = json_decode(
687 + get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ),
688 + true
689 + );
690 +
691 + $page_id = $payload['page_id'] = $payload['page_id'] ?? 0;
692 +
693 + foreach ( $settings as &$items ) {
694 + // echo $items['page_id'],"\n";
695 + // var_dump($page_id , $items['page_id']);
696 + if ( $page_id === $items['page_id'] ) {
697 + $items = null;
698 + break;
699 + } elseif ( ! empty( $items['children'] ) ) {
700 + foreach ( $items['children'] as &$c_items ) {
701 + if ( $page_id === $c_items['page_id'] ) {
702 + $c_items = null;
703 + $items['children'] = array_filter( $items['children'] );
704 + break 2;
705 + }
706 + }
707 + }
708 + }
709 +
710 + update_option(
711 + ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME,
712 + wp_json_encode( array_filter( $settings ) )
713 + );
714 +
715 + wp_send_json_success( $payload );
716 + }
717 +
718 + public function edit_fronted_dashboard_page( $payload ) {
719 + if ( empty( $payload['page_id'] ) ) {
720 + wp_send_json_error( 'Page ID is required for updating.' );
721 + }
722 +
723 + wp_update_post( [
724 + 'ID' => $payload['page_id'],
725 + 'post_title' => $payload['label'],
726 + 'post_slug' => $payload['slug'],
727 + 'priority' => $payload['priority'],
728 + 'post_parent' => ! empty( $payload['parent_id'] ) ? (int) $payload['parent_id'] : 0,
729 + ], true );
730 +
731 + $settings = json_decode( get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ), true );
732 +
733 + $update_settings_recursive = null; // initialize first
734 + $update_settings_recursive = function ( &$settings ) use ( &$update_settings_recursive, $payload ) {
735 + foreach ( $settings as &$setting ) {
736 + if ( $setting['page_id'] === $payload['page_id'] ) {
737 + $setting['label'] = $payload['label'] ?? $setting['label'];
738 + $setting['slug'] = $payload['slug'] ?? $setting['slug'];
739 + $setting['icon'] = $payload['icon'] ?? $setting['icon'];
740 + $setting['class_name'] = $payload['class_name'] ?? $setting['class_name'];
741 + $setting['priority'] = $payload['priority'] ?? ( $setting['priority'] ?? 0 );
742 + if ( isset( $payload['slug'] ) ||
743 + isset( $payload['label'] )
744 + ) {
745 + wp_update_post( [
746 + 'ID' => $payload['page_id'],
747 + 'post_title' => $payload['label'] ?? $setting['label'],
748 + 'post_name' => $payload['slug'] ?? $setting['slug'],
749 + ] );
750 + }
751 + if ( isset( $payload['children'] ) ) {
752 + $setting['children'] = $payload['children'];
753 + }
754 + return true;
755 + }//end if
756 +
757 + if ( ! empty( $setting['children'] ) ) {
758 + if ( $update_settings_recursive( $setting['children'] ) ) {
759 + return true;
760 + }
761 + }
762 + }//end foreach
763 + return false;
764 + };
765 +
766 + $update_settings_recursive( $settings );
767 + update_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, wp_json_encode( $settings ) );
768 +
769 + flush_rewrite_rules();
770 + // Step 4: Return updated page
771 + wp_send_json_success( get_post( $payload['page_id'] ) );
772 + }
773 +
774 + public function delete_fronted_dashboard_page( $payload ) {
775 + // Load existing frontend dashboard sub-pages settings
776 + $settings = json_decode( get_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}' ), true );
777 + if ( ! is_array( $settings ) ) {
778 + $settings = [];
779 + }
780 +
781 + $remove_id = $payload['page_id'] ?? null;
782 + $remove_slug = $payload['slug'] ?? null;
783 +
784 + if ( ! $remove_id && ! $remove_slug ) {
785 + wp_send_json_error( 'Page ID or slug is required to delete.' );
786 + }
787 +
788 + // Step 1: Delete the post if ID is provided
789 + if ( $remove_id ) {
790 + wp_delete_post( (int) $remove_id, true );
791 + } elseif ( $remove_slug ) {
792 + // If only slug is provided, try to find the page
793 + $page = get_page_by_path( $remove_slug, OBJECT, 'page' );
794 + if ( $page ) {
795 + $remove_id = $page->ID;
796 + wp_delete_post( $remove_id, true );
797 + }
798 + }
799 +
800 + // Step 2: Recursively remove from settings
801 + $remove_from_settings = function ( &$settings ) use ( &$remove_from_settings, $remove_id, $remove_slug ) {
802 + $settings = array_values(array_filter($settings, function ( $item ) use ( $remove_id, $remove_slug ) {
803 + $match_id = isset( $item['page_id'] ) && $remove_id && $item['page_id'] == $remove_id;
804 + $match_slug = isset( $item['slug'] ) && $remove_slug && $item['slug'] == $remove_slug;
805 + return ! $match_id && ! $match_slug;
806 + }));
807 +
808 + // Recurse into children
809 + foreach ( $settings as &$item ) {
810 + if ( ! empty( $item['children'] ) ) {
811 + $remove_from_settings( $item['children'] );
812 + }
813 + }
814 + unset( $item );
815 + };
816 +
817 + $remove_from_settings( $settings );
818 +
819 + // Step 3: Save updated settings
820 + update_option( ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, wp_json_encode( $settings ) );
821 +
822 + wp_send_json_success( $remove_id ?? $remove_slug );
823 + }
824 +
825 + public function move_fronted_dashboard_page( array $payload ) : void {
826 + $reordered_settings = json_decode( $payload['reordered_items'] ?? '{}', true );
827 + $settings = json_decode(
828 + get_option(
829 + ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME, '{}'
830 + ),
831 + true
832 + );
833 +
834 + if ( is_array( $reordered_settings ) &&
835 + count( $reordered_settings ) === count( $settings )
836 + ) {
837 + update_option(
838 + ABLOCKS_FRONTEND_DASHBOARD_SUB_PAGES_SETTINGS_NAME,
839 + $payload['reordered_items'] ?? '{}'
840 + );
841 + wp_send_json_success( __( 'Success!', 'ablocks' ) );
842 + }
843 + wp_send_json_error( __( 'Invalid data', 'ablocks' ), 400 );
844 + }
845 +}