PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.3.0
Adminify – White Label, Admin Menu Editor, Login Customizer v4.3.0
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Classes / Wizard / Adminify_Setup_Wizard.php

Adminify_Setup_Wizard.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.3.0, at Inc/Classes/Wizard/Adminify_Setup_Wizard.php

317 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Classes\Wizard;
4
5 use \PXLBSAdminify\Inc\Admin\AdminSettings;
6 use PXLBSAdminify\Inc\Utils;
7
8 // no direct access allowed
9 if (!defined('ABSPATH')) {
10 exit;
11 }
12
13 class Adminify_Setup_Wizard {
14 public $options;
15
16 public function __construct() {
17
18 if (current_user_can('manage_options') && current_user_can('administrator')) {
19
20 add_action('wp_ajax_pxlbsadminify_save_wizard_data', [$this, 'pxlbsadminify_save_wizard_data']);
21
22 $this->options = (array) AdminSettings::get_instance()->get();
23
24 $this->setup_wizard();
25
26 add_action('wp_ajax_pxlbsadminify_drag_and_drop_image', [$this, 'pxlbsadminify_drag_and_drop_image_callback']);
27
28 }
29
30 }
31
32 // Drag and Drop Image
33 public function pxlbsadminify_drag_and_drop_image_callback() {
34 check_ajax_referer('pxlbsadminify_sw');
35
36 // Security check - only administrators can upload images via wizard
37 if (!current_user_can('manage_options')) {
38 wp_send_json_error(__('You do not have permission to perform this action.', 'adminify'));
39 }
40
41 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- nonce verified above; settings array recursively sanitized via wp_kses_post_deep().
42 $data_source = empty($_POST['settings']) ? [] : (array) wp_kses_post_deep(wp_unslash($_POST['settings']));
43
44 $base64_image = isset($data_source['image_data']) ? (string) $data_source['image_data'] : '';
45
46 // Validate the data URI shape before parsing.
47 if (strpos($base64_image, ';') === false || strpos($base64_image, ',') === false) {
48 wp_send_json_error(__('Invalid image data.', 'adminify'));
49 }
50
51 // Extract the base64 data (remove the data URI scheme)
52 list($type, $data) = explode(';', $base64_image);
53 list(, $data) = explode(',', $data);
54 $decoded_data = base64_decode($data, true);
55
56 if ($decoded_data === false) {
57 wp_send_json_error(__('Invalid image data.', 'adminify'));
58 }
59
60 // Sanitize the filename: strip any path components and enforce an image extension allowlist.
61 $raw_name = isset($data_source['image_name']) ? (string) $data_source['image_name'] : '';
62 $safe_name = sanitize_file_name(basename($raw_name));
63
64 $filetype = wp_check_filetype($safe_name);
65 $allowed = array('jpg', 'jpeg', 'png', 'gif', 'webp');
66 if (empty($safe_name) || !in_array(strtolower((string) $filetype['ext']), $allowed, true)) {
67 wp_send_json_error(__('Invalid image file type.', 'adminify'));
68 }
69
70 // Write the decoded bytes into the uploads dir (handles unique filename + path).
71 $uploaded = wp_upload_bits($safe_name, null, $decoded_data);
72 if (!empty($uploaded['error']) || empty($uploaded['file'])) {
73 wp_send_json_error(__('Failed to save the image.', 'adminify'));
74 }
75
76 // Register the file as a Media Library attachment so it behaves like a normal upload.
77 $attachment = array(
78 'post_mime_type' => $filetype['type'],
79 'post_title' => sanitize_text_field(pathinfo($safe_name, PATHINFO_FILENAME)),
80 'post_content' => '',
81 'post_status' => 'inherit',
82 );
83
84 $attachment_id = wp_insert_attachment($attachment, $uploaded['file']);
85 if (is_wp_error($attachment_id) || !$attachment_id) {
86 wp_send_json_error(__('Failed to register the image in the media library.', 'adminify'));
87 }
88
89 // Generate thumbnails/metadata for the attachment.
90 require_once ABSPATH . 'wp-admin/includes/image.php';
91 $metadata = wp_generate_attachment_metadata($attachment_id, $uploaded['file']);
92 wp_update_attachment_metadata($attachment_id, $metadata);
93
94 wp_send_json_success(
95 array(
96 'id' => $attachment_id,
97 'url' => wp_get_attachment_url($attachment_id),
98 )
99 );
100 }
101
102 public function validate_before_save($settings) {
103 foreach ($settings as $key => $setting) {
104 $settings[$key] = $this->maybe_convert_to_boolean($setting);
105 }
106
107 return $settings;
108 }
109
110 public function maybe_convert_to_boolean(&$setting) {
111 if (gettype($setting) == 'string' && ($setting === 'true' || $setting === 'false')) {
112 $setting = wp_validate_boolean($setting);
113 } elseif (gettype($setting) == 'array') {
114 foreach ($setting as $key => $_setting) {
115 $setting[$key] = $this->maybe_convert_to_boolean($_setting);
116 }
117 }
118 return $setting;
119 }
120
121 // TEXT validation
122 public function text_validation($text) {
123 return sanitize_text_field( wp_unslash( $text ?? '' ) );
124 }
125
126 // Build the full CSF media field value from an attachment id.
127 public function build_media_value($attachment_id) {
128 $attachment_id = absint($attachment_id);
129 $full = wp_get_attachment_image_src($attachment_id, 'full');
130 $thumb = wp_get_attachment_image_src($attachment_id, 'thumbnail');
131
132 return array(
133 'id' => $attachment_id,
134 'url' => $full ? $full[0] : wp_get_attachment_url($attachment_id),
135 'width' => $full ? $full[1] : '',
136 'height' => $full ? $full[2] : '',
137 'thumbnail' => $thumb ? $thumb[0] : '',
138 'alt' => (string) get_post_meta($attachment_id, '_wp_attachment_image_alt', true),
139 'title' => get_the_title($attachment_id),
140 'description' => '',
141 );
142 }
143
144 public function pxlbsadminify_save_wizard_data() {
145 check_ajax_referer('pxlbsadminify_sw');
146
147 // Security check - only administrators can save wizard settings
148 if (!current_user_can('manage_options')) {
149 wp_send_json_error(__('You do not have permission to perform this action.', 'adminify'));
150 }
151
152 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- nonce verified above; settings array recursively sanitized via wp_kses_post_deep().
153 $settings = empty($_POST['settings']) ? [] : (array) wp_kses_post_deep(wp_unslash($_POST['settings']));
154
155 $validate_settings = $this->validate_before_save($settings);
156
157 $settings = get_option('pxlbsadminify_settings', []);
158
159 // Adminify UI
160 if( array_key_exists('admin_ui', $validate_settings) ) {
161 $settings['admin_ui'] = !empty($validate_settings['admin_ui']) ? true : false;
162 }
163
164 // Admin Bar Logo
165 if( array_key_exists('admin_ui_logo_type', $validate_settings) && array_key_exists('admin_ui_light_mode', $validate_settings)) {
166
167 $settings['light_dark_mode']['admin_ui_logo_type'] = $validate_settings['admin_ui_logo_type'];
168 if($validate_settings['admin_ui_logo_type'] === 'text_logo') {
169 $settings['light_dark_mode']['admin_ui_light_mode']['admin_ui_light_logo_text'] = $this->text_validation( $validate_settings['admin_ui_light_mode']['admin_ui_light_logo_text'] );
170 }
171 if($validate_settings['admin_ui_logo_type'] === 'image_logo') {
172 $logo_value = $validate_settings['admin_ui_light_mode']['admin_ui_light_logo'];
173 $attachment_id = isset($logo_value['id']) ? absint($logo_value['id']) : 0;
174
175 if ($attachment_id && wp_attachment_is_image($attachment_id)) {
176 // Rebuild the full media value from the attachment so the CSF
177 // media field has every key it renders (thumbnail drives the preview).
178 $settings['light_dark_mode']['admin_ui_light_mode']['admin_ui_light_logo'] = $this->build_media_value($attachment_id);
179 } else {
180 $settings['light_dark_mode']['admin_ui_light_mode']['admin_ui_light_logo']['url'] = wp_http_validate_url($logo_value['url']);
181 }
182 }
183
184 }
185
186 // WP Footer Text
187 if( array_key_exists('footer_text', $validate_settings) ) {
188 $settings['white_label']['wordpress']['footer_text'] = wp_kses_post( $validate_settings['footer_text'] );
189 }
190
191 update_option('pxlbsadminify_settings', $settings);
192
193 $is_complete = !empty($_POST['is_complete']) && $_POST['is_complete'] === '1';
194 if ($is_complete) {
195 update_option('pxlbsadminify_setup_wizard_ran', '1');
196 }
197
198 wp_send_json_success(
199 [
200 'redirect' => true,
201 'is_complete' => $is_complete,
202 ]
203 );
204 }
205
206 public function load_scripts() {
207
208 // Register
209 // wp_register_script('wp-adminify-vue-vendors', PXLBSADMINIFY_ASSETS . 'admin/js/vendor' . Utils::assets_ext('.js'), [], PXLBSADMINIFY_VER, true);
210 wp_register_style('adminify-sw-setup', PXLBSADMINIFY_ASSETS . 'css/setup.css', array(), PXLBSADMINIFY_VER);
211 wp_register_script('adminify-sw-setup', PXLBSADMINIFY_ASSETS . 'admin/js/wp-adminify--setup-wizard' . Utils::assets_ext('.js'), ['react', 'jquery'], PXLBSADMINIFY_VER, true);
212
213 // Elementor registers "elementor-ai-media-library" inside the
214 // WordPress media iframe with dependencies (elementor-v2-ui,
215 // elementor-v2-icons) that are not registered in this admin
216 // context. WordPress 6.9.1+ raises a "called incorrectly" notice
217 // at registration time when that happens. Pre-register empty stubs
218 // for those handles before wp_enqueue_media() so the dependency
219 // check passes silently. The wizard does not use Elementor, so we
220 // also dequeue Elementor's media-library script after enqueue to
221 // avoid loading unrelated assets here.
222 if (!wp_script_is('elementor-v2-ui', 'registered')) {
223 wp_register_script('elementor-v2-ui', '', [], PXLBSADMINIFY_VER, true);
224 }
225 if (!wp_script_is('elementor-v2-icons', 'registered')) {
226 wp_register_script('elementor-v2-icons', '', [], PXLBSADMINIFY_VER, true);
227 }
228
229 // Media uploader
230 wp_enqueue_media();
231
232 add_action('admin_print_scripts', function () {
233 if (wp_script_is('elementor-ai-media-library', 'enqueued')) {
234 wp_dequeue_script('elementor-ai-media-library');
235 }
236 }, 999);
237
238 // Load
239 wp_enqueue_style('adminify-sw-setup');
240 // wp_enqueue_script('media-upload');
241 wp_enqueue_script('adminify-sw-setup');
242
243
244 $is_network = is_multisite() && is_network_admin();
245 $settings_url = $is_network
246 ? network_admin_url('admin.php?page=wp-adminify-settings')
247 : admin_url('admin.php?page=wp-adminify-settings');
248 $dashboard_url = $is_network ? network_admin_url('/') : admin_url('/');
249
250 // Localize Script
251 $adminify_data = [
252 // 'rest_base' => $this->get_rest_url(''),
253 'ajax_url' => admin_url('admin-ajax.php'),
254 'admin_url' => $dashboard_url,
255 'settings_url' => $settings_url,
256 'rest_url' => esc_url_raw(rest_url('adminify/v1/')),
257 'settings' => [
258 'admin_ui' => $this->options['admin_ui'],
259 'admin_ui_logo_type' => $this->options['light_dark_mode']['admin_ui_logo_type'],
260 'admin_ui_light_mode' => [
261 'admin_ui_light_logo' => [
262 'url' => $this->options['light_dark_mode']['admin_ui_light_mode']['admin_ui_light_logo']['url']
263 ],
264 'admin_ui_light_logo_text' => $this->options['light_dark_mode']['admin_ui_light_mode']['admin_ui_light_logo_text'] ?? '',
265 ],
266 'footer_text' => $this->options['white_label']['wordpress']['footer_text'],
267 ],
268 'images' => PXLBSADMINIFY_ASSETS_IMAGE,
269 'wpnonce' => wp_create_nonce('pxlbsadminify_sw'),
270 'rest_nonce' => wp_create_nonce('wp_rest')
271 ];
272
273 wp_localize_script('adminify-sw-setup', 'PXLBSADMINIFY_SETUP_WIZARD_DATA', $adminify_data);
274
275
276 // // Dequeue Styles
277 // // wp_dequeue_style('install');
278 // wp_deregister_style('install');
279 // // wp_deregister_style('dashicons');
280
281 // // Dequeue Scripts
282 // wp_deregister_script('debug-bar');
283 // wp_deregister_script('debug-bar-js');
284 // wp_deregister_script('admin-bar');
285 // wp_deregister_script('shortcode');
286
287 }
288
289 public function setup_wizard() {
290 global $hook_suffix;
291
292 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check, no state change.
293 if (empty($_GET['page']) || 'wp-adminify-setup-wizard' !== sanitize_text_field(wp_unslash($_GET['page']))) {
294 return;
295 }
296
297 require_once ABSPATH . WPINC . '/media-template.php';
298 // add_action( 'admin_footer', 'wp_print_media_templates' );
299 // add_action( 'wp_footer', 'wp_print_media_templates' );
300 // add_action( 'customize_controls_print_footer_scripts', 'wp_print_media_templates' );
301
302 add_action( 'admin_print_footer_scripts', 'wp_print_media_templates' );
303
304 $this->load_scripts();
305
306 echo '<div id="wp-adminify--setup-wizard" class="wp-adminify-sw-setup-content"></div>';
307
308 // do_action('admin_footer');
309 // do_action("admin_print_footer_scripts-{$hook_suffix}");
310 do_action('admin_print_footer_scripts');
311 do_action("admin_footer-{$hook_suffix}");
312
313 exit;
314 }
315
316 }
317