Файловый менеджер - Редактировать - /home/avadvi5/calendar.aeronextgen.com/app.zip
Ðазад
PK ��\��Lm� � view.phpnu �[��� <?php namespace Elementor\App; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } /** * @var App $this */ $theme_class = 'dark' === $this->get_elementor_ui_theme_preference() ? 'eps-theme-dark' : ''; ?> <!DOCTYPE html> <html <?php language_attributes(); ?>> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title><?php echo esc_html__( 'Elementor', 'elementor' ) . ' ... '; ?></title> <base target="_parent"> <?php wp_print_styles(); ?> </head> <body class="<?php Utils::print_unescaped_internal_string( $theme_class ); ?>"> <div id="e-app"></div> <?php wp_print_footer_scripts(); ?> </body> </html> PK ��\~�X X 2 admin-menu-items/editor-one-theme-builder-menu.phpnu �[��� <?php namespace Elementor\App\AdminMenuItems; use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_Interface; use Elementor\Core\Admin\EditorOneMenu\Interfaces\Menu_Item_With_Custom_Url_Interface; use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item_With_Page; use Elementor\Modules\EditorOne\Classes\Menu_Config; use Elementor\Modules\EditorOne\Classes\Menu_Data_Provider; use Elementor\App\App; if ( ! defined( 'ABSPATH' ) ) { exit; } class Editor_One_Theme_Builder_Menu implements Menu_Item_Interface, Admin_Menu_Item_With_Page, Menu_Item_With_Custom_Url_Interface { public function get_capability(): string { return 'manage_options'; } public function get_parent_slug(): string { return Menu_Config::ELEMENTOR_MENU_SLUG; } public function is_visible(): bool { return true; } public function get_label(): string { return esc_html__( 'Theme Builder', 'elementor' ); } public function get_position(): int { return 15; } public function get_slug(): string { return App::PAGE_ID; } public function get_menu_url(): string { return Menu_Data_Provider::instance()->get_theme_builder_url(); } public function get_group_id(): string { return Menu_Config::TEMPLATES_GROUP_ID; } public function get_page_title(): string { return esc_html__( 'Theme Builder', 'elementor' ); } public function render(): void { } } PK ��\ �e: : , admin-menu-items/theme-builder-menu-item.phpnu �[��� <?php namespace Elementor\App\AdminMenuItems; use Elementor\Core\Admin\Menu\Interfaces\Admin_Menu_Item; use Elementor\TemplateLibrary\Source_Local; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Theme_Builder_Menu_Item implements Admin_Menu_Item { public function is_visible() { return true; } public function get_parent_slug() { return Source_Local::ADMIN_MENU_SLUG; } public function get_label() { return esc_html__( 'Theme Builder', 'elementor' ); } public function get_capability() { return 'manage_options'; } } PK ��\��]��$ �$ app.phpnu �[��� <?php namespace Elementor\App; use Elementor\App\AdminMenuItems\Theme_Builder_Menu_Item; use Elementor\Core\Admin\Menu\Admin_Menu_Manager; use Elementor\Core\Experiments\Manager as ExperimentsManager; use Elementor\Modules\WebCli\Module as WebCLIModule; use Elementor\Core\Base\App as BaseApp; use Elementor\Core\Settings\Manager as SettingsManager; use Elementor\Plugin; use Elementor\TemplateLibrary\Source_Local; use Elementor\User; use Elementor\Utils; use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager; use Elementor\Core\Utils\Assets_Config_Provider; use Elementor\Core\Utils\Collection; use Elementor\Core\Utils\Assets_Translation_Loader; use Elementor\Modules\EditorOne\Classes\Menu_Data_Provider; use Elementor\App\AdminMenuItems\Editor_One_Theme_Builder_Menu; use Elementor\App\Modules\ImportExport\Module as ImportExportModule; use Elementor\App\Modules\KitLibrary\Module as KitLibraryModule; use Elementor\App\Modules\ImportExportCustomization\Module as ImportExportCustomizationModule; use Elementor\App\Modules\SiteEditor\Module as SiteEditorModule; use Elementor\App\Modules\Onboarding\Module as OnboardingModule; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class App extends BaseApp { const PAGE_ID = 'elementor-app'; /** * Get module name. * * Retrieve the module name. * * @since 3.0.0 * @access public * * @return string Module name. */ public function get_name() { return 'app'; } public function get_base_url() { return admin_url( 'admin.php?page=' . self::PAGE_ID . '&ver=' . ELEMENTOR_VERSION ); } private function register_editor_one_menu( Menu_Data_Provider $menu_data_provider ) { $menu_data_provider->register_menu( new Editor_One_Theme_Builder_Menu() ); } public function fix_submenu( $menu ) { global $submenu; if ( is_multisite() && is_network_admin() ) { return $menu; } // Non admin role / custom wp menu. if ( empty( $submenu[ Source_Local::ADMIN_MENU_SLUG ] ) ) { return $menu; } // Hack to add a link to sub menu. foreach ( $submenu[ Source_Local::ADMIN_MENU_SLUG ] as &$item ) { if ( self::PAGE_ID === $item[2] ) { $item[2] = $this->get_settings( 'menu_url' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $item[4] = 'elementor-app-link'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited } } return $menu; } public function is_current() { return ( ! empty( $_GET['page'] ) && self::PAGE_ID === $_GET['page'] ); } public function admin_init() { do_action( 'elementor/app/init', $this ); // Add the introduction and user settings only when it is needed (when loading the app and not in the editor or admin pages) $this->set_settings( 'user', [ 'introduction' => (object) User::get_introduction_meta(), 'is_administrator' => current_user_can( 'manage_options' ), 'restrictions' => Plugin::$instance->role_manager->get_user_restrictions_array(), ] ); $this->enqueue_assets(); remove_action( 'wp_print_styles', 'print_emoji_styles' ); // Setup default heartbeat options // TODO: Enable heartbeat. add_filter( 'heartbeat_settings', function( $settings ) { $settings['interval'] = 15; return $settings; } ); $this->render(); die; } protected function get_init_settings() { $referer = wp_get_referer(); return [ 'menu_url' => $this->get_base_url() . '#site-editor/promotion', 'assets_url' => ELEMENTOR_ASSETS_URL, 'pages_url' => admin_url( 'edit.php?post_type=page' ), 'return_url' => $referer ? $referer : admin_url(), 'hasPro' => Utils::has_pro(), 'admin_url' => admin_url(), 'login_url' => wp_login_url(), 'base_url' => $this->get_base_url(), 'home_url' => home_url(), 'promotion' => Filtered_Promotions_Manager::get_filtered_promotion_data( [ 'upgrade_url' => 'https://go.elementor.com/go-pro-theme-builder/' ], 'elementor/site-editor/promotion', 'upgrade_url' ), ]; } private function render() { require __DIR__ . '/view.php'; } /** * Get Elementor editor theme color preference. * * Retrieve the user theme color preference as defined by editor preferences manager. * * @since 3.0.0 * @access private * * @return string Preferred editor theme. */ private function get_elementor_ui_theme_preference() { $editor_preferences = SettingsManager::get_settings_managers( 'editorPreferences' ); return $editor_preferences->get_model()->get_settings( 'ui_theme' ); } /** * Enqueue dark theme detection script. * * Enqueues an inline script that detects user-agent settings for dark mode and adds a complimentary class to the body tag. * * @since 3.0.0 * @access private */ private function enqueue_dark_theme_detection_script() { if ( 'auto' === $this->get_elementor_ui_theme_preference() ) { wp_add_inline_script( 'elementor-app', 'if ( window.matchMedia && window.matchMedia( `(prefers-color-scheme: dark)` ).matches ) { document.body.classList.add( `eps-theme-dark` ); }' ); } } private function register_packages() { $assets_config_provider = ( new Assets_Config_Provider() ) ->set_path_resolver( function ( $name ) { return ELEMENTOR_ASSETS_PATH . "js/packages/{$name}/{$name}.asset.php"; } ); Collection::make( [ 'ui', 'icons', 'store', 'query', 'utils', 'events', 'onboarding' ] ) ->each( function( $package ) use ( $assets_config_provider ) { $suffix = Utils::is_script_debug() ? '' : '.min'; $config = $assets_config_provider->load( $package )->get( $package ); if ( ! $config ) { return; } wp_register_script( $config['handle'], ELEMENTOR_ASSETS_URL . "js/packages/{$package}/{$package}{$suffix}.js", $config['deps'], ELEMENTOR_VERSION, true ); } ); } private function enqueue_assets() { Plugin::$instance->init_common(); $this->register_packages(); /** @var WebCLIModule $web_cli */ $web_cli = Plugin::$instance->modules_manager->get_modules( 'web-cli' ); $web_cli->register_scripts(); Plugin::$instance->common->register_scripts(); wp_register_style( 'select2', $this->get_css_assets_url( 'e-select2', 'assets/lib/e-select2/css/' ), [], '4.0.6-rc.1' ); Plugin::$instance->common->register_styles(); wp_register_style( 'select2', ELEMENTOR_ASSETS_URL . 'lib/e-select2/css/e-select2.css', [], '4.0.6-rc.1' ); wp_enqueue_style( 'elementor-app', $this->get_css_assets_url( 'app', null, 'default', true ), [ 'select2', 'elementor-icons', 'elementor-common', 'select2', ], ELEMENTOR_VERSION ); wp_enqueue_script( 'elementor-app-packages', $this->get_js_assets_url( 'app-packages' ), [ 'wp-i18n', 'react', ], ELEMENTOR_VERSION, true ); wp_register_script( 'select2', $this->get_js_assets_url( 'e-select2.full', 'assets/lib/e-select2/js/' ), [ 'jquery', ], '4.0.6-rc.1', true ); wp_enqueue_script( 'elementor-app', $this->get_js_assets_url( 'app' ), [ 'wp-url', 'wp-i18n', 'elementor-v2-ui', 'elementor-v2-icons', 'elementor-v2-onboarding', 'react', 'react-dom', 'select2', ], ELEMENTOR_VERSION, true ); $this->enqueue_dark_theme_detection_script(); Assets_Translation_Loader::for_handles( [ 'elementor-app-packages', 'elementor-app' ], 'elementor' ); $this->print_config(); } public function enqueue_app_loader() { wp_enqueue_script( 'elementor-app-loader', $this->get_js_assets_url( 'app-loader' ), [ 'elementor-common', ], ELEMENTOR_VERSION, true ); $this->print_config( 'elementor-app-loader' ); } private function register_import_export_customization_experiment() { Plugin::$instance->experiments->add_feature( [ 'name' => 'import-export-customization', 'title' => esc_html__( 'Import/Export Customization', 'elementor' ), 'description' => esc_html__( 'Enhanced import/export for website templates. Selectively include site content, templates, and settings with advanced granular control.', 'elementor' ), 'release_status' => ExperimentsManager::RELEASE_STATUS_BETA, 'default' => ExperimentsManager::STATE_ACTIVE, 'hidden' => true, 'mutable' => false, ] ); } public function __construct() { $this->register_import_export_customization_experiment(); $this->add_component( 'site-editor', new SiteEditorModule() ); if ( current_user_can( 'manage_options' ) || Utils::is_wp_cli() ) { $this->add_component( 'import-export', new ImportExportModule() ); if ( Plugin::$instance->experiments->is_feature_active( 'import-export-customization' ) ) { $this->add_component( 'import-export-customization', new ImportExportCustomizationModule() ); } // Kit library is depended on import-export $this->add_component( 'kit-library', new KitLibraryModule() ); } $this->add_component( 'onboarding', new OnboardingModule() ); add_action( 'elementor/editor-one/menu/register', function ( Menu_Data_Provider $menu_data_provider ) { $this->register_editor_one_menu( $menu_data_provider ); } ); // Happens after WP plugin page validation. add_filter( 'add_menu_classes', [ $this, 'fix_submenu' ] ); if ( $this->is_current() ) { add_action( 'admin_init', [ $this, 'admin_init' ], 0 ); } else { add_action( 'elementor/common/after_register_scripts', [ $this, 'enqueue_app_loader' ] ); } } } PK ��\6v<l l : modules/onboarding/storage/onboarding-progress-manager.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Storage; use Elementor\App\Modules\Onboarding\Module; use Elementor\App\Modules\Onboarding\Storage\Entities\User_Choices; use Elementor\App\Modules\Onboarding\Storage\Entities\User_Progress; if ( ! defined( 'ABSPATH' ) ) { exit; } class Onboarding_Progress_Manager { const PROGRESS_OPTION_KEY = 'elementor_onboarding_progress'; const CHOICES_OPTION_KEY = 'elementor_onboarding_choices'; const DEFAULT_TOTAL_STEPS = 5; private static ?Onboarding_Progress_Manager $instance = null; public static function instance(): Onboarding_Progress_Manager { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } public function get_progress(): User_Progress { $data = get_option( self::PROGRESS_OPTION_KEY, [] ); return User_Progress::from_array( $data ); } public function save_progress( User_Progress $progress ): User_Progress { update_option( self::PROGRESS_OPTION_KEY, $progress->to_array() ); return $progress; } public function update_progress( array $params ): User_Progress { $progress = $this->get_progress(); if ( isset( $params['current_step'] ) ) { $progress->set_current_step( (int) $params['current_step'] ); } if ( isset( $params['completed_steps'] ) ) { $progress->set_completed_steps( (array) $params['completed_steps'] ); } if ( isset( $params['exit_type'] ) ) { $progress->set_exit_type( $params['exit_type'] ); } if ( isset( $params['complete_step'] ) ) { $step = $params['complete_step']; $progress->add_completed_step( $step ); $step_index = $params['step_index'] ?? $progress->get_current_step_index(); $total_steps = $params['total_steps'] ?? self::DEFAULT_TOTAL_STEPS; $next_index = $step_index + 1; if ( $next_index < $total_steps ) { $progress->set_current_step_index( $next_index ); $progress->set_current_step_id( null ); } } if ( ! empty( $params['skip_step'] ) ) { $step_index = $params['step_index'] ?? $progress->get_current_step_index(); $total_steps = $params['total_steps'] ?? self::DEFAULT_TOTAL_STEPS; $next_index = $step_index + 1; if ( $next_index < $total_steps ) { $progress->set_current_step_index( $next_index ); $progress->set_current_step_id( null ); } } if ( isset( $params['start'] ) && $params['start'] ) { $progress->set_started_at( current_time( 'timestamp' ) ); $progress->set_exit_type( null ); } if ( isset( $params['complete'] ) && $params['complete'] ) { $progress->set_exit_type( 'user_exit' ); update_option( Module::ONBOARDING_OPTION, Module::VERSION ); } if ( isset( $params['user_exit'] ) && $params['user_exit'] ) { $progress->set_exit_type( 'user_exit' ); } if ( isset( $params['starter_dismissed'] ) && $params['starter_dismissed'] ) { $progress->set_starter_dismissed( true ); } $progress->set_last_active_timestamp( current_time( 'timestamp' ) ); return $this->save_progress( $progress ); } public function get_choices(): User_Choices { $data = get_option( self::CHOICES_OPTION_KEY, [] ); return User_Choices::from_array( $data ); } public function save_choices( User_Choices $choices ): User_Choices { update_option( self::CHOICES_OPTION_KEY, $choices->to_array() ); return $choices; } public function update_choices( array $params ): User_Choices { $choices = $this->get_choices(); if ( isset( $params['building_for'] ) ) { $choices->set_building_for( $params['building_for'] ); } if ( isset( $params['site_about'] ) ) { $choices->set_site_about( (array) $params['site_about'] ); } if ( isset( $params['experience_level'] ) ) { $choices->set_experience_level( $params['experience_level'] ); } if ( isset( $params['theme_selection'] ) ) { $choices->set_theme_selection( $params['theme_selection'] ); } if ( isset( $params['site_features'] ) ) { $choices->set_site_features( (array) $params['site_features'] ); } return $this->save_choices( $choices ); } public function reset(): void { delete_option( self::PROGRESS_OPTION_KEY ); delete_option( self::CHOICES_OPTION_KEY ); } private function __construct() {} } PK ��\zR�+� � 4 modules/onboarding/storage/entities/user-choices.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Storage\Entities; if ( ! defined( 'ABSPATH' ) ) { exit; } class User_Choices { private ?string $building_for = null; private array $site_about = []; private ?string $experience_level = null; private ?string $theme_selection = null; private array $site_features = []; public static function from_array( array $data ): self { $instance = new self(); $instance->building_for = $data['building_for'] ?? null; $instance->site_about = $data['site_about'] ?? []; $instance->experience_level = $data['experience_level'] ?? null; $instance->theme_selection = $data['theme_selection'] ?? null; $instance->site_features = $data['site_features'] ?? []; return $instance; } public function to_array(): array { return [ 'building_for' => $this->building_for, 'site_about' => $this->site_about, 'experience_level' => $this->experience_level, 'theme_selection' => $this->theme_selection, 'site_features' => $this->site_features, ]; } public function get_building_for(): ?string { return $this->building_for; } public function set_building_for( ?string $value ): void { $this->building_for = $value; } public function get_site_about(): array { return $this->site_about; } public function set_site_about( array $value ): void { $this->site_about = $value; } public function get_experience_level(): ?string { return $this->experience_level; } public function set_experience_level( ?string $value ): void { $this->experience_level = $value; } public function get_theme_selection(): ?string { return $this->theme_selection; } public function set_theme_selection( ?string $value ): void { $this->theme_selection = $value; } public function get_site_features(): array { return $this->site_features; } public function set_site_features( array $value ): void { $this->site_features = $value; } } PK ��\쐪�� � 5 modules/onboarding/storage/entities/user-progress.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Storage\Entities; if ( ! defined( 'ABSPATH' ) ) { exit; } class User_Progress { private int $current_step_index = 0; private ?string $current_step_id = null; private array $completed_steps = []; private ?string $exit_type = null; private ?int $last_active_timestamp = null; private ?int $started_at = null; private bool $starter_dismissed = false; public static function from_array( array $data ): self { $instance = new self(); $instance->current_step_index = $data['current_step_index'] ?? $data['current_step'] ?? 0; $instance->current_step_id = $data['current_step_id'] ?? null; $instance->completed_steps = $data['completed_steps'] ?? []; $instance->exit_type = $data['exit_type'] ?? null; $instance->last_active_timestamp = $data['last_active_timestamp'] ?? null; $instance->started_at = $data['started_at'] ?? null; $instance->starter_dismissed = ! empty( $data['starter_dismissed'] ); return $instance; } public function to_array(): array { return [ 'current_step' => $this->current_step_index, 'current_step_index' => $this->current_step_index, 'current_step_id' => $this->current_step_id, 'completed_steps' => $this->completed_steps, 'exit_type' => $this->exit_type, 'last_active_timestamp' => $this->last_active_timestamp, 'started_at' => $this->started_at, 'starter_dismissed' => $this->starter_dismissed, ]; } public function get_current_step(): int { return $this->current_step_index; } public function get_current_step_index(): int { return $this->current_step_index; } public function set_current_step_index( int $index ): void { $this->current_step_index = $index; } public function get_current_step_id(): ?string { return $this->current_step_id; } public function set_current_step_id( ?string $step_id ): void { $this->current_step_id = $step_id; } public function set_current_step( int $step, ?string $step_id = null ): void { $this->current_step_index = $step; if ( null !== $step_id ) { $this->current_step_id = $step_id; } } public function get_completed_steps(): array { return $this->completed_steps; } public function set_completed_steps( array $steps ): void { $this->completed_steps = $steps; } public function add_completed_step( $step ): void { if ( ! in_array( $step, $this->completed_steps, true ) ) { $this->completed_steps[] = $step; } } public function is_step_completed( $step ): bool { return in_array( $step, $this->completed_steps, true ); } public function get_exit_type(): ?string { return $this->exit_type; } public function set_exit_type( ?string $type ): void { $this->exit_type = $type; } public function get_last_active_timestamp(): ?int { return $this->last_active_timestamp; } public function set_last_active_timestamp( ?int $timestamp ): void { $this->last_active_timestamp = $timestamp; } public function get_started_at(): ?int { return $this->started_at; } public function set_started_at( ?int $timestamp ): void { $this->started_at = $timestamp; } public function is_starter_dismissed(): bool { return $this->starter_dismissed; } public function set_starter_dismissed( bool $dismissed ): void { $this->starter_dismissed = $dismissed; } public function had_unexpected_exit( bool $is_completed ): bool { return null === $this->exit_type && $this->current_step_index > 0 && ! $is_completed; } } PK ��\SI$E E 0 modules/onboarding/validation/base-validator.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Validation; use WP_Error; if ( ! defined( 'ABSPATH' ) ) { exit; } abstract class Base_Validator { protected array $errors = []; abstract protected function get_rules(): array; public function validate( array $params ) { if ( ! is_array( $params ) ) { return new WP_Error( 'invalid_params', 'Parameters must be an array.', [ 'status' => 400 ] ); } $this->errors = []; $validated = []; foreach ( $this->get_rules() as $field => $rule ) { if ( ! array_key_exists( $field, $params ) ) { continue; } $result = $this->validate_field( $field, $params[ $field ], $rule ); if ( is_wp_error( $result ) ) { return $result; } $validated[ $field ] = $result; } return $validated; } protected function validate_field( string $field, $value, array $rule ) { $type = $rule['type'] ?? 'string'; $nullable = $rule['nullable'] ?? false; if ( null === $value ) { if ( $nullable ) { return null; } return $this->error( $field, "{$field} cannot be null." ); } switch ( $type ) { case 'string': return $this->validate_string( $field, $value ); case 'int': return $this->validate_int( $field, $value ); case 'bool': return $this->validate_bool( $field, $value ); case 'array': return $this->validate_array( $field, $value, $rule ); case 'string_array': return $this->validate_string_array( $field, $value ); case 'custom_data': return $this->validate_custom_data( $field, $value ); default: return $value; } } protected function validate_string( string $field, $value ) { if ( ! is_string( $value ) ) { return $this->error( $field, "{$field} must be a string." ); } return sanitize_text_field( $value ); } protected function validate_int( string $field, $value ) { if ( ! is_numeric( $value ) ) { return $this->error( $field, "{$field} must be a number." ); } return (int) $value; } protected function validate_bool( string $field, $value ) { if ( ! is_bool( $value ) ) { return $this->error( $field, "{$field} must be a boolean." ); } return $value; } protected function validate_array( string $field, $value, array $rule ) { if ( ! is_array( $value ) ) { return $this->error( $field, "{$field} must be an array." ); } $allowed = $rule['allowed'] ?? null; if ( $allowed && ! in_array( $value, $allowed, true ) ) { return $this->error( $field, "{$field} contains invalid value." ); } return $value; } protected function validate_string_array( string $field, $value ) { if ( ! is_array( $value ) ) { return $this->error( $field, "{$field} must be an array." ); } return array_values( array_filter( array_map( static function ( $item ) { return is_string( $item ) ? sanitize_text_field( $item ) : null; }, $value ), static function ( $item ) { return null !== $item; } ) ); } protected function validate_custom_data( string $field, $value ) { if ( ! is_array( $value ) ) { return $this->error( $field, "{$field} must be an array." ); } return $this->sanitize_recursive( $value ); } protected function sanitize_recursive( array $data ): array { $sanitized = []; foreach ( $data as $key => $value ) { $safe_key = sanitize_key( $key ); if ( is_string( $value ) ) { $sanitized[ $safe_key ] = sanitize_text_field( $value ); } elseif ( is_array( $value ) ) { $sanitized[ $safe_key ] = $this->sanitize_recursive( $value ); } elseif ( is_numeric( $value ) || is_bool( $value ) || null === $value ) { $sanitized[ $safe_key ] = $value; } else { $sanitized[ $safe_key ] = null; } } return $sanitized; } protected function error( string $field, string $message ): WP_Error { return new WP_Error( 'invalid_' . $field, $message, [ 'status' => 400 ] ); } } PK ��\����E E 8 modules/onboarding/validation/user-choices-validator.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Validation; if ( ! defined( 'ABSPATH' ) ) { exit; } class User_Choices_Validator extends Base_Validator { protected function get_rules(): array { return [ 'building_for' => [ 'type' => 'string', 'nullable' => true, ], 'site_about' => [ 'type' => 'string_array', ], 'experience_level' => [ 'type' => 'string', 'nullable' => true, ], 'theme_selection' => [ 'type' => 'string', 'nullable' => true, ], 'site_features' => [ 'type' => 'string_array', ], ]; } } PK ��\[a�?S S 9 modules/onboarding/validation/user-progress-validator.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding\Validation; if ( ! defined( 'ABSPATH' ) ) { exit; } class User_Progress_Validator extends Base_Validator { private const ALLOWED_EXIT_TYPES = [ 'user_exit', 'unexpected', null, '' ]; protected function get_rules(): array { return [ 'current_step' => [ 'type' => 'int', ], 'completed_steps' => [ 'type' => 'mixed_array', ], 'exit_type' => [ 'type' => 'exit_type', 'nullable' => true, ], 'complete_step' => [ 'type' => 'string_or_int', ], 'skip_step' => [ 'type' => 'bool', ], 'step_index' => [ 'type' => 'int', ], 'total_steps' => [ 'type' => 'int', ], 'start' => [ 'type' => 'bool', ], 'complete' => [ 'type' => 'bool', ], 'user_exit' => [ 'type' => 'bool', ], 'starter_dismissed' => [ 'type' => 'bool', ], ]; } protected function validate_field( string $field, $value, array $rule ) { $type = $rule['type'] ?? 'string'; switch ( $type ) { case 'exit_type': return $this->validate_exit_type( $value ); case 'string_or_int': return $this->validate_string_or_int( $field, $value ); case 'mixed_array': return $this->validate_mixed_array( $field, $value ); default: return parent::validate_field( $field, $value, $rule ); } } private function validate_exit_type( $value ) { if ( ! in_array( $value, self::ALLOWED_EXIT_TYPES, true ) ) { return $this->error( 'exit_type', 'Exit type is invalid.' ); } return '' === $value ? null : $value; } private function validate_string_or_int( string $field, $value ) { if ( is_numeric( $value ) ) { return (int) $value; } if ( is_string( $value ) ) { return sanitize_text_field( $value ); } return $this->error( $field, "{$field} must be a number or string." ); } private function validate_mixed_array( string $field, $value ) { if ( ! is_array( $value ) ) { return $this->error( $field, "{$field} must be an array." ); } return array_values( array_filter( array_map( static function ( $item ) { if ( is_numeric( $item ) ) { return (int) $item; } if ( is_string( $item ) ) { return sanitize_text_field( $item ); } return null; }, $value ), static function ( $item ) { return null !== $item; } ) ); } } PK ��\��� V) V) modules/onboarding/module.phpnu �[��� <?php namespace Elementor\App\Modules\Onboarding; use Elementor\App\Modules\Onboarding\Data\Controller; use Elementor\App\Modules\Onboarding\Data\Endpoints\Install_Theme; use Elementor\App\Modules\Onboarding\Storage\Entities\User_Choices; use Elementor\App\Modules\Onboarding\Storage\Entities\User_Progress; use Elementor\App\Modules\Onboarding\Storage\Onboarding_Progress_Manager; use Elementor\Core\Base\Module as BaseModule; use Elementor\Core\Settings\Manager as SettingsManager; use Elementor\Includes\EditorAssetsAPI; use Elementor\Plugin; use Elementor\Utils; if ( ! defined( 'ABSPATH' ) ) { exit; } class Module extends BaseModule { const VERSION = '2.0.0'; const ASSETS_BASE_URL = 'https://assets.elementor.com/onboarding/v1/strings/'; const ONBOARDING_OPTION = 'elementor_onboarded'; const SUPPORTED_LOCALES = [ 'de_DE' => 'de', 'es_ES' => 'es', 'fr_FR' => 'fr', 'he_IL' => 'he', 'id_ID' => 'id', 'it_IT' => 'it', 'nl_NL' => 'nl', 'pl_PL' => 'pl', 'pt_BR' => 'pt', 'tr_TR' => 'tr', ]; private Onboarding_Progress_Manager $progress_manager; public function get_name(): string { return 'onboarding'; } public static function has_user_finished_onboarding(): bool { return (bool) get_option( self::ONBOARDING_OPTION ); } public function __construct() { $this->progress_manager = Onboarding_Progress_Manager::instance(); Plugin::instance()->data_manager_v2->register_controller( new Controller() ); add_action( 'elementor/init', [ $this, 'on_elementor_init' ], 12 ); if ( $this->should_show_starter() ) { add_filter( 'elementor/editor/localize_settings', [ $this, 'add_starter_settings' ] ); add_filter( 'elementor/editor/v2/packages', [ $this, 'add_starter_packages' ] ); add_action( 'elementor/editor/v2/styles/enqueue', [ $this, 'enqueue_fonts' ] ); add_action( 'elementor/preview/enqueue_styles', [ $this, 'enqueue_starter_preview_css' ] ); } } public function on_elementor_init(): void { if ( ! Plugin::instance()->app->is_current() ) { return; } $this->set_onboarding_settings(); $this->enqueue_fonts(); } public function enqueue_fonts(): void { wp_enqueue_style( 'elementor-onboarding-fonts', 'https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap', [], ELEMENTOR_VERSION ); } public function enqueue_starter_preview_css(): void { $css = ' #site-header, .page-header { display: var(--e-starter-header-display, none); } '; wp_register_style( 'elementor-starter-preview', false ); wp_enqueue_style( 'elementor-starter-preview' ); wp_add_inline_style( 'elementor-starter-preview', $css ); } public function progress_manager(): Onboarding_Progress_Manager { return $this->progress_manager; } private function set_onboarding_settings(): void { if ( ! Plugin::instance()->common ) { return; } $progress = $this->progress_manager->get_progress(); $choices = $this->progress_manager->get_choices(); $steps = $this->get_steps_config(); // If the user previously selected a theme but it's no longer the active theme, // clear the theme selection so the user can re-select. $this->maybe_invalidate_theme_selection( $progress, $choices ); $is_connected = $this->is_user_connected(); Plugin::$instance->app->set_settings( 'onboarding', [ 'version' => self::VERSION, 'restUrl' => rest_url( 'elementor/v1/onboarding/' ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'progress' => $this->validate_progress_for_steps( $progress, $steps ), 'choices' => $choices->to_array(), 'hadUnexpectedExit' => $progress->had_unexpected_exit( self::has_user_finished_onboarding() ), 'isConnected' => $is_connected, 'userName' => $this->get_user_display_name(), 'steps' => $steps, 'uiTheme' => $this->get_ui_theme_preference(), 'translations' => $this->get_translated_strings(), 'shouldShowProInstallScreen' => $is_connected ? $this->should_show_pro_install_screen() : false, 'urls' => [ 'dashboard' => admin_url(), 'editor' => admin_url( 'edit.php?post_type=elementor_library' ), 'connect' => $this->get_connect_url(), 'comparePlans' => 'https://go.elementor.com/go-pro-onboarding-editor-features-step-upgrade/', 'createNewPage' => Plugin::$instance->documents->get_create_new_post_url(), 'upgradeUrl' => 'https://go.elementor.com/go-pro-onboarding-editor-header-upgrade/', ], ] ); } private function validate_progress_for_steps( User_Progress $progress, array $steps ): array { $progress_data = $progress->to_array(); $step_count = count( $steps ); $current_step_index = $progress->get_current_step_index() ?? 0; $current_step_id = $progress->get_current_step_id() ?? $steps[0]['id'] ?? 'building_for'; $is_invalid_step_index = $current_step_index < 0 || $current_step_index >= $step_count; if ( $is_invalid_step_index ) { $current_step_id = $steps[0]['id']; $current_step_index = 0; } $progress_data['current_step_id'] = $current_step_id; $progress_data['current_step_index'] = $current_step_index; return $progress_data; } private function is_user_connected(): bool { $library = $this->get_library_app(); return $library ? $library->is_connected() : false; } private function get_connect_url(): string { $library = $this->get_library_app(); if ( ! $library ) { return ''; } return $library->get_admin_url( 'authorize', [ 'utm_source' => 'onboarding-wizard', 'utm_campaign' => 'connect-account', 'utm_medium' => 'wp-dash', 'utm_term' => self::VERSION, 'source' => 'generic', ] ) ?? ''; } private function get_library_app() { $connect = Plugin::instance()->common->get_component( 'connect' ); if ( ! $connect ) { return null; } return $connect->get_app( 'library' ); } public static function should_show_pro_install_screen(): bool { if ( self::is_elementor_pro_installed() ) { return false; } $connect = Plugin::$instance->common->get_component( 'connect' ); if ( ! $connect ) { return false; } $pro_install_app = $connect->get_app( 'pro-install' ); if ( ! $pro_install_app || ! $pro_install_app->is_connected() ) { return false; } $download_link = $pro_install_app->get_download_link(); return ! empty( $download_link ); } private function get_ui_theme_preference(): string { $editor_preferences = SettingsManager::get_settings_managers( 'editorPreferences' ); $ui_theme = $editor_preferences->get_model()->get_settings( 'ui_theme' ); return $ui_theme ? $ui_theme : 'auto'; } private function get_user_display_name(): string { $library = $this->get_library_app(); if ( ! $library || ! $library->is_connected() ) { return ''; } $user = $library->get( 'user' ); return $user->first_name ?? ''; } public function should_show_starter(): bool { $progress = $this->progress_manager->get_progress(); return self::VERSION === get_option( self::ONBOARDING_OPTION ) && ! $progress->is_starter_dismissed(); } public function add_starter_packages( array $packages ): array { $packages[] = 'editor-starter'; return $packages; } public function add_starter_settings( array $settings ): array { $settings['starter'] = [ 'restPath' => 'elementor/v1/onboarding/user-progress', 'aiPlannerUrl' => 'https://planner.elementor.com/home.html', 'kitLibraryUrl' => Plugin::$instance->app->get_base_url() . '#/kit-library', ]; return $settings; } private function maybe_invalidate_theme_selection( User_Progress $progress, User_Choices $choices ): void { $selected_theme = $choices->get_theme_selection(); if ( empty( $selected_theme ) ) { return; } $active_theme = get_stylesheet(); if ( $active_theme !== $selected_theme ) { $completed = $this->filter_out_theme_selection_step( $progress->get_completed_steps() ); $progress->set_completed_steps( $completed ); $this->progress_manager->save_progress( $progress ); $choices->set_theme_selection( null ); $this->progress_manager->save_choices( $choices ); } } private function filter_out_theme_selection_step( array $steps ): array { return array_values( array_filter( $steps, function ( $step ) { return 'theme_selection' !== $step; } ) ); } private function get_translated_strings(): array { $locale = $this->get_onboarding_locale(); $api = new EditorAssetsAPI( [ EditorAssetsAPI::ASSETS_DATA_URL => self::ASSETS_BASE_URL . $locale . '.json', EditorAssetsAPI::ASSETS_DATA_TRANSIENT_KEY => '_elementor_onboarding_strings_' . $locale, EditorAssetsAPI::ASSETS_DATA_KEY => 'translations', ] ); return $api->get_assets_data(); } private function get_onboarding_locale(): string { static $flipped_locales = null; if ( null === $flipped_locales ) { $flipped_locales = array_flip( self::SUPPORTED_LOCALES ); } $user_locale = get_user_locale(); if ( isset( self::SUPPORTED_LOCALES[ $user_locale ] ) ) { return $user_locale; } $locale = substr( $user_locale, 0, 2 ); if ( isset( $flipped_locales[ $locale ] ) ) { return $flipped_locales[ $locale ]; } return 'en'; } private function get_steps_config(): array { $steps = [ [ 'id' => 'building_for', 'label' => __( 'Who are you building for?', 'elementor' ), 'type' => 'single', ], [ 'id' => 'site_about', 'label' => __( 'What is your site about?', 'elementor' ), 'type' => 'multiple', ], [ 'id' => 'experience_level', 'label' => __( 'How much experience do you have with Elementor?', 'elementor' ), 'type' => 'single', ], ]; if ( ! $this->is_elementor_theme_active() ) { $steps[] = [ 'id' => 'theme_selection', 'label' => __( 'Start with a theme that fits your needs', 'elementor' ), 'type' => 'single', ]; } if ( ! self::is_elementor_pro_installed() ) { $steps[] = [ 'id' => 'site_features', 'label' => __( 'What do you want to include in your site?', 'elementor' ), 'type' => 'multiple', ]; } return apply_filters( 'elementor/onboarding/steps', $steps ); } private static function is_elementor_pro_installed(): bool { $is_pro_installed = Utils::has_pro() || Utils::is_pro_installed_and_not_active(); return (bool) apply_filters( 'elementor/onboarding/is_elementor_pro_installed', $is_pro_installed ); } private function is_elementor_theme_active(): bool { $active_theme = get_stylesheet(); $is_active = in_array( $active_theme, Install_Theme::ALLOWED_THEMES, true ); return (bool) apply_filters( 'elementor/onboarding/is_elementor_theme_active', $is_active ); } } PK ��\F�/�P P &