芝麻web文件管理V1.00
编辑当前文件:/home/conskgoa/doughi.co.uk/app.zip
PK ,\Lm view.phpnu [ get_elementor_ui_theme_preference() ? 'eps-theme-dark' : ''; ?> >
PK ,\zE- - modules/site-editor/module.phpnu [ 'elementor_app_site_editor', 'title' => esc_html__( 'Theme Builder', 'elementor' ), 'sub_title' => esc_html__( 'Site', 'elementor' ), 'href' => Plugin::$instance->app->get_settings( 'menu_url' ), 'class' => 'elementor-app-link', 'parent_class' => 'elementor-second-section', ]; return $admin_bar_config; } public function __construct() { add_filter( 'elementor/frontend/admin_bar/settings', [ $this, 'add_menu_in_admin_bar' ] ); // After kit (Site settings) } } PK ,\SI$E E 0 modules/onboarding/validation/base-validator.phpnu [ 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 ,\[a?S S 9 modules/onboarding/validation/user-progress-validator.phpnu [ [ '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 ,\E E 8 modules/onboarding/validation/user-choices-validator.phpnu [ [ '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 ,\lP) ) modules/onboarding/module.phpnu [ '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(), 'signUp' => $this->get_connect_url( 'signup' ), '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 $screen_hint = '' ): 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', 'screen_hint' => $screen_hint, ] ) ?? ''; } 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 ,\6v<l l : modules/onboarding/storage/onboarding-progress-manager.phpnu [ 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 [ 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 [ 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 ,\F/P P &