PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.3
Elementor Website Builder – more than just a page builder v3.6.3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / app / modules / onboarding / module.php

module.php in Elementor Website Builder – more than just a page builder 3.6.3, at core/app/modules/onboarding/module.php

452 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\App\Modules\Onboarding;
3
4 use Automatic_Upgrader_Skin;
5 use Elementor\Core\Base\Module as BaseModule;
6 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
7 use Elementor\Core\Common\Modules\Connect\Apps\Library;
8 use Elementor\Core\Files\Uploads_Manager;
9 use Elementor\Plugin;
10 use Elementor\Tracker;
11 use Plugin_Upgrader;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly
15 }
16
17 /**
18 * Onboarding Module
19 *
20 * Responsible for initializing Elementor App functionality
21 *
22 * @since 3.6.0
23 */
24 class Module extends BaseModule {
25
26 const VERSION = '1.0.0';
27 const ONBOARDING_OPTION = 'elementor_onboarded';
28
29 /**
30 * Get name.
31 *
32 * @since 3.6.0
33 * @access public
34 *
35 * @return string
36 */
37 public function get_name() {
38 return 'onboarding';
39 }
40
41 /**
42 * Set Onboarding Settings
43 *
44 * Creates an array of module settings that is localized into the JS App config.
45 *
46 * @since 3.6.0
47 */
48 private function set_onboarding_settings() {
49 if ( ! Plugin::$instance->common ) {
50 return;
51 }
52
53 // Get the published pages and posts
54 $pages_and_posts = new \WP_Query( [
55 'post_type' => [ 'page', 'post' ],
56 'post_status' => 'publish',
57 'update_post_meta_cache' => false,
58 'update_post_term_cache' => false,
59 'no_found_rows' => true,
60 ] );
61
62 $custom_site_logo_id = get_theme_mod( 'custom_logo' );
63 $custom_logo_src = wp_get_attachment_image_src( $custom_site_logo_id, 'full' );
64 $site_name = get_option( 'blogname', '' );
65
66 $hello_theme = wp_get_theme( 'hello-elementor' );
67 $hello_theme_errors = is_object( $hello_theme->errors() ) ? $hello_theme->errors()->errors : [];
68
69 /** @var Library $library */
70 $library = Plugin::$instance->common->get_component( 'connect' )->get_app( 'library' );
71
72 Plugin::$instance->app->set_settings( 'onboarding', [
73 'eventPlacement' => 'Onboarding wizard',
74 'onboardingAlreadyRan' => get_option( self::ONBOARDING_OPTION ),
75 'onboardingVersion' => self::VERSION,
76 'isLibraryConnected' => $library->is_connected(),
77 // Used to check if the Hello Elementor theme is installed but not activated.
78 'helloInstalled' => empty( $hello_theme_errors['theme_not_found'] ),
79 'helloActivated' => 'hello-elementor' === get_option( 'template' ),
80 // The "Use Hello theme on my site" checkbox should be checked by default only if this condition is met.
81 'helloOptOut' => count( $pages_and_posts->posts ) < 5,
82 'siteName' => esc_html( $site_name ),
83 'isUnfilteredFilesEnabled' => Uploads_Manager::are_unfiltered_uploads_enabled(),
84 'urls' => [
85 'kitLibrary' => Plugin::$instance->app->get_base_url() . '#/kit-library?order[direction]=desc&order[by]=featuredIndex',
86 'createNewPage' => Plugin::$instance->documents->get_create_new_post_url(),
87 'connect' => $library->get_admin_url( 'authorize', [
88 'utm_source' => 'onboarding-wizard',
89 'utm_campaign' => 'connect-account',
90 'utm_medium' => 'wp-dash',
91 'utm_term' => self::VERSION,
92 'source' => 'generic',
93 ] ),
94 'signUp' => $library->get_admin_url( 'authorize', [
95 'utm_source' => 'onboarding-wizard',
96 'utm_campaign' => 'connect-account',
97 'utm_medium' => 'wp-dash',
98 'utm_term' => self::VERSION,
99 'source' => 'generic',
100 'screen_hint' => 'signup',
101 ] ),
102 'uploadPro' => Plugin::$instance->app->get_base_url() . '#/onboarding/uploadAndInstallPro?mode=popup',
103 ],
104 'siteLogo' => [
105 'id' => $custom_site_logo_id,
106 'url' => $custom_logo_src ? $custom_logo_src[0] : '',
107 ],
108 'utms' => [
109 'connectTopBar' => '&utm_content=top-bar',
110 'connectCta' => '&utm_content=cta-button',
111 'connectCtaLink' => '&utm_content=cta-link',
112 'downloadPro' => '?utm_source=onboarding-wizard&utm_campaign=my-account-subscriptions&utm_medium=wp-dash&utm_content=import-pro-plugin&utm_term=' . self::VERSION,
113 ],
114 'nonce' => wp_create_nonce( 'onboarding' ),
115 ] );
116 }
117
118 /**
119 * Set Opt In
120 *
121 * This method opts the user into sharing non-sensitive usage data with Elementor.
122 *
123 * @since 3.6.0
124 *
125 * @return array
126 */
127 private function set_usage_data_opt_in() {
128 Tracker::set_opt_in( true );
129
130 return [
131 'status' => 'success',
132 'payload' => [
133 'usageDataShared' => true,
134 ],
135 ];
136 }
137
138 /**
139 * Maybe Update Site Logo
140 *
141 * If a new name is provided, it will be updated as the Site Name.
142 *
143 * @since 3.6.0
144 *
145 * @return array
146 */
147 private function maybe_update_site_name() {
148 // phpcs:ignore WordPress.Security.NonceVerification.Missing
149 $data = $_POST['data'];
150
151 if ( empty( $data ) ) {
152 return [
153 'status' => 'error',
154 'payload' => [
155 'error_message' => 'there was a problem setting your site name',
156 ],
157 ];
158 }
159
160 $data = json_decode( stripslashes( $data ), true );
161
162 /**
163 * Onboarding Site Name
164 *
165 * Filters the new site name passed by the user to update in Elementor's onboarding process.
166 * Elementor runs `esc_html()` on the Site Name passed by the user for security reasons. If a user wants to
167 * include special characters in their site name, they can use this filter to override it.
168 *
169 * @since 3.6.0
170 *
171 * @param string Escaped new site name
172 */
173 $new_site_name = apply_filters( 'elementor/onboarding/site-name', esc_html( $data['siteName'] ) );
174
175 update_option( 'blogname', $new_site_name );
176
177 return [
178 'status' => 'success',
179 'payload' => [
180 'siteNameUpdated' => true,
181 ],
182 ];
183 }
184
185 /**
186 * Maybe Update Site Logo
187 *
188 * If an image attachment ID is provided, it will be updated as the Site Logo Theme Mod.
189 *
190 * @since 3.6.0
191 *
192 * @return array
193 */
194 private function maybe_update_site_logo() {
195 // phpcs:ignore WordPress.Security.NonceVerification.Missing
196 $data = $_POST['data'];
197
198 if ( empty( $data ) ) {
199 $result = [
200 'status' => 'error',
201 'payload' => [
202 'error_message' => __( 'there was a problem setting your site logo', 'elementor' ),
203 ],
204 ];
205 } else {
206 $data = json_decode( stripslashes( $data ), true );
207
208 set_theme_mod( 'custom_logo', esc_html( $data['attachmentId'] ) );
209
210 $result = [
211 'status' => 'success',
212 'payload' => [
213 'siteLogoUpdated' => true,
214 ],
215 ];
216 }
217
218 return $result;
219 }
220
221 /**
222 * Maybe Upload Logo Image
223 *
224 * If an image file upload is provided, and it passes validation, it will be uploaded to the site's Media Library.
225 *
226 * @since 3.6.0
227 *
228 * @return array
229 */
230 private function maybe_upload_logo_image() {
231 $result = [];
232 $error_message = __( 'There was a problem uploading your file', 'elementor' );
233
234 // phpcs:ignore WordPress.Security.NonceVerification.Missing
235 if ( empty( $_FILES['fileToUpload'] ) ) {
236 $result = [
237 'status' => 'error',
238 'payload' => [
239 'error_message' => $error_message,
240 ],
241 ];
242
243 return $result;
244 }
245
246 // If the user has allowed it, set the Request's state as an "Elementor Upload" request, in order to add
247 // support for non-standard file uploads.
248 if ( 'image/svg+xml' === $_FILES['fileToUpload']['type'] ) {
249 if ( Uploads_Manager::are_unfiltered_uploads_enabled() ) {
250 Plugin::$instance->uploads_manager->set_elementor_upload_state( true );
251 } else {
252 wp_send_json_error( 'To upload SVG files, you must allow uploading unfiltered files.' );
253 }
254 }
255
256 $image_attachment = Plugin::$instance->templates_manager->get_import_images_instance()->import( $_FILES['fileToUpload'] );
257
258 if ( 'image/svg+xml' === $_FILES['fileToUpload']['type'] && Uploads_Manager::are_unfiltered_uploads_enabled() ) {
259 // Reset Upload state.
260 Plugin::$instance->uploads_manager->set_elementor_upload_state( false );
261 }
262
263 if ( $image_attachment && ! is_wp_error( $image_attachment ) ) {
264 $result = [
265 'status' => 'success',
266 'payload' => [
267 'imageAttachment' => $image_attachment,
268 ],
269 ];
270 } else {
271 $result = [
272 'status' => 'error',
273 'payload' => [
274 'error_message' => $error_message,
275 ],
276 ];
277 }
278
279 return $result;
280 }
281
282 /**
283 * Activate Hello Theme
284 *
285 * @since 3.6.0
286 *
287 * @return array
288 */
289 private function activate_hello_theme() {
290 switch_theme( 'hello-elementor' );
291
292 return [
293 'status' => 'success',
294 'payload' => [
295 'helloThemeActivated' => true,
296 ],
297 ];
298 }
299
300 /**
301 * Upload and Install Elementor Pro
302 *
303 * @since 3.6.0
304 *
305 * @return array
306 */
307 private function upload_and_install_pro() {
308 $result = [];
309 $error_message = __( 'There was a problem uploading your file', 'elementor' );
310
311 // phpcs:ignore WordPress.Security.NonceVerification.Missing
312 if ( empty( $_FILES['fileToUpload'] ) ) {
313 $result = [
314 'status' => 'error',
315 'payload' => [
316 'error_message' => $error_message,
317 ],
318 ];
319
320 return $result;
321 }
322
323 if ( ! class_exists( 'Automatic_Upgrader_Skin' ) ) {
324 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
325 }
326
327 $skin = new Automatic_Upgrader_Skin();
328 $upgrader = new Plugin_Upgrader( $skin );
329 $upload_result = $upgrader->install( $_FILES['fileToUpload']['tmp_name'], [ 'overwrite_package' => false ] );
330
331 if ( ! $upload_result || is_wp_error( $upload_result ) ) {
332 $result = [
333 'status' => 'error',
334 'payload' => [
335 'error_message' => $error_message,
336 ],
337 ];
338 } else {
339 $activated = activate_plugin( WP_PLUGIN_DIR . '/elementor-pro/elementor-pro.php', false, false, true );
340
341 if ( ! is_wp_error( $activated ) ) {
342 $result = [
343 'status' => 'success',
344 'payload' => [
345 'elementorProInstalled' => true,
346 ],
347 ];
348 } else {
349 $result = [
350 'status' => 'error',
351 'payload' => [
352 'error_message' => $error_message,
353 'elementorProInstalled' => false,
354 ],
355 ];
356 }
357 }
358
359 return $result;
360 }
361
362 private function maybe_update_onboarding_db_option() {
363 $db_option = get_option( self::ONBOARDING_OPTION );
364
365 if ( ! $db_option ) {
366 update_option( self::ONBOARDING_OPTION, true );
367 }
368
369 return [
370 'status' => 'success',
371 'payload' => 'onboarding DB',
372 ];
373 }
374
375 /**
376 * Maybe Handle Ajax
377 *
378 * This method checks if there are any AJAX actions being
379 * @since 3.6.0
380 *
381 * @return array|null
382 */
383 private function maybe_handle_ajax() {
384 $result = [];
385
386 // phpcs:ignore WordPress.Security.NonceVerification.Missing
387 switch ( $_POST['action'] ) {
388 case 'elementor_update_site_name':
389 // If no value is passed for any reason, no need ot update the site name.
390 $result = $this->maybe_update_site_name();
391 break;
392 case 'elementor_update_site_logo':
393 $result = $this->maybe_update_site_logo();
394 break;
395 case 'elementor_upload_site_logo':
396 $result = $this->maybe_upload_logo_image();
397 break;
398 case 'elementor_update_data_sharing':
399 $result = $this->set_usage_data_opt_in();
400 break;
401 case 'elementor_activate_hello_theme':
402 $result = $this->activate_hello_theme();
403 break;
404 case 'elementor_upload_and_install_pro':
405 $result = $this->upload_and_install_pro();
406 break;
407 case 'elementor_update_onboarding_option':
408 $result = $this->maybe_update_onboarding_db_option();
409 }
410
411 if ( ! empty( $result ) ) {
412 if ( 'success' === $result['status'] ) {
413 wp_send_json_success( $result['payload'] );
414 } else {
415 wp_send_json_error( $result['payload'] );
416 }
417 }
418 }
419
420 public function __construct() {
421 add_action( 'elementor/init', function() {
422 // Only load when viewing the onboarding app.
423 if ( Plugin::$instance->app->is_current() ) {
424 $this->set_onboarding_settings();
425 // Needed for installing the Hello Elementor theme.
426 wp_enqueue_script( 'updates' );
427 // Needed for uploading Logo from WP Media Library.
428 wp_enqueue_media();
429
430 Plugin::$instance->app->set_settings( 'disable_dark_theme', true );
431 }
432 }, 12 );
433
434 // Needed for uploading Logo from WP Media Library. The 'admin_menu' hook is used because it runs before
435 // 'admin_init', and the App triggers printing footer scripts on 'admin_init' at priority 0.
436 add_action( 'admin_menu', function() {
437 add_action( 'wp_print_footer_scripts', 'wp_print_media_templates' );
438 } );
439
440 add_action( 'admin_init', function() {
441 if ( wp_doing_ajax() &&
442 isset( $_POST['action'] ) &&
443 isset( $_POST['_nonce'] ) &&
444 wp_verify_nonce( $_POST['_nonce'], Ajax::NONCE_KEY ) &&
445 current_user_can( 'manage_options' )
446 ) {
447 $this->maybe_handle_ajax();
448 }
449 } );
450 }
451 }
452