PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 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 All 452 releases
elementor / modules / mcp / utils / editor-sync-state.php

editor-sync-state.php in Elementor Website Builder – more than just a page builder 4.3.0-beta3, at modules/mcp/utils/editor-sync-state.php

130 lines 3.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\Mcp\Utils;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 class Editor_Sync_State {
10
11 const EDITOR_UNSAVED_TTL = 300;
12 const MCP_MUTATION_TTL = 3600;
13
14 public function register_hooks(): void {
15 add_filter( 'elementor/mcp/pre_execute_guard', [ $this, 'check_mutation_guard' ], 10, 2 );
16 add_action( 'elementor/heartbeat/unsaved_signal', [ $this, 'handle_unsaved_signal' ], 10, 2 );
17 add_filter( 'elementor/heartbeat/mutation_marker', [ $this, 'build_mutation_marker' ], 10, 2 );
18 add_action( 'elementor/document/after_save', [ $this, 'on_document_saved' ] );
19 }
20
21 public function handle_unsaved_signal( int $post_id, $signal_value ): void {
22 if ( ! current_user_can( 'edit_post', $post_id ) ) {
23 return;
24 }
25 if ( $signal_value ) {
26 self::set_editor_unsaved( $post_id );
27 } else {
28 self::clear_editor_unsaved( $post_id );
29 }
30 }
31
32 public function build_mutation_marker( $default, int $post_id ): ?array {
33 $mutated_at = self::get_mcp_mutation_time( $post_id );
34 if ( ! $mutated_at ) {
35 return null;
36 }
37 return [
38 'post_id' => $post_id,
39 'mutated_at' => $mutated_at,
40 ];
41 }
42
43 public function check_mutation_guard( $error, $input ): ?\WP_Error {
44 $post_id = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
45
46 if ( $post_id <= 0 ) {
47 return null;
48 }
49
50 if ( ! function_exists( 'wp_check_post_lock' ) ) {
51 require_once ABSPATH . 'wp-admin/includes/post.php';
52 }
53
54 $has_lock = (bool) wp_check_post_lock( $post_id );
55 $has_unsaved = self::has_editor_unsaved( $post_id );
56
57 if ( ! $has_lock || ! $has_unsaved ) {
58 return null;
59 }
60
61 return new \WP_Error(
62 'elementor_editor_unsaved_changes',
63 __( 'The editor has unsaved changes for this document. Ask the user to save or discard their changes in the Elementor editor before retrying this operation.', 'elementor' ),
64 [
65 'status' => 409,
66 'post_id' => $post_id,
67 ]
68 );
69 }
70
71 public function on_document_saved( $document ): void {
72 $post_id = (int) $document->get_post()->ID;
73 self::clear_editor_unsaved( $post_id );
74 self::delete_mcp_mutation( $post_id );
75 }
76
77 private static function unsaved_key( int $post_id ): string {
78 return "_elementor_editor_unsaved_{$post_id}";
79 }
80
81 private static function mutation_key( int $post_id ): string {
82 return "_elementor_mcp_mutation_{$post_id}";
83 }
84
85 public static function set_editor_unsaved( int $post_id ): void {
86 if ( $post_id <= 0 ) {
87 return;
88 }
89 set_transient( self::unsaved_key( $post_id ), get_current_user_id(), self::EDITOR_UNSAVED_TTL );
90 }
91
92 public static function clear_editor_unsaved( int $post_id ): void {
93 if ( $post_id <= 0 ) {
94 return;
95 }
96 $owner = (int) get_transient( self::unsaved_key( $post_id ) );
97 if ( get_current_user_id() === $owner ) {
98 delete_transient( self::unsaved_key( $post_id ) );
99 }
100 }
101
102 public static function has_editor_unsaved( int $post_id ): bool {
103 if ( $post_id <= 0 ) {
104 return false;
105 }
106 return (bool) get_transient( self::unsaved_key( $post_id ) );
107 }
108
109 public static function set_mcp_mutation( int $post_id ): void {
110 if ( $post_id <= 0 ) {
111 return;
112 }
113 set_transient( self::mutation_key( $post_id ), time(), self::MCP_MUTATION_TTL );
114 }
115
116 public static function get_mcp_mutation_time( int $post_id ): int {
117 if ( $post_id <= 0 ) {
118 return 0;
119 }
120 return (int) get_transient( self::mutation_key( $post_id ) );
121 }
122
123 public static function delete_mcp_mutation( int $post_id ): void {
124 if ( $post_id <= 0 ) {
125 return;
126 }
127 delete_transient( self::mutation_key( $post_id ) );
128 }
129 }
130