Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/elementor/core/admin/admin.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + namespace Elementor\Core\Admin;
3 +
4 + use Elementor\Api;
5 + use Elementor\Beta_Testers;
6 + use Elementor\App\Modules\Onboarding\Module as Onboarding_Module;
7 + use Elementor\Core\Base\App;
8 + use Elementor\Core\Upgrade\Manager as Upgrade_Manager;
9 + use Elementor\Core\Utils\Assets_Config_Provider;
10 + use Elementor\Core\Utils\Collection;
11 + use Elementor\Modules\FloatingButtons\Module as Floating_Buttons_Module;
12 + use Elementor\Plugin;
13 + use Elementor\Settings;
14 + use Elementor\User;
15 + use Elementor\Utils;
16 + use Elementor\Core\Utils\Hints;
17 +
18 + if ( ! defined( 'ABSPATH' ) ) {
19 + exit; // Exit if accessed directly.
20 + }
21 +
22 + class Admin extends App {
23 +
24 + private $menus = [];
25 +
26 + /**
27 + * Get module name.
28 + *
29 + * Retrieve the module name.
30 + *
31 + * @since 2.3.0
32 + * @access public
33 + *
34 + * @return string Module name.
35 + */
36 + public function get_name() {
37 + return 'admin';
38 + }
39 +
40 + /**
41 + * Check if current page is an Elementor admin page.
42 + *
43 + * @param \WP_Screen|null $current_screen Optional. Screen object to check. Defaults to current screen.
44 + *
45 + * @return bool Whether current page is an Elementor admin page.
46 + */
47 + public static function is_elementor_admin_page( $current_screen = null ) {
48 + if ( ! $current_screen ) {
49 + $current_screen = get_current_screen();
50 + }
51 +
52 + if ( ! $current_screen ) {
53 + return false;
54 + }
55 +
56 + $screen_id = $current_screen->id ?? '';
57 + $post_type = $current_screen->post_type ?? '';
58 +
59 + $is_elementor_screen = strpos( $screen_id, 'elementor' ) !== false
60 + || strpos( $screen_id, Floating_Buttons_Module::CPT_FLOATING_BUTTONS ) !== false;
61 +
62 + $is_elementor_post_type = strpos( $post_type, 'elementor' ) !== false
63 + || strpos( $post_type, Floating_Buttons_Module::CPT_FLOATING_BUTTONS ) !== false;
64 +
65 + return $is_elementor_screen || $is_elementor_post_type;
66 + }
67 +
68 + /**
69 + * @since 2.2.0
70 + * @access public
71 + */
72 + public function maybe_redirect_to_getting_started() {
73 + if ( ! get_transient( 'elementor_activation_redirect' ) ) {
74 + return;
75 + }
76 +
77 + if ( wp_doing_ajax() ) {
78 + return;
79 + }
80 +
81 + delete_transient( 'elementor_activation_redirect' );
82 +
83 + if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
84 + return;
85 + }
86 +
87 + $already_had_onboarding = get_option( Onboarding_Module::ONBOARDING_OPTION );
88 +
89 + // Get the latest installation from Elementor's Install log in the DB.
90 + $latest_install = key( Upgrade_Manager::get_installs_history() );
91 +
92 + if ( ! empty( $latest_install ) ) {
93 + $is_new_install = version_compare( $latest_install, '3.6.0-beta', '>=' );
94 + } else {
95 + // If `$latest_install` is not set, Elementor was never installed on this site.
96 + $is_new_install = true;
97 + }
98 +
99 + if ( $already_had_onboarding || ! $is_new_install ) {
100 + return;
101 + }
102 +
103 + wp_safe_redirect( admin_url( 'admin.php?page=elementor-app#onboarding' ) );
104 +
105 + exit;
106 + }
107 +
108 + private function register_packages() {
109 + $assets_config_provider = ( new Assets_Config_Provider() )
110 + ->set_path_resolver( function ( $name ) {
111 + return ELEMENTOR_ASSETS_PATH . "js/packages/{$name}/{$name}.asset.php";
112 + } );
113 +
114 + Collection::make( [ 'ui', 'icons', 'query' ] )
115 + ->each( function( $package ) use ( $assets_config_provider ) {
116 + $suffix = Utils::is_script_debug() ? '' : '.min';
117 + $config = $assets_config_provider->load( $package )->get( $package );
118 +
119 + if ( ! $config ) {
120 + return;
121 + }
122 +
123 + wp_register_script(
124 + $config['handle'],
125 + ELEMENTOR_ASSETS_URL . "js/packages/{$package}/{$package}{$suffix}.js",
126 + $config['deps'],
127 + ELEMENTOR_VERSION,
128 + true
129 + );
130 + } );
131 + }
132 +
133 + /**
134 + * Enqueue admin scripts.
135 + *
136 + * Registers all the admin scripts and enqueues them.
137 + *
138 + * Fired by `admin_enqueue_scripts` action.
139 + *
140 + * @since 1.0.0
141 + * @access public
142 + */
143 + public function enqueue_scripts() {
144 + wp_register_script(
145 + 'elementor-admin-modules',
146 + $this->get_js_assets_url( 'admin-modules' ),
147 + [],
148 + ELEMENTOR_VERSION,
149 + true
150 + );
151 +
152 + $this->register_packages();
153 +
154 + // Temporary solution for the admin.
155 + wp_register_script(
156 + 'elementor-ai-admin',
157 + $this->get_js_assets_url( 'ai-admin' ),
158 + [
159 + 'elementor-common',
160 + 'elementor-v2-ui',
161 + 'elementor-v2-icons',
162 + ],
163 + ELEMENTOR_VERSION,
164 + true
165 + );
166 +
167 + wp_register_script(
168 + 'elementor-admin',
169 + $this->get_js_assets_url( 'admin' ),
170 + [
171 + 'elementor-common',
172 + 'elementor-admin-modules',
173 + ],
174 + ELEMENTOR_VERSION,
175 + true
176 + );
177 +
178 + wp_enqueue_script( 'elementor-admin' );
179 +
180 + wp_set_script_translations( 'elementor-admin', 'elementor' );
181 +
182 + $this->maybe_enqueue_hints();
183 +
184 + $this->print_config();
185 + }
186 +
187 + /**
188 + * Enqueue admin styles.
189 + *
190 + * Registers all the admin styles and enqueues them.
191 + *
192 + * Fired by `admin_enqueue_scripts` action.
193 + *
194 + * @since 1.0.0
195 + * @access public
196 + */
197 + public function enqueue_styles() {
198 + wp_register_style(
199 + 'elementor-admin',
200 + $this->get_css_assets_url( 'admin' ),
201 + [
202 + 'elementor-common',
203 + ],
204 + ELEMENTOR_VERSION
205 + );
206 +
207 + wp_enqueue_style( 'elementor-admin' );
208 +
209 + // It's for upgrade notice.
210 + // TODO: enqueue this just if needed.
211 + add_thickbox();
212 + }
213 +
214 + /**
215 + * Print switch mode button.
216 + *
217 + * Adds a switch button in post edit screen (which has cpt support). To allow
218 + * the user to switch from the native WordPress editor to Elementor builder.
219 + *
220 + * Fired by `edit_form_after_title` action.
221 + *
222 + * @since 1.0.0
223 + * @access public
224 + *
225 + * @param \WP_Post $post The current post object.
226 + */
227 + public function print_switch_mode_button( $post ) {
228 + // Exit if Gutenberg are active.
229 + if ( did_action( 'enqueue_block_editor_assets' ) ) {
230 + return;
231 + }
232 +
233 + $document = Plugin::$instance->documents->get( $post->ID );
234 +
235 + if ( ! $document || ! $document->is_editable_by_current_user() ) {
236 + return;
237 + }
238 +
239 + wp_nonce_field( basename( __FILE__ ), '_elementor_edit_mode_nonce' );
240 + ?>
241 + <div id="elementor-switch-mode">
242 + <input id="elementor-switch-mode-input" type="hidden" name="_elementor_post_mode" value="<?php echo esc_attr( $document->is_built_with_elementor() ); ?>" />
243 + <button id="elementor-switch-mode-button" type="button" class="button button-primary button-hero">
244 + <span class="elementor-switch-mode-on">
245 + <i class="eicon-arrow-<?php echo ( is_rtl() ) ? 'right' : 'left'; ?>" aria-hidden="true"></i>
246 + <?php echo esc_html__( 'Back to WordPress Editor', 'elementor' ); ?>
247 + </span>
248 + <span class="elementor-switch-mode-off">
249 + <i class="eicon-elementor-square" aria-hidden="true"></i>
250 + <?php echo esc_html__( 'Edit with Elementor', 'elementor' ); ?>
251 + </span>
252 + </button>
253 + </div>
254 + <div id="elementor-editor">
255 + <a id="elementor-go-to-edit-page-link" href="<?php echo esc_url( $document->get_edit_url() ); ?>">
256 + <div id="elementor-editor-button" class="button button-primary button-hero">
257 + <i class="eicon-elementor-square" aria-hidden="true"></i>
258 + <?php echo esc_html__( 'Edit with Elementor', 'elementor' ); ?>
259 + </div>
260 + <div class="elementor-loader-wrapper">
261 + <div class="elementor-loader">
262 + <div class="elementor-loader-boxes">
263 + <div class="elementor-loader-box"></div>
264 + <div class="elementor-loader-box"></div>
265 + <div class="elementor-loader-box"></div>
266 + <div class="elementor-loader-box"></div>
267 + </div>
268 + </div>
269 + <div class="elementor-loading-title"><?php echo esc_html__( 'Loading', 'elementor' ); ?></div>
270 + </div>
271 + </a>
272 + </div>
273 + <?php
274 + }
275 +
276 + /**
277 + * Save post.
278 + *
279 + * Flag the post mode when the post is saved.
280 + *
281 + * Fired by `save_post` action.
282 + *
283 + * @since 1.0.0
284 + * @access public
285 + *
286 + * @param int $post_id Post ID.
287 + */
288 + public function save_post( $post_id ) {
289 + if ( ! wp_verify_nonce( Utils::get_super_global_value( $_POST, '_elementor_edit_mode_nonce' ), basename( __FILE__ ) ) ) {
290 + return;
291 + }
292 +
293 + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
294 + return;
295 + }
296 +
297 + Plugin::$instance->documents->get( $post_id )->set_is_built_with_elementor( ! empty( $_POST['_elementor_post_mode'] ) );
298 + }
299 +
300 + /**
301 + * Add Elementor post state.
302 + *
303 + * Adds a new "Elementor" post state to the post table.
304 + *
305 + * Fired by `display_post_states` filter.
306 + *
307 + * @since 1.8.0
308 + * @access public
309 + *
310 + * @param array $post_states An array of post display states.
311 + * @param \WP_Post $post The current post object.
312 + *
313 + * @return array A filtered array of post display states.
314 + */
315 + public function add_elementor_post_state( $post_states, $post ) {
316 + $document = Plugin::$instance->documents->get( $post->ID );
317 +
318 + if ( $document && $document->is_built_with_elementor() && $document->is_editable_by_current_user() ) {
319 + $post_states['elementor'] = esc_html__( 'Elementor', 'elementor' );
320 + }
321 +
322 + return $post_states;
323 + }
324 +
325 + /**
326 + * Body status classes.
327 + *
328 + * Adds CSS classes to the admin body tag.
329 + *
330 + * Fired by `admin_body_class` filter.
331 + *
332 + * @since 1.0.0
333 + * @access public
334 + *
335 + * @param string $classes Space-separated list of CSS classes.
336 + *
337 + * @return string Space-separated list of CSS classes.
338 + */
339 + public function body_status_classes( $classes ) {
340 + global $pagenow;
341 +
342 + if ( in_array( $pagenow, [ 'post.php', 'post-new.php' ], true ) && Utils::is_post_support() ) {
343 + $post = get_post();
344 +
345 + $document = Plugin::$instance->documents->get( $post->ID );
346 +
347 + $mode_class = $document && $document->is_built_with_elementor() ? 'elementor-editor-active' : 'elementor-editor-inactive';
348 +
349 + $classes .= ' ' . $mode_class;
350 + }
351 +
352 + return $classes;
353 + }
354 +
355 + /**
356 + * Plugin action links.
357 + *
358 + * Adds action links to the plugin list table
359 + *
360 + * Fired by `plugin_action_links` filter.
361 + *
362 + * @since 1.0.0
363 + * @access public
364 + *
365 + * @param array $links An array of plugin action links.
366 + *
367 + * @return array An array of plugin action links.
368 + */
369 + public function plugin_action_links( $links ) {
370 + $settings_link = sprintf( '<a href="%1$s">%2$s</a>', admin_url( 'admin.php?page=' . Settings::PAGE_ID ), esc_html__( 'Settings', 'elementor' ) );
371 +
372 + array_unshift( $links, $settings_link );
373 +
374 + $go_pro_text = esc_html__( 'Get Elementor Pro', 'elementor' );
375 + if ( Utils::is_sale_time() ) {
376 + $go_pro_text = esc_html__( 'Discounted Upgrades Now!', 'elementor' );
377 + }
378 +
379 + $links['go_pro'] = sprintf( '<a href="%1$s" target="_blank" class="elementor-plugins-gopro">%2$s</a>', 'https://go.elementor.com/go-pro-wp-plugins/', $go_pro_text );
380 +
381 + return $links;
382 + }
383 +
384 + /**
385 + * Plugin row meta.
386 + *
387 + * Adds row meta links to the plugin list table
388 + *
389 + * Fired by `plugin_row_meta` filter.
390 + *
391 + * @since 1.1.4
392 + * @access public
393 + *
394 + * @param array $plugin_meta An array of the plugin's metadata, including
395 + * the version, author, author URI, and plugin URI.
396 + * @param string $plugin_file Path to the plugin file, relative to the plugins
397 + * directory.
398 + *
399 + * @return array An array of plugin row meta links.
400 + */
401 + public function plugin_row_meta( $plugin_meta, $plugin_file ) {
402 + if ( ELEMENTOR_PLUGIN_BASE === $plugin_file ) {
403 + $row_meta = [
404 + 'docs' => '<a href="https://go.elementor.com/docs-admin-plugins/" aria-label="' . esc_attr__( 'View Elementor Documentation', 'elementor' ) . '" target="_blank">' . esc_html__( 'Docs & FAQs', 'elementor' ) . '</a>',
405 + 'ideo' => '<a href="https://go.elementor.com/yt-admin-plugins/" aria-label="' . esc_attr__( 'View Elementor Video Tutorials', 'elementor' ) . '" target="_blank">' . esc_html__( 'Video Tutorials', 'elementor' ) . '</a>',
406 + ];
407 +
408 + $plugin_meta = array_merge( $plugin_meta, $row_meta );
409 + }
410 +
411 + return $plugin_meta;
412 + }
413 +
414 + /**
415 + * Admin footer text.
416 + *
417 + * Modifies the "Thank you" text displayed in the admin footer.
418 + *
419 + * Fired by `admin_footer_text` filter.
420 + *
421 + * @since 1.0.0
422 + * @access public
423 + *
424 + * @param string $footer_text The content that will be printed.
425 + *
426 + * @return string The content that will be printed.
427 + */
428 + public function admin_footer_text( $footer_text ) {
429 + $current_screen = get_current_screen();
430 + $is_elementor_screen = ( $current_screen && false !== strpos( $current_screen->id, 'elementor' ) );
431 +
432 + if ( $is_elementor_screen ) {
433 + $footer_text = sprintf(
434 + /* translators: 1: Elementor, 2: Link to plugin review */
435 + __( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'elementor' ),
436 + '<strong>' . esc_html__( 'Elementor', 'elementor' ) . '</strong>',
437 + '<a href="https://go.elementor.com/admin-review/" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
438 + );
439 + }
440 +
441 + return $footer_text;
442 + }
443 +
444 + /**
445 + * Register dashboard widgets.
446 + *
447 + * Adds a new Elementor widgets to WordPress dashboard.
448 + *
449 + * Fired by `wp_dashboard_setup` action.
450 + *
451 + * @since 1.9.0
452 + * @access public
453 + */
454 + public function register_dashboard_widgets() {
455 + wp_add_dashboard_widget( 'e-dashboard-overview', esc_html__( 'Elementor Overview', 'elementor' ), [ $this, 'elementor_dashboard_overview_widget' ] );
456 +
457 + // Move our widget to top.
458 + global $wp_meta_boxes;
459 +
460 + $dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
461 + $ours = [
462 + 'e-dashboard-overview' => $dashboard['e-dashboard-overview'],
463 + ];
464 +
465 + $wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
466 + }
467 +
468 + /**
469 + * Displays the Elementor dashboard widget.
470 + *
471 + * Fired by `wp_add_dashboard_widget` function.
472 + *
473 + * @since 1.9.0
474 + * @access public
475 + */
476 + public function elementor_dashboard_overview_widget() {
477 + ?>
478 + <div class="e-dashboard-overview e-dashboard-widget">
479 + <?php
480 + self::elementor_dashboard_overview_header();
481 + self::elementor_dashboard_overview_recently_edited();
482 + self::elementor_dashboard_overview_news_updates();
483 + self::elementor_dashboard_overview_footer();
484 + ?>
485 + </div>
486 + <?php
487 + }
488 +
489 + /**
490 + * Displays the Elementor dashboard widget - header section.
491 + * Fired by `elementor_dashboard_overview_widget` function.
492 + *
493 + * @param bool $show_versions
494 + * @param bool $is_create_post_enabled
495 + *
496 + * @return void
497 + * @since 3.12.0
498 + */
499 + public static function elementor_dashboard_overview_header( bool $show_versions = true, bool $is_create_post_enabled = true ) {
500 + if ( User::is_current_user_can_edit_post_type( 'page' ) ) {
501 + $create_new_label = esc_html__( 'Create New Page', 'elementor' );
502 + $create_new_post_type = 'page';
503 + } elseif ( User::is_current_user_can_edit_post_type( 'post' ) ) {
504 + $create_new_label = esc_html__( 'Create New Post', 'elementor' );
505 + $create_new_post_type = 'post';
506 + }
507 + ?>
508 + <div class="e-overview__header">
509 + <?php if ( $show_versions ) { ?>
510 + <div class="e-overview__logo">
511 + <div class="e-logo-wrapper"><i class="eicon-elementor"></i></div>
512 + </div>
513 + <div class="e-overview__versions">
514 + <span class="e-overview__version"><?php echo esc_html__( 'Elementor', 'elementor' ); ?> v<?php echo ELEMENTOR_VERSION; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
515 + <?php
516 + /**
517 + * Elementor dashboard widget after the version.
518 + * Fires after Elementor version display in the dashboard widget.
519 + *
520 + * @since 1.9.0
521 + */
522 + do_action( 'elementor/admin/dashboard_overview_widget/after_version' );
523 + ?>
524 + </div>
525 + <?php } ?>
526 + <?php if ( ! empty( $create_new_post_type ) && $is_create_post_enabled ) { ?>
527 + <div class="e-overview__create">
528 + <a href="<?php echo esc_url( Plugin::$instance->documents->get_create_new_post_url( $create_new_post_type ) ); ?>" class="button"><span aria-hidden="true" class="dashicons dashicons-plus"></span> <?php echo esc_html( $create_new_label ); ?></a>
529 + </div>
530 + <?php } ?>
531 + </div>
532 + <?php
533 + }
534 +
535 + /**
536 + * Displays the Elementor dashboard widget - recently edited section.
537 + * Fired by `elementor_dashboard_overview_widget` function.
538 + *
539 + * @param array $args
540 + * @param bool $show_heading
541 + *
542 + * @return void
543 + * @since 3.12.0
544 + */
545 + public static function elementor_dashboard_overview_recently_edited( array $args = [], bool $show_heading = true ) {
546 + $recently_edited_query = Utils::get_recently_edited_posts_query( $args );
547 +
548 + if ( $recently_edited_query->have_posts() ) { ?>
549 + <div class="e-overview__recently-edited">
550 + <?php if ( $show_heading ) { ?>
551 + <h3 class="e-heading e-divider_bottom"><?php echo esc_html__( 'Recently Edited', 'elementor' ); ?></h3>
552 + <?php } ?>
553 + <ul class="e-overview__posts">
554 + <?php
555 + while ( $recently_edited_query->have_posts() ) {
556 + $recently_edited_query->the_post();
557 + $document = Plugin::$instance->documents->get( get_the_ID() );
558 +
559 + $date = date_i18n( _x( 'M jS', 'Dashboard Overview Widget Recently Date', 'elementor' ), get_the_modified_time( 'U' ) );
560 + ?>
561 + <li class="e-overview__post">
562 + <a href="<?php echo esc_url( $document->get_edit_url() ); ?>" class="e-overview__post-link"><?php echo esc_html( get_the_title() ); ?>
563 + <span class="dashicons dashicons-edit"></span></a>
564 + <span><?php echo $date; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>, <?php the_modified_time(); ?></span>
565 + </li>
566 + <?php } ?>
567 + </ul>
568 + </div>
569 + <?php }
570 + }
571 +
572 + /**
573 + * Displays the Elementor dashboard widget - news and updates section.
574 + * Fired by `elementor_dashboard_overview_widget` function.
575 + *
576 + * @param int $limit_feed
577 + * @param bool $show_heading
578 + *
579 + * @return void
580 + * @since 3.12.0
581 + * @access public
582 + */
583 + public static function elementor_dashboard_overview_news_updates( int $limit_feed = 0, bool $show_heading = true ) {
584 + $elementor_feed = Api::get_feed_data();
585 + if ( $limit_feed > 0 ) {
586 + $elementor_feed = array_slice( $elementor_feed, 0, $limit_feed );
587 + }
588 +
589 + if ( ! empty( $elementor_feed ) ) { ?>
590 + <div class="e-overview__feed">
591 + <?php if ( $show_heading ) { ?>
592 + <h3 class="e-heading e-divider_bottom"><?php echo esc_html__( 'News & Updates', 'elementor' ); ?></h3>
593 + <?php } ?>
594 + <ul class="e-overview__posts">
595 + <?php foreach ( $elementor_feed as $feed_item ) { ?>
596 + <li class="e-overview__post">
597 + <a href="<?php echo esc_url( $feed_item['url'] ); ?>" class="e-overview__post-link" target="_blank">
598 + <?php if ( ! empty( $feed_item['badge'] ) ) { ?>
599 + <span class="e-overview__badge"><?php echo esc_html( $feed_item['badge'] ); ?></span>
600 + <?php } ?>
601 + <?php echo esc_html( $feed_item['title'] ); ?>
602 + </a>
603 + <p class="e-overview__post-description"><?php echo esc_html( $feed_item['excerpt'] ); ?></p>
604 + </li>
605 + <?php } ?>
606 + </ul>
607 + </div>
608 + <?php }
609 + }
610 +
611 + /**
612 + * Displays the Elementor dashboard widget - footer section.
613 + * Fired by `elementor_dashboard_overview_widget` function.
614 + *
615 + * @since 3.12.0
616 + */
617 + public static function elementor_dashboard_overview_footer() {
618 + ?>
619 + <div class="e-overview__footer e-divider_top">
620 + <ul>
621 + <?php foreach ( self::static_get_dashboard_overview_widget_footer_actions() as $action_id => $action ) { ?>
622 + <li class="e-overview__<?php echo esc_attr( $action_id ); ?>">
623 + <a href="<?php echo esc_url( $action['link'] ); ?>" target="_blank"><?php echo esc_html( $action['title'] ); ?>
624 + <span class="screen-reader-text"><?php echo esc_html__( '(opens in a new window)', 'elementor' ); ?></span>
625 + <span aria-hidden="true" class="dashicons dashicons-external"></span></a>
626 + </li>
627 + <?php } ?>
628 + </ul>
629 + </div>
630 + <?php
631 + }
632 +
633 + /**
634 + * Get elementor dashboard overview widget footer actions.
635 + *
636 + * Retrieves the footer action links displayed in elementor dashboard widget.
637 + *
638 + * @since 3.12.0
639 + * @access public
640 + */
641 + public static function static_get_dashboard_overview_widget_footer_actions() {
642 + $base_actions = [
643 + 'blog' => [
644 + 'title' => esc_html__( 'Blog', 'elementor' ),
645 + 'link' => 'https://go.elementor.com/overview-widget-blog/',
646 + ],
647 + 'help' => [
648 + 'title' => esc_html__( 'Help', 'elementor' ),
649 + 'link' => 'https://go.elementor.com/overview-widget-docs/',
650 + ],
651 + ];
652 +
653 + $additions_actions = [];
654 + $additions_actions['ai'] = [
655 + 'title' => esc_html__( 'Build Smart with AI', 'elementor' ),
656 + 'link' => 'https://go.elementor.com/overview-widget-ai/',
657 + ];
658 + $additions_actions['go-pro'] = [
659 + 'title' => esc_html__( 'Upgrade', 'elementor' ),
660 + 'link' => 'https://go.elementor.com/go-pro-wp-overview-widget/',
661 + ];
662 +
663 + /**
664 + * Dashboard widget footer actions.
665 + *
666 + * Filters the additions actions displayed in Elementor dashboard widget.
667 + *
668 + * Developers can add new action links to Elementor dashboard widget
669 + * footer using this filter.
670 + *
671 + * @since 1.9.0
672 + *
673 + * @param array $additions_actions Elementor dashboard widget footer actions.
674 + */
675 + $additions_actions = apply_filters( 'elementor/admin/dashboard_overview_widget/footer_actions', $additions_actions );
676 +
677 + $actions = $base_actions + $additions_actions;
678 +
679 + return $actions;
680 + }
681 +
682 + /**
683 + * Get elementor dashboard overview widget footer actions.
684 + *
685 + * Retrieves the footer action links displayed in elementor dashboard widget.
686 + *
687 + * @since 1.9.0
688 + * @access private
689 + */
690 + private function get_dashboard_overview_widget_footer_actions() {
691 + return self::static_get_dashboard_overview_widget_footer_actions();
692 + }
693 +
694 + /**
695 + * Admin action new post.
696 + *
697 + * When a new post action is fired the title is set to 'Elementor' and the post ID.
698 + *
699 + * Fired by `admin_action_elementor_new_post` action.
700 + *
701 + * @since 1.9.0
702 + * @access public
703 + */
704 + public function admin_action_new_post() {
705 + check_admin_referer( 'elementor_action_new_post' );
706 +
707 + $post_type = Utils::get_super_global_value( $_GET, 'post_type' ) ?? 'post';
708 +
709 + if ( ! User::is_current_user_can_edit_post_type( $post_type ) ) {
710 + return;
711 + }
712 +
713 + if ( empty( $_GET['template_type'] ) ) {
714 + $type = 'post';
715 + } else {
716 + $type = sanitize_text_field( wp_unslash( $_GET['template_type'] ) );
717 + }
718 +
719 + $post_data = Utils::get_super_global_value( $_GET, 'post_data' ) ?? [];
720 +
721 + $post_data = $this->filter_post_data( $post_data );
722 +
723 + /**
724 + * Create new post meta data.
725 + *
726 + * Filters the meta data of any new post created.
727 + *
728 + * @since 2.0.0
729 + *
730 + * @param array $meta Post meta data.
731 + */
732 + $meta = [];
733 +
734 + if ( isset( $_GET['meta'] ) && is_array( $_GET['meta'] ) ) {
735 + $meta = array_map( 'sanitize_text_field', wp_unslash( $_GET['meta'] ) );
736 + }
737 +
738 + $meta = apply_filters( 'elementor/admin/create_new_post/meta', $meta );
739 +
740 + $post_data['post_type'] = $post_type;
741 +
742 + $document = Plugin::$instance->documents->create( $type, $post_data, $meta );
743 +
744 + if ( is_wp_error( $document ) ) {
745 + wp_die( $document ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
746 + }
747 +
748 + wp_safe_redirect( $document->get_edit_url() );
749 +
750 + die;
751 + }
752 +
753 + private function get_allowed_fields_for_role() {
754 + $allowed_fields = [
755 + 'post_title',
756 + 'post_content',
757 + 'post_excerpt',
758 + 'post_category',
759 + 'post_type',
760 + 'tags_input',
761 + ];
762 +
763 + if ( current_user_can( 'publish_posts' ) ) {
764 + $allowed_fields[] = 'post_status';
765 + }
766 +
767 + if ( current_user_can( 'edit_others_posts' ) ) {
768 + $allowed_fields[] = 'post_author';
769 + }
770 +
771 + return $allowed_fields;
772 + }
773 +
774 + private function filter_post_data( $post_data ) {
775 + $allowed_fields = $this->get_allowed_fields_for_role();
776 + return array_filter(
777 + $post_data,
778 + function( $key ) use ( $allowed_fields ) {
779 + return in_array( $key, $allowed_fields, true );
780 + },
781 + ARRAY_FILTER_USE_KEY
782 + );
783 + }
784 + /**
785 + * @since 2.3.0
786 + * @access public
787 + */
788 + public function add_new_template_template() {
789 + Plugin::$instance->common->add_template( ELEMENTOR_PATH . 'includes/admin-templates/new-template.php' );
790 + }
791 +
792 + public function add_new_floating_elements_template() {
793 + Plugin::$instance->common->add_template( ELEMENTOR_PATH . 'includes/admin-templates/new-floating-elements.php' );
794 + }
795 +
796 + public function enqueue_new_floating_elements_scripts() {
797 + $suffix = Utils::is_script_debug() ? '' : '.min';
798 +
799 + wp_enqueue_script(
800 + 'elementor-floating-elements-modal',
801 + ELEMENTOR_ASSETS_URL . 'js/floating-elements-modal' . $suffix . '.js',
802 + [],
803 + ELEMENTOR_VERSION,
804 + true
805 + );
806 +
807 + wp_set_script_translations( 'elementor-floating-elements-modal', 'elementor' );
808 + }
809 +
810 + /**
811 + * @access public
812 + */
813 + public function enqueue_new_template_scripts() {
814 + $suffix = Utils::is_script_debug() ? '' : '.min';
815 +
816 + wp_enqueue_script(
817 + 'elementor-new-template',
818 + ELEMENTOR_ASSETS_URL . 'js/new-template' . $suffix . '.js',
819 + [],
820 + ELEMENTOR_VERSION,
821 + true
822 + );
823 +
824 + wp_set_script_translations( 'elementor-new-template', 'elementor' );
825 + }
826 +
827 + /**
828 + * @since 2.6.0
829 + * @access public
830 + */
831 + public function add_beta_tester_template() {
832 + Plugin::$instance->common->add_template( ELEMENTOR_PATH . 'includes/admin-templates/beta-tester.php' );
833 + }
834 +
835 + /**
836 + * @access public
837 + */
838 + public function enqueue_beta_tester_scripts() {
839 + $suffix = Utils::is_script_debug() ? '' : '.min';
840 +
841 + wp_enqueue_script(
842 + 'elementor-beta-tester',
843 + ELEMENTOR_ASSETS_URL . 'js/beta-tester' . $suffix . '.js',
844 + [],
845 + ELEMENTOR_VERSION,
846 + true
847 + );
848 +
849 + wp_set_script_translations( 'elementor-beta-tester', 'elementor' );
850 + }
851 +
852 + public function init_floating_elements() {
853 + $screens = [
854 + 'elementor_library_page_e-floating-buttons' => true,
855 + 'edit-e-floating-buttons' => true,
856 + ];
857 +
858 + if ( ! isset( $screens[ get_current_screen()->id ] ) ) {
859 + return;
860 + }
861 +
862 + add_action( 'admin_head', [ $this, 'add_new_floating_elements_template' ] );
863 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_new_floating_elements_scripts' ] );
864 + }
865 +
866 + /**
867 + * @access public
868 + */
869 + public function init_new_template() {
870 + if ( 'edit-elementor_library' !== get_current_screen()->id ) {
871 + return;
872 + }
873 +
874 + // Allow plugins to add their templates on admin_head.
875 + add_action( 'admin_head', [ $this, 'add_new_template_template' ] );
876 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_new_template_scripts' ] );
877 + }
878 +
879 + public function version_update_warning( $current_version, $new_version ) {
880 + $current_version_minor_part = explode( '.', $current_version )[1];
881 + $new_version_minor_part = explode( '.', $new_version )[1];
882 +
883 + if ( $current_version_minor_part === $new_version_minor_part ) {
884 + return;
885 + }
886 + ?>
887 + <hr class="e-major-update-warning__separator" />
888 + <div class="e-major-update-warning">
889 + <div class="e-major-update-warning__icon">
890 + <i class="eicon-info-circle"></i>
891 + </div>
892 + <div>
893 + <div class="e-major-update-warning__title">
894 + <?php echo esc_html__( 'Heads up, Please backup before upgrade!', 'elementor' ); ?>
895 + </div>
896 + <div class="e-major-update-warning__message">
897 + <?php
898 + printf(
899 + /* translators: %1$s Link open tag, %2$s: Link close tag. */
900 + esc_html__( 'The latest update includes some substantial changes across different areas of the plugin. We highly recommend you %1$sbackup your site before upgrading%2$s, and make sure you first update in a staging environment', 'elementor' ),
901 + '<a href="https://go.elementor.com/wp-dash-update-backup/">',
902 + '</a>'
903 + );
904 + ?>
905 + </div>
906 + </div>
907 + </div>
908 + <?php
909 + }
910 +
911 + /**
912 + * @access public
913 + */
914 + public function init_beta_tester( $current_screen ) {
915 + if ( ( 'toplevel_page_elementor' === $current_screen->base ) || 'elementor_page_elementor-tools' === $current_screen->id ) {
916 + add_action( 'admin_head', [ $this, 'add_beta_tester_template' ] );
917 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_beta_tester_scripts' ] );
918 + }
919 + }
920 +
921 + /**
922 + * Admin constructor.
923 + *
924 + * Initializing Elementor in WordPress admin.
925 + *
926 + * @since 1.0.0
927 + * @access public
928 + */
929 + public function __construct() {
930 + Plugin::$instance->init_common();
931 +
932 + $this->add_component( 'feedback', new Feedback() );
933 + $this->add_component( 'admin-notices', new Admin_Notices() );
934 +
935 + add_action( 'admin_init', [ $this, 'maybe_redirect_to_getting_started' ] );
936 +
937 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
938 + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_styles' ] );
939 +
940 + add_action( 'edit_form_after_title', [ $this, 'print_switch_mode_button' ] );
941 + add_action( 'save_post', [ $this, 'save_post' ] );
942 +
943 + add_filter( 'display_post_states', [ $this, 'add_elementor_post_state' ], 10, 2 );
944 +
945 + add_filter( 'plugin_action_links_' . ELEMENTOR_PLUGIN_BASE, [ $this, 'plugin_action_links' ] );
946 + add_filter( 'plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 2 );
947 +
948 + add_filter( 'admin_body_class', [ $this, 'body_status_classes' ] );
949 + add_filter( 'admin_footer_text', [ $this, 'admin_footer_text' ] );
950 +
951 + // Register Dashboard Widgets.
952 + add_action( 'wp_dashboard_setup', [ $this, 'register_dashboard_widgets' ] );
953 +
954 + // Admin Actions
955 + add_action( 'admin_action_elementor_new_post', [ $this, 'admin_action_new_post' ] );
956 +
957 + add_action( 'current_screen', [ $this, 'init_new_template' ] );
958 + add_action( 'current_screen', [ $this, 'init_floating_elements' ] );
959 + add_action( 'current_screen', [ $this, 'init_beta_tester' ] );
960 +
961 + add_action( 'in_plugin_update_message-' . ELEMENTOR_PLUGIN_BASE, function( $plugin_data ) {
962 + $this->version_update_warning( ELEMENTOR_VERSION, $plugin_data['new_version'] );
963 + } );
964 +
965 + add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_hints' ] );
966 + }
967 +
968 + /**
969 + * @since 2.3.0
970 + * @access protected
971 + */
972 + protected function get_init_settings() {
973 + $beta_tester_email = get_user_meta( get_current_user_id(), User::BETA_TESTER_META_KEY, true );
974 + $elementor_beta = get_option( 'elementor_beta', 'no' );
975 + $all_introductions = User::get_introduction_meta();
976 + $beta_tester_signup_dismissed = array_key_exists( Beta_Testers::BETA_TESTER_SIGNUP, $all_introductions );
977 +
978 + $settings = [
979 + 'home_url' => home_url(),
980 + 'settings_url' => Settings::get_url(),
981 + 'user' => [
982 + 'introduction' => User::get_introduction_meta(),
983 + 'restrictions' => Plugin::$instance->role_manager->get_user_restrictions_array(),
984 + 'is_administrator' => current_user_can( 'manage_options' ),
985 + ],
986 + 'beta_tester' => [
987 + 'beta_tester_signup' => Beta_Testers::BETA_TESTER_SIGNUP,
988 + 'has_email' => $beta_tester_email,
989 + 'option_enabled' => 'no' !== $elementor_beta,
990 + 'signup_dismissed' => $beta_tester_signup_dismissed,
991 + ],
992 + 'experiments' => $this->get_experiments(),
993 + ];
994 +
995 + /**
996 + * Localize settings.
997 + *
998 + * Filters the initial localize settings in the admin.
999 + *
1000 + * WordPress has it's own way to pass localized data from PHP (backend) to
1001 + * JS (frontend). Elementor uses this method to pass localize data in the
1002 + * admin. This hook can be used to add more localized settings in addition
1003 + * to the initial Elementor settings.
1004 + *
1005 + * @since 2.3.0
1006 + *
1007 + * @param array $settings Initial localize settings.
1008 + */
1009 + $settings = apply_filters( 'elementor/admin/localize_settings', $settings );
1010 +
1011 + return $settings;
1012 + }
1013 +
1014 + private function get_experiments() {
1015 + return ( new Collection( Plugin::$instance->experiments->get_features() ) )
1016 + ->map( function ( $experiment_data ) {
1017 + $dependencies = $experiment_data['dependencies'] ?? [];
1018 +
1019 + $dependencies = ( new Collection( $dependencies ) )
1020 + ->map( function ( $dependency ) {
1021 + return $dependency->get_name();
1022 + } )->all();
1023 +
1024 + return [
1025 + 'name' => $experiment_data['name'],
1026 + 'title' => $experiment_data['title'] ?? $experiment_data['name'],
1027 + 'state' => $experiment_data['state'],
1028 + 'default' => $experiment_data['default'],
1029 + 'dependencies' => $dependencies,
1030 + 'messages' => $experiment_data['messages'] ?? [],
1031 + ];
1032 + } )->all();
1033 + }
1034 +
1035 + private function maybe_enqueue_hints() {
1036 + if ( ! Hints::should_display_hint( 'image-optimization' ) ) {
1037 + return;
1038 + }
1039 +
1040 + wp_register_script(
1041 + 'media-hints',
1042 + $this->get_js_assets_url( 'media-hints' ),
1043 + [],
1044 + ELEMENTOR_VERSION,
1045 + true
1046 + );
1047 +
1048 + $content = sprintf("%1\$s <a class='e-btn-1' href='%2\$s' target='_blank'>%3\$s</a>!",
1049 + __( 'Optimize your images to enhance site performance by using Image Optimizer.', 'elementor' ),
1050 + Hints::get_plugin_action_url( 'image-optimization' ),
1051 + ( Hints::is_plugin_installed( 'image-optimization' ) ? __( 'Activate', 'elementor' ) : __( 'Install', 'elementor' ) ) . ' ' . __( 'Image Optimizer', 'elementor' )
1052 + );
1053 +
1054 + $dismissible = 'image_optimizer_hint';
1055 +
1056 + wp_localize_script( 'media-hints', 'elementorAdminHints', [
1057 + 'mediaHint' => [
1058 + 'display' => true,
1059 + 'type' => 'info',
1060 + 'content' => $content,
1061 + 'icon' => true,
1062 + 'dismissible' => $dismissible,
1063 + 'dismiss' => __( 'Dismiss this notice.', 'elementor' ),
1064 + 'button_event' => $dismissible,
1065 + 'button_data' => base64_encode(
1066 + wp_json_encode( [
1067 + 'action_url' => Hints::get_plugin_action_url( 'image-optimization' ),
1068 + ] ),
1069 + ),
1070 + ],
1071 + ] );
1072 +
1073 + wp_enqueue_script( 'media-hints' );
1074 + }
1075 +
1076 + public function register_ajax_hints( $ajax_manager ) {
1077 + $ajax_manager->register_ajax_action( 'elementor_image_optimization_campaign', [ $this, 'ajax_set_image_optimization_campaign' ] );
1078 + $ajax_manager->register_ajax_action( 'elementor_core_site_mailer_campaign', [ $this, 'ajax_site_mailer_campaign' ] );
1079 + $ajax_manager->register_ajax_action( 'elementor_core_ally_campaign', [ $this, 'ajax_ally_campaign' ] );
1080 + }
1081 +
1082 + public function ajax_ally_campaign( $request ) {
1083 + if ( ! current_user_can( 'install_plugins' ) ) {
1084 + return;
1085 + }
1086 +
1087 + if ( empty( $request['source'] ) ) {
1088 + return;
1089 + }
1090 +
1091 + $campaign_data = [
1092 + 'source' => sanitize_key( $request['source'] ),
1093 + 'campaign' => 'ally-plg',
1094 + 'medium' => 'wp-dash',
1095 + ];
1096 +
1097 + set_transient( 'elementor_ea11y_campaign', $campaign_data, 30 * DAY_IN_SECONDS );
1098 + }
1099 +
1100 + public function ajax_set_image_optimization_campaign( $request ) {
1101 + if ( ! current_user_can( 'install_plugins' ) ) {
1102 + return;
1103 + }
1104 +
1105 + if ( empty( $request['source'] ) ) {
1106 + return;
1107 + }
1108 +
1109 + $campaign_data = [
1110 + 'source' => sanitize_key( $request['source'] ),
1111 + 'campaign' => 'io-plg',
1112 + 'medium' => 'wp-dash',
1113 + ];
1114 +
1115 + set_transient( 'elementor_image_optimization_campaign', $campaign_data, 30 * DAY_IN_SECONDS );
1116 + }
1117 +
1118 + public function ajax_site_mailer_campaign( $request ) {
1119 + if ( ! current_user_can( 'install_plugins' ) ) {
1120 + return;
1121 + }
1122 +
1123 + if ( empty( $request['source'] ) ) {
1124 + return;
1125 + }
1126 +
1127 + $campaign_data = [
1128 + 'source' => sanitize_key( $request['source'] ),
1129 + 'campaign' => 'sm-plg',
1130 + 'medium' => 'wp-dash',
1131 + ];
1132 +
1133 + set_transient( 'elementor_site_mailer_campaign', $campaign_data, 30 * DAY_IN_SECONDS );
1134 + }
1135 + }
1136 +