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