PluginProbe ʕ •ᴥ•ʔ
Elementor Website Builder – more than just a page builder / 3.19.0-beta6
Elementor Website Builder – more than just a page builder v3.19.0-beta6
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 4.0.6 4.0.5 4.0.4 4.0.3 3.22.0-dev1 4.0.0-beta3 3.22.0-dev2 4.0.0-beta4 3.22.0-dev3 4.0.0-beta5 3.22.0-dev4 4.0.0-dev1 3.22.0-dev5 4.0.0-dev2 3.22.0-dev6 4.0.0-dev3 3.22.1 4.0.0-dev4 3.22.2 4.0.0-dev5 3.22.3 4.0.1 3.23.0 4.0.2 3.23.0-beta1 3.23.0-beta2 3.23.0-beta3 3.23.0-beta4 3.23.0-beta5 3.23.0-beta6 3.23.0-dev1 3.23.0-dev2 3.23.0-dev3 3.23.0-dev4 3.23.0-dev5 3.23.0-dev6 3.23.1 3.23.2 3.23.3 3.23.4 3.24.0 3.24.0-beta1 3.24.0-beta2 3.24.0-beta3 3.24.0-dev1 3.24.0-dev2 3.24.0-dev3 3.24.1 3.24.2 3.24.3 3.24.4 3.24.5 3.24.6 3.24.7 3.24.8 3.25.0 3.25.0-beta1 3.25.0-beta2 3.25.0-beta3 3.25.0-dev1 3.25.0-dev2 3.25.0-dev3 3.25.1 3.25.10 3.25.11 3.25.2 3.25.3 3.25.4 3.25.5 3.25.6 3.25.7 3.25.8 3.25.9 3.26.0 3.26.0-beta1 3.26.0-beta2 3.26.0-beta3 3.26.0-beta4 3.26.0-beta5 3.26.0-dev1 3.26.0-dev2 3.26.0-dev3 3.26.0-dev4 3.26.0-dev5 3.26.1 3.26.2 3.26.3 3.26.4 3.26.5 3.27.0 3.27.0-beta1 3.27.0-beta2 3.27.0-dev1 3.27.0-dev2 3.27.1 3.27.2 3.27.3 3.27.4 3.27.5 3.27.6 3.27.7 3.28.0 3.28.0-beta1 3.28.0-beta2 3.28.0-beta3 3.28.0-dev1 3.28.0-dev2 3.28.0-dev3 3.28.1 3.28.2 3.28.3 3.28.4 3.29.0 3.29.0-beta1 trunk 3.29.0-beta2 3.0.0 3.29.0-beta3 3.0.1 3.29.0-beta4 3.0.10 3.29.0-dev1 3.0.11 3.29.0-dev2 3.0.12 3.29.0-dev3 3.0.13 3.29.0-dev4 3.0.14 3.29.1 3.0.15 3.29.2 3.0.16 3.3.0 3.0.2 3.3.1 3.0.3 3.30.0 3.0.4 3.30.0-beta1 3.0.5 3.30.0-beta2 3.0.6 3.30.0-beta3 3.0.7 3.30.0-dev1 3.0.8 3.30.0-dev2 3.0.8.1 3.30.0-dev3 3.0.9 3.30.1 3.1.0 3.30.2 3.1.0-beta1 3.30.3 3.1.0-beta2 3.30.4 3.1.0-beta3 3.31.0 3.1.0-beta4 3.31.0-beta1 3.1.0-dev1 3.31.0-beta2 3.1.0-dev2 3.31.0-dev1 3.1.0-dev3 3.31.0-dev2 3.1.1 3.31.1 3.1.2 3.31.2 3.1.3 3.31.3 3.1.4 3.31.4 3.10.0 3.31.5 3.10.0-dev1 3.32.0 3.10.1 3.32.0-beta1 3.10.2 3.32.0-beta2 3.11.0 3.32.0-beta3 3.11.0-beta1 3.32.0-dev1 3.11.0-beta2 3.32.0-dev2 3.11.0-beta3 3.32.0-dev3 3.11.0-dev1 3.32.1 3.11.0-dev2 3.32.2 3.11.0-dev3 3.32.3 3.11.1 3.32.4 3.11.2 3.32.5 3.11.3 3.33.0 3.11.4 3.33.0-beta1 3.11.5 3.33.0-beta2 3.12.0 3.33.0-beta3 3.12.1 3.33.0-beta4 3.12.2 3.33.0-dev1 3.13.0 3.33.0-dev2 3.13.0-beta1 3.33.0-dev3 3.13.0-beta2 3.33.0-dev4 3.13.0-beta3 3.33.1 3.13.0-dev3 3.33.2 3.13.0-dev4 3.33.3 3.13.1 3.33.4 3.13.2 3.33.5 3.13.3 3.33.6 3.13.4 3.34.0 3.14.0 3.34.0-beta1 3.14.0-beta1 3.34.0-beta2 3.14.0-beta2 3.34.0-beta3 3.14.0-beta3 3.34.0-dev1 3.14.0-beta4 3.34.0-dev2 3.14.0-beta5 3.34.1 3.14.1 3.34.2 3.15.0 3.34.3 3.15.1 3.34.4 3.15.2 3.35.0 3.15.3 3.35.0-beta1 3.16.0 3.35.0-beta2 3.16.0-beta3 3.35.0-beta3 3.16.0-beta4 3.35.0-beta4 3.16.0-dev1 3.35.0-dev1 3.16.0-dev2 3.35.0-dev2 3.16.1 3.35.0-dev3 3.16.2 3.35.0-dev4 3.16.3 3.35.1 3.16.4 3.35.2 3.16.5 3.35.3 3.16.6 3.35.4 3.17.0 3.35.5 3.17.0-dev2 3.35.6 3.17.0-dev3 3.35.7 3.17.0-dev4 3.35.8 3.17.1 3.35.9 3.17.2 3.4.0 3.17.3 3.4.0-dev7 3.18.0 3.4.0-dev8 3.18.0-beta1 3.4.0-dev9 3.18.0-beta2 3.4.1 3.18.0-beta3 3.4.2 3.18.0-beta4 3.4.3 3.18.0-dev1 3.4.4 3.18.1 3.4.5 3.18.2 3.4.6 3.18.3 3.4.7 3.19.0 3.4.8 3.19.0-beta1 3.5.0 3.19.0-beta2 3.5.0-beta1 3.19.0-beta3 3.5.0-beta2 3.19.0-beta4 3.5.0-beta3 3.19.0-beta5 3.5.0-beta4 3.19.0-beta6 3.5.0-beta5 3.19.0-dev1 3.5.0-beta7 3.19.0-dev2 3.5.0-beta8 3.19.0-dev3 3.5.0-dev8 3.19.0-dev4 3.5.0-dev9 3.19.0-dev5 3.5.1 3.19.0-dev6 3.5.2 3.19.1 3.5.3 3.19.2 3.5.4 3.19.3 3.5.5 3.19.4 3.5.6 3.2.0 3.6.0 3.2.1 3.6.0-beta1 3.2.2 3.6.0-beta2 3.2.3 3.6.0-beta3 3.2.4 3.6.0-beta4 3.2.5 3.6.0-beta5 3.20.0 3.6.0-dev1 3.20.0-beta1 3.6.0-dev10 3.20.0-beta2 3.6.1 3.20.0-beta3 3.6.2 3.20.0-beta4 3.6.3 3.20.0-dev1 3.6.4 3.20.0-dev2 3.6.5 3.20.0-dev3 3.6.6 3.20.0-dev4 3.6.7 3.20.1 3.6.8 3.20.2 3.7.0 3.20.3 3.7.0-beta1 3.20.4 3.7.0-beta2 3.21.0 3.7.0-beta3 3.21.0-beta1 3.7.0-beta4 3.21.0-beta2 3.7.0-dev1 3.21.0-beta3 3.7.1 3.21.0-dev1 3.7.2 3.21.0-dev2 3.7.3 3.21.0-dev3 3.7.4 3.21.1 3.7.5 3.21.2 3.7.6 3.21.3 3.7.7 3.21.4 3.7.8 3.21.5 3.8.0 3.21.6 3.8.0-beta1 3.21.7 3.8.0-beta2 3.21.8 3.8.0-beta3 3.22.0 3.8.1 3.22.0-beta1 3.9.0 3.22.0-beta2 3.9.1 3.22.0-beta3 3.9.2 3.22.0-beta4 4.0.0 3.22.0-beta5 4.0.0-beta1 3.22.0-beta6 4.0.0-beta2
elementor / core / kits / manager.php
elementor / core / kits Last commit date
controls 3 years ago documents 2 years ago views 2 years ago manager.php 2 years ago
manager.php
480 lines
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 private $should_skip_trash_kit_confirmation = false;
29
30 public function get_active_id() {
31 return get_option( self::OPTION_ACTIVE );
32 }
33
34 public function get_previous_id() {
35 return get_option( self::OPTION_PREVIOUS );
36 }
37
38 public function get_kit( $kit_id ) {
39 $kit = Plugin::$instance->documents->get( $kit_id );
40
41 if ( ! $this->is_valid_kit( $kit ) ) {
42 return $this->get_empty_kit_instance();
43 }
44
45 return $kit;
46 }
47
48 public function get_active_kit() {
49 return $this->get_kit( $this->get_active_id() );
50 }
51
52 public function get_active_kit_for_frontend() {
53 $kit = Plugin::$instance->documents->get_doc_for_frontend( $this->get_active_id() );
54
55 if ( ! $this->is_valid_kit( $kit ) ) {
56 return $this->get_empty_kit_instance();
57 }
58
59 return $kit;
60 }
61
62 /**
63 * @param $kit
64 *
65 * @return bool
66 */
67 private function is_valid_kit( $kit ) {
68 return $kit && $kit instanceof Kit && 'trash' !== $kit->get_main_post()->post_status;
69 }
70
71 /**
72 * Returns an empty kit for situation when there is no kit in the site.
73 *
74 * @return Kit
75 * @throws \Exception
76 */
77 private function get_empty_kit_instance() {
78 return new Kit( [
79 'settings' => [],
80 'post_id' => 0,
81 ] );
82 }
83
84 /**
85 * Checks if specific post is a kit.
86 *
87 * @param $post_id
88 *
89 * @return bool
90 */
91 public function is_kit( $post_id ) {
92 $document = Plugin::$instance->documents->get( $post_id );
93
94 return $document && $document instanceof Kit && ! $document->is_revision();
95 }
96
97
98 /**
99 * Init kit controls.
100 *
101 * A temp solution in order to avoid init kit group control from within another group control.
102 *
103 * 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
104 * and because the group control is a singleton, its args are changed to the last kit group control.
105 */
106 public function init_kit_controls() {
107 $this->get_active_kit_for_frontend()->get_settings();
108 }
109
110 public function get_current_settings( $setting = null ) {
111 $kit = $this->get_active_kit_for_frontend();
112
113 if ( ! $kit ) {
114 return '';
115 }
116
117 return $kit->get_settings( $setting );
118 }
119
120 public function create( array $kit_data = [], array $kit_meta_data = [] ) {
121 $default_kit_data = [
122 'post_status' => 'publish',
123 ];
124
125 $kit_data = array_merge( $default_kit_data, $kit_data );
126
127 $kit_data['post_type'] = Source_Local::CPT;
128
129 $kit = Plugin::$instance->documents->create( 'kit', $kit_data, $kit_meta_data );
130
131 if ( isset( $kit_data['settings'] ) ) {
132 $kit->save( [ 'settings' => $kit_data['settings'] ] );
133 }
134
135 return $kit->get_id();
136 }
137
138 public function create_new_kit( $kit_name = '', $settings = [], $active = true ) {
139 $kit_name = $kit_name ? $kit_name : esc_html__( 'Custom', 'elementor' );
140
141 $id = $this->create( [
142 'post_title' => $kit_name,
143 'settings' => $settings,
144 ] );
145
146 if ( $active ) {
147 update_option( self::OPTION_PREVIOUS, $this->get_active_id() );
148 update_option( self::OPTION_ACTIVE, $id );
149 }
150
151 return $id;
152 }
153
154 public function create_default() {
155 return $this->create( [
156 'post_title' => esc_html__( 'Default Kit', 'elementor' ),
157 ] );
158 }
159
160 /**
161 * Create a default kit if needed.
162 *
163 * This action runs on activation hook, all the Plugin components do not exists and
164 * the Document manager and Kits manager instances cannot be used.
165 *
166 * @return int|void|\WP_Error
167 */
168 public static function create_default_kit() {
169 if ( get_option( self::OPTION_ACTIVE ) ) {
170 return;
171 }
172
173 $id = wp_insert_post( [
174 'post_title' => esc_html__( 'Default Kit', 'elementor' ),
175 'post_type' => Source_Local::CPT,
176 'post_status' => 'publish',
177 'meta_input' => [
178 '_elementor_edit_mode' => 'builder',
179 Document::TYPE_META_KEY => 'kit',
180 ],
181 ] );
182
183 update_option( self::OPTION_ACTIVE, $id );
184
185 return $id;
186 }
187
188 /**
189 * @param $imported_kit_id int The id of the imported kit that should be deleted.
190 * @param $active_kit_id int The id of the kit that should set as 'active_kit' after the deletion.
191 * @param $previous_kit_id int The id of the kit that should set as 'previous_kit' after the deletion.
192 * @return void
193 */
194 public function revert( int $imported_kit_id, int $active_kit_id, int $previous_kit_id ) {
195 // If the kit that should set as active is not a valid kit then abort the revert.
196 if ( ! $this->is_kit( $active_kit_id ) ) {
197 return;
198 }
199
200 // This a hacky solution to avoid from the revert process to be interrupted by the `trash_kit_confirmation`.
201 $this->should_skip_trash_kit_confirmation = true;
202
203 $kit = $this->get_kit( $imported_kit_id );
204 $kit->force_delete();
205
206 $this->should_skip_trash_kit_confirmation = false;
207
208 update_option( self::OPTION_ACTIVE, $active_kit_id );
209
210 if ( $this->is_kit( $previous_kit_id ) ) {
211 update_option( self::OPTION_PREVIOUS, $previous_kit_id );
212 }
213 }
214
215 /**
216 * @param Documents_Manager $documents_manager
217 */
218 public function register_document( $documents_manager ) {
219 $documents_manager->register_document_type( 'kit', Kit::get_class_full_name() );
220 }
221
222 public function localize_settings( $settings ) {
223 $kit = $this->get_active_kit();
224 $kit_controls = $kit->get_controls();
225 $design_system_controls = [
226 'colors' => $kit_controls['system_colors']['fields'],
227 'typography' => $kit_controls['system_typography']['fields'],
228 ];
229
230 $settings = array_replace_recursive( $settings, [
231 'kit_id' => $kit->get_main_id(),
232 'kit_config' => [
233 'typography_prefix' => Global_Typography::TYPOGRAPHY_GROUP_PREFIX,
234 'design_system_controls' => $design_system_controls,
235 ],
236 'user' => [
237 'can_edit_kit' => $kit->is_editable_by_current_user(),
238 ],
239 ] );
240
241 return $settings;
242 }
243
244 public function preview_enqueue_styles() {
245 $kit = $this->get_kit_for_frontend();
246
247 if ( $kit ) {
248 // On preview, the global style is not enqueued.
249 $this->frontend_before_enqueue_styles();
250
251 Plugin::$instance->frontend->print_fonts_links();
252 }
253 }
254
255 public function frontend_before_enqueue_styles() {
256 $kit = $this->get_kit_for_frontend();
257
258 if ( $kit ) {
259 if ( $kit->is_autosave() ) {
260 $css_file = Post_Preview::create( $kit->get_id() );
261 } else {
262 $css_file = Post_CSS::create( $kit->get_id() );
263 }
264
265 $css_file->enqueue();
266 }
267 }
268
269 public function render_panel_html() {
270 require __DIR__ . '/views/panel.php';
271 }
272
273 public function get_kit_for_frontend() {
274 $kit = false;
275 $active_kit = $this->get_active_kit();
276 $is_kit_preview = is_preview() && isset( $_GET['preview_id'] ) && $active_kit->get_main_id() === (int) $_GET['preview_id'];
277
278 if ( $is_kit_preview ) {
279 $kit = Plugin::$instance->documents->get_doc_or_auto_save( $active_kit->get_main_id(), get_current_user_id() );
280 } elseif ( 'publish' === $active_kit->get_main_post()->post_status ) {
281 $kit = $active_kit;
282 }
283
284 return $kit;
285 }
286
287 public function update_kit_settings_based_on_option( $key, $value ) {
288 /** @var Kit $active_kit */
289 $active_kit = $this->get_active_kit();
290
291 if ( $active_kit->is_saving() ) {
292 return;
293 }
294
295 $active_kit->update_settings( [ $key => $value ] );
296 }
297
298 /**
299 * Map Scheme To Global
300 *
301 * Convert a given scheme value to its corresponding default global value
302 *
303 * @param string $type 'color'/'typography'
304 * @param $value
305 * @return mixed
306 */
307 private function map_scheme_to_global( $type, $value ) {
308 $schemes_to_globals_map = [
309 'color' => [
310 '1' => Global_Colors::COLOR_PRIMARY,
311 '2' => Global_Colors::COLOR_SECONDARY,
312 '3' => Global_Colors::COLOR_TEXT,
313 '4' => Global_Colors::COLOR_ACCENT,
314 ],
315 'typography' => [
316 '1' => Global_Typography::TYPOGRAPHY_PRIMARY,
317 '2' => Global_Typography::TYPOGRAPHY_SECONDARY,
318 '3' => Global_Typography::TYPOGRAPHY_TEXT,
319 '4' => Global_Typography::TYPOGRAPHY_ACCENT,
320 ],
321 ];
322
323 return $schemes_to_globals_map[ $type ][ $value ];
324 }
325
326 /**
327 * Convert Scheme to Default Global
328 *
329 * If a control has a scheme property, convert it to a default Global.
330 *
331 * @param $scheme - Control scheme property
332 * @return array - Control/group control args
333 * @since 3.0.0
334 * @access public
335 */
336 public function convert_scheme_to_global( $scheme ) {
337 if ( isset( $scheme['type'] ) && isset( $scheme['value'] ) ) {
338 //_deprecated_argument( $args['scheme'], '3.0.0', 'Schemes are now deprecated - use $args[\'global\'] instead.' );
339 return $this->map_scheme_to_global( $scheme['type'], $scheme['value'] );
340 }
341
342 // Typography control 'scheme' properties usually only include the string with the typography value ('1'-'4').
343 return $this->map_scheme_to_global( 'typography', $scheme );
344 }
345
346 public function register_controls() {
347 $controls_manager = Plugin::$instance->controls_manager;
348
349 $controls_manager->register( new Repeater() );
350 }
351
352 public function is_custom_colors_enabled() {
353 return ! get_option( 'elementor_disable_color_schemes' );
354 }
355
356 public function is_custom_typography_enabled() {
357 return ! get_option( 'elementor_disable_typography_schemes' );
358 }
359
360 /**
361 * Add kit wrapper body class.
362 *
363 * It should be added even for non Elementor pages,
364 * in order to support embedded templates.
365 */
366 private function add_body_class() {
367 $kit = $this->get_kit_for_frontend();
368
369 if ( $kit ) {
370 Plugin::$instance->frontend->add_body_class( 'elementor-kit-' . $kit->get_main_id() );
371 }
372 }
373
374 /**
375 * Send a confirm message before move a kit to trash, or if delete permanently not for trash.
376 *
377 * @param $post_id
378 * @param false $is_permanently_delete
379 */
380 private function before_delete_kit( $post_id, $is_permanently_delete = false ) {
381 if ( $this->should_skip_trash_kit_confirmation ) {
382 return;
383 }
384
385 $document = Plugin::$instance->documents->get( $post_id );
386
387 if (
388 ! $document ||
389 ! $this->is_kit( $post_id ) ||
390 isset( $_GET['force_delete_kit'] ) || // phpcs:ignore -- nonce validation is not require here.
391 ( $is_permanently_delete && $document->is_trash() )
392 ) {
393 return;
394 }
395
396 ob_start();
397 require __DIR__ . '/views/trash-kit-confirmation.php';
398
399 $confirmation_content = ob_get_clean();
400
401 // PHPCS - the content does not contain user input value.
402 wp_die( new \WP_Error( 'cant_delete_kit', $confirmation_content ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
403 }
404
405 /**
406 * Add 'Edit with elementor -> Site Settings' in admin bar.
407 *
408 * @param [] $admin_bar_config
409 *
410 * @return array $admin_bar_config
411 */
412 private function add_menu_in_admin_bar( $admin_bar_config ) {
413 $document = Plugin::$instance->documents->get( get_the_ID() );
414
415 if ( ! $document || ! $document->is_built_with_elementor() ) {
416 $recent_edited_post = Utils::get_recently_edited_posts_query( [
417 'posts_per_page' => 1,
418 ] );
419
420 if ( $recent_edited_post->post_count ) {
421 $posts = $recent_edited_post->get_posts();
422 $document = Plugin::$instance->documents->get( reset( $posts )->ID );
423 }
424 }
425
426 if ( $document ) {
427 $document_edit_url = add_query_arg(
428 [
429 'active-document' => $this->get_active_id(),
430 ],
431 $document->get_edit_url()
432 );
433
434 $admin_bar_config['elementor_edit_page']['children'][] = [
435 'id' => 'elementor_site_settings',
436 'title' => esc_html__( 'Site Settings', 'elementor' ),
437 'sub_title' => esc_html__( 'Site', 'elementor' ),
438 'href' => $document_edit_url,
439 'class' => 'elementor-site-settings',
440 'parent_class' => 'elementor-second-section',
441 ];
442 }
443
444 return $admin_bar_config;
445 }
446
447 public function __construct() {
448 add_action( 'elementor/documents/register', [ $this, 'register_document' ] );
449 add_filter( 'elementor/editor/localize_settings', [ $this, 'localize_settings' ] );
450 add_filter( 'elementor/editor/footer', [ $this, 'render_panel_html' ] );
451 add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'frontend_before_enqueue_styles' ], 0 );
452 add_action( 'elementor/preview/enqueue_styles', [ $this, 'preview_enqueue_styles' ], 0 );
453 add_action( 'elementor/controls/register', [ $this, 'register_controls' ] );
454
455 add_action( 'wp_trash_post', function ( $post_id ) {
456 $this->before_delete_kit( $post_id );
457 } );
458
459 add_action( 'before_delete_post', function ( $post_id ) {
460 $this->before_delete_kit( $post_id, true );
461 } );
462
463 add_action( 'update_option_blogname', function ( $old_value, $value ) {
464 $this->update_kit_settings_based_on_option( 'site_name', $value );
465 }, 10, 2 );
466
467 add_action( 'update_option_blogdescription', function ( $old_value, $value ) {
468 $this->update_kit_settings_based_on_option( 'site_description', $value );
469 }, 10, 2 );
470
471 add_action( 'wp_head', function() {
472 $this->add_body_class();
473 } );
474
475 add_filter( 'elementor/frontend/admin_bar/settings', function ( $admin_bar_config ) {
476 return $this->add_menu_in_admin_bar( $admin_bar_config );
477 }, 9 /* Before site-editor (theme-builder) */ );
478 }
479 }
480