PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.4
Elementor Website Builder – more than just a page builder v3.6.4
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / kits / manager.php

manager.php in Elementor Website Builder – more than just a page builder 3.6.4, at core/kits/manager.php

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