balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

manager.php (11707B)


      1 <?php
      2 namespace Elementor\Core\Kits;
      3 
      4 use Elementor\Core\Base\Document;
      5 use Elementor\Core\Kits\Controls\Repeater;
      6 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
      7 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
      8 use Elementor\Plugin;
      9 use Elementor\Core\Files\CSS\Post as Post_CSS;
     10 use Elementor\Core\Files\CSS\Post_Preview as Post_Preview;
     11 use Elementor\Core\Documents_Manager;
     12 use Elementor\Core\Kits\Documents\Kit;
     13 use Elementor\TemplateLibrary\Source_Local;
     14 use Elementor\Utils;
     15 
     16 if ( ! defined( 'ABSPATH' ) ) {
     17 	exit; // Exit if accessed directly.
     18 }
     19 
     20 class Manager {
     21 
     22 	const OPTION_ACTIVE = 'elementor_active_kit';
     23 
     24 	const E_HASH_COMMAND_OPEN_SITE_SETTINGS = 'e:run:panel/global/open';
     25 
     26 	public function get_active_id() {
     27 		return get_option( self::OPTION_ACTIVE );
     28 	}
     29 
     30 	public function get_active_kit() {
     31 		$kit = Plugin::$instance->documents->get( $this->get_active_id() );
     32 
     33 		if ( ! $this->is_valid_kit( $kit ) ) {
     34 			return $this->get_empty_kit_instance();
     35 		}
     36 
     37 		return $kit;
     38 	}
     39 
     40 	public function get_active_kit_for_frontend() {
     41 		$kit = Plugin::$instance->documents->get_doc_for_frontend( $this->get_active_id() );
     42 
     43 		if ( ! $this->is_valid_kit( $kit ) ) {
     44 			return $this->get_empty_kit_instance();
     45 		}
     46 
     47 		return $kit;
     48 	}
     49 
     50 	/**
     51 	 * @param $kit
     52 	 *
     53 	 * @return bool
     54 	 */
     55 	private function is_valid_kit( $kit ) {
     56 		return $kit && $kit instanceof Kit && 'trash' !== $kit->get_main_post()->post_status;
     57 	}
     58 
     59 	/**
     60 	 * Returns an empty kit for situation when there is no kit in the site.
     61 	 *
     62 	 * @return Kit
     63 	 * @throws \Exception
     64 	 */
     65 	private function get_empty_kit_instance() {
     66 		return new Kit( [
     67 			'settings' => [],
     68 			'post_id' => 0,
     69 		] );
     70 	}
     71 
     72 	/**
     73 	 * Checks if specific post is a kit.
     74 	 *
     75 	 * @param $post_id
     76 	 *
     77 	 * @return bool
     78 	 */
     79 	public function is_kit( $post_id ) {
     80 		$document = Plugin::$instance->documents->get( $post_id );
     81 
     82 		return $document && $document instanceof Kit && ! $document->is_revision();
     83 	}
     84 
     85 
     86 	/**
     87 	 * Init kit controls.
     88 	 *
     89 	 * A temp solution in order to avoid init kit group control from within another group control.
     90 	 *
     91 	 * After moving the `default_font` to the kit, the Typography group control cause initialize the kit controls at: https://github.com/elementor/elementor/blob/e6e1db9eddef7e3c1a5b2ba0c2338e2af2a3bfe3/includes/controls/groups/typography.php#L91
     92 	 * and because the group control is a singleton, its args are changed to the last kit group control.
     93 	 */
     94 	public function init_kit_controls() {
     95 		$this->get_active_kit_for_frontend()->get_settings();
     96 	}
     97 
     98 	public function get_current_settings( $setting = null ) {
     99 		$kit = $this->get_active_kit_for_frontend();
    100 
    101 		if ( ! $kit ) {
    102 			return '';
    103 		}
    104 
    105 		return $kit->get_settings( $setting );
    106 	}
    107 
    108 	public function create( array $kit_data = [], array $kit_meta_data = [] ) {
    109 		$default_kit_data = [
    110 			'post_status' => 'publish',
    111 		];
    112 
    113 		$kit_data = array_merge( $default_kit_data, $kit_data );
    114 
    115 		$kit_data['post_type'] = Source_Local::CPT;
    116 
    117 		$kit = Plugin::$instance->documents->create( 'kit', $kit_data, $kit_meta_data );
    118 
    119 		return $kit->get_id();
    120 	}
    121 
    122 	public function create_default() {
    123 		return $this->create( [
    124 			'post_title' => esc_html__( 'Default Kit', 'elementor' ),
    125 		] );
    126 	}
    127 
    128 	/**
    129 	 * Create a default kit if needed.
    130 	 *
    131 	 * This action runs on activation hook, all the Plugin components do not exists and
    132 	 * the Document manager and Kits manager instances cannot be used.
    133 	 *
    134 	 * @return int|void|\WP_Error
    135 	 */
    136 	public static function create_default_kit() {
    137 		if ( get_option( self::OPTION_ACTIVE ) ) {
    138 			return;
    139 		}
    140 
    141 		$id = wp_insert_post( [
    142 			'post_title' => __( 'Default Kit', 'elementor' ),
    143 			'post_type' => Source_Local::CPT,
    144 			'post_status' => 'publish',
    145 			'meta_input' => [
    146 				'_elementor_edit_mode' => 'builder',
    147 				Document::TYPE_META_KEY => 'kit',
    148 			],
    149 		] );
    150 
    151 		update_option( self::OPTION_ACTIVE, $id );
    152 
    153 		return $id;
    154 	}
    155 
    156 	/**
    157 	 * @param Documents_Manager $documents_manager
    158 	 */
    159 	public function register_document( $documents_manager ) {
    160 		$documents_manager->register_document_type( 'kit', Kit::get_class_full_name() );
    161 	}
    162 
    163 	public function localize_settings( $settings ) {
    164 		$kit = $this->get_active_kit();
    165 		$kit_controls = $kit->get_controls();
    166 		$design_system_controls = [
    167 			'colors' => $kit_controls['system_colors']['fields'],
    168 			'typography' => $kit_controls['system_typography']['fields'],
    169 		];
    170 
    171 		$settings = array_replace_recursive( $settings, [
    172 			'kit_id' => $kit->get_main_id(),
    173 			'kit_config' => [
    174 				'typography_prefix' => Global_Typography::TYPOGRAPHY_GROUP_PREFIX,
    175 				'design_system_controls' => $design_system_controls,
    176 			],
    177 			'user' => [
    178 				'can_edit_kit' => $kit->is_editable_by_current_user(),
    179 			],
    180 		] );
    181 
    182 		return $settings;
    183 	}
    184 
    185 	public function preview_enqueue_styles() {
    186 		$kit = $this->get_kit_for_frontend();
    187 
    188 		if ( $kit ) {
    189 			// On preview, the global style is not enqueued.
    190 			$this->frontend_before_enqueue_styles();
    191 
    192 			Plugin::$instance->frontend->print_fonts_links();
    193 		}
    194 	}
    195 
    196 	public function frontend_before_enqueue_styles() {
    197 		$kit = $this->get_kit_for_frontend();
    198 
    199 		if ( $kit ) {
    200 			if ( $kit->is_autosave() ) {
    201 				$css_file = Post_Preview::create( $kit->get_id() );
    202 			} else {
    203 				$css_file = Post_CSS::create( $kit->get_id() );
    204 			}
    205 
    206 			$css_file->enqueue();
    207 		}
    208 	}
    209 
    210 	public function render_panel_html() {
    211 		require __DIR__ . '/views/panel.php';
    212 	}
    213 
    214 	public function get_kit_for_frontend() {
    215 		$kit = false;
    216 		$active_kit = $this->get_active_kit();
    217 		$is_kit_preview = is_preview() && isset( $_GET['preview_id'] ) && $active_kit->get_main_id() === (int) $_GET['preview_id'];
    218 
    219 		if ( $is_kit_preview ) {
    220 			$kit = Plugin::$instance->documents->get_doc_or_auto_save( $active_kit->get_main_id(), get_current_user_id() );
    221 		} elseif ( 'publish' === $active_kit->get_main_post()->post_status ) {
    222 			$kit = $active_kit;
    223 		}
    224 
    225 		return $kit;
    226 	}
    227 
    228 	public function update_kit_settings_based_on_option( $key, $value ) {
    229 		/** @var Kit $active_kit */
    230 		$active_kit = $this->get_active_kit();
    231 
    232 		if ( $active_kit->is_saving() ) {
    233 			return;
    234 		}
    235 
    236 		$active_kit->update_settings( [ $key => $value ] );
    237 	}
    238 
    239 	/**
    240 	 * Map Scheme To Global
    241 	 *
    242 	 * Convert a given scheme value to its corresponding default global value
    243 	 *
    244 	 * @param string $type 'color'/'typography'
    245 	 * @param $value
    246 	 * @return mixed
    247 	 */
    248 	private function map_scheme_to_global( $type, $value ) {
    249 		$schemes_to_globals_map = [
    250 			'color' => [
    251 				'1' => Global_Colors::COLOR_PRIMARY,
    252 				'2' => Global_Colors::COLOR_SECONDARY,
    253 				'3' => Global_Colors::COLOR_TEXT,
    254 				'4' => Global_Colors::COLOR_ACCENT,
    255 			],
    256 			'typography' => [
    257 				'1' => Global_Typography::TYPOGRAPHY_PRIMARY,
    258 				'2' => Global_Typography::TYPOGRAPHY_SECONDARY,
    259 				'3' => Global_Typography::TYPOGRAPHY_TEXT,
    260 				'4' => Global_Typography::TYPOGRAPHY_ACCENT,
    261 			],
    262 		];
    263 
    264 		return $schemes_to_globals_map[ $type ][ $value ];
    265 	}
    266 
    267 	/**
    268 	 * Convert Scheme to Default Global
    269 	 *
    270 	 * If a control has a scheme property, convert it to a default Global.
    271 	 *
    272 	 * @param $scheme - Control scheme property
    273 	 * @return array - Control/group control args
    274 	 * @since 3.0.0
    275 	 * @access public
    276 	 */
    277 	public function convert_scheme_to_global( $scheme ) {
    278 		if ( isset( $scheme['type'] ) && isset( $scheme['value'] ) ) {
    279 			//_deprecated_argument( $args['scheme'], '3.0.0', 'Schemes are now deprecated - use $args[\'global\'] instead.' );
    280 			return $this->map_scheme_to_global( $scheme['type'], $scheme['value'] );
    281 		}
    282 
    283 		// Typography control 'scheme' properties usually only include the string with the typography value ('1'-'4').
    284 		return $this->map_scheme_to_global( 'typography', $scheme );
    285 	}
    286 
    287 	public function register_controls() {
    288 		$controls_manager = Plugin::$instance->controls_manager;
    289 
    290 		$controls_manager->register_control( Repeater::CONTROL_TYPE, new Repeater() );
    291 	}
    292 
    293 	public function is_custom_colors_enabled() {
    294 		return ! get_option( 'elementor_disable_color_schemes' );
    295 	}
    296 
    297 	public function is_custom_typography_enabled() {
    298 		return ! get_option( 'elementor_disable_typography_schemes' );
    299 	}
    300 
    301 	/**
    302 	 * Add kit wrapper body class.
    303 	 *
    304 	 * It should be added even for non Elementor pages,
    305 	 * in order to support embedded templates.
    306 	 */
    307 	private function add_body_class() {
    308 		$kit = $this->get_kit_for_frontend();
    309 
    310 		if ( $kit ) {
    311 			Plugin::$instance->frontend->add_body_class( 'elementor-kit-' . $kit->get_main_id() );
    312 		}
    313 	}
    314 
    315 	/**
    316 	 * Send a confirm message before move a kit to trash, or if delete permanently not for trash.
    317 	 *
    318 	 * @param       $post_id
    319 	 * @param false $is_permanently_delete
    320 	 */
    321 	private function before_delete_kit( $post_id, $is_permanently_delete = false ) {
    322 		$document = Plugin::$instance->documents->get( $post_id );
    323 
    324 		if (
    325 			! $document ||
    326 			! $this->is_kit( $post_id ) ||
    327 			isset( $_GET['force_delete_kit'] ) ||  // phpcs:ignore -- nonce validation is not require here.
    328 			( $is_permanently_delete && $document->is_trash() )
    329 		) {
    330 			return;
    331 		}
    332 
    333 		ob_start();
    334 		require __DIR__ . '/views/trash-kit-confirmation.php';
    335 
    336 		$confirmation_content = ob_get_clean();
    337 
    338 		// PHPCS - the content does not contain user input value.
    339 		wp_die( new \WP_Error( 'cant_delete_kit', $confirmation_content ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    340 	}
    341 
    342 	/**
    343 	 * Add 'Edit with elementor -> Site Settings' in admin bar.
    344 	 *
    345 	 * @param [] $admin_bar_config
    346 	 *
    347 	 * @return array $admin_bar_config
    348 	 */
    349 	private function add_menu_in_admin_bar( $admin_bar_config ) {
    350 		$document = Plugin::$instance->documents->get( get_the_ID() );
    351 
    352 		if ( ! $document || ! $document->is_built_with_elementor() ) {
    353 			$recent_edited_post = Utils::get_recently_edited_posts_query( [
    354 				'posts_per_page' => 1,
    355 			] );
    356 
    357 			if ( $recent_edited_post->post_count ) {
    358 				$posts = $recent_edited_post->get_posts();
    359 				$document = Plugin::$instance->documents->get( reset( $posts )->ID );
    360 			}
    361 		}
    362 
    363 		if ( $document ) {
    364 			$admin_bar_config['elementor_edit_page']['children'][] = [
    365 				'id' => 'elementor_site_settings',
    366 				'title' => esc_html__( 'Site Settings', 'elementor' ),
    367 				'sub_title' => esc_html__( 'Site', 'elementor' ),
    368 				'href' => $document->get_edit_url() . '#' . self::E_HASH_COMMAND_OPEN_SITE_SETTINGS,
    369 				'class' => 'elementor-site-settings',
    370 				'parent_class' => 'elementor-second-section',
    371 			];
    372 		}
    373 
    374 		return $admin_bar_config;
    375 	}
    376 
    377 	public function __construct() {
    378 		add_action( 'elementor/documents/register', [ $this, 'register_document' ] );
    379 		add_filter( 'elementor/editor/localize_settings', [ $this, 'localize_settings' ] );
    380 		add_filter( 'elementor/editor/footer', [ $this, 'render_panel_html' ] );
    381 		add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'frontend_before_enqueue_styles' ], 0 );
    382 		add_action( 'elementor/preview/enqueue_styles', [ $this, 'preview_enqueue_styles' ], 0 );
    383 		add_action( 'elementor/controls/controls_registered', [ $this, 'register_controls' ] );
    384 
    385 		add_action( 'wp_trash_post', function ( $post_id ) {
    386 			$this->before_delete_kit( $post_id );
    387 		} );
    388 
    389 		add_action( 'before_delete_post', function ( $post_id ) {
    390 			$this->before_delete_kit( $post_id, true );
    391 		} );
    392 
    393 		add_action( 'update_option_blogname', function ( $old_value, $value ) {
    394 			$this->update_kit_settings_based_on_option( 'site_name', $value );
    395 		}, 10, 2 );
    396 
    397 		add_action( 'update_option_blogdescription', function ( $old_value, $value ) {
    398 			$this->update_kit_settings_based_on_option( 'site_description', $value );
    399 		}, 10, 2 );
    400 
    401 		add_action( 'wp_head', function() {
    402 			$this->add_body_class();
    403 		} );
    404 
    405 		add_filter( 'elementor/frontend/admin_bar/settings', function ( $admin_bar_config ) {
    406 			return $this->add_menu_in_admin_bar( $admin_bar_config );
    407 		}, 9 /* Before site-editor (theme-builder) */ );
    408 	}
    409 }