PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.2
Elementor Website Builder – more than just a page builder v3.6.2
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 / modules / history / revisions-manager.php

revisions-manager.php in Elementor Website Builder – more than just a page builder 3.6.2, at modules/history/revisions-manager.php

422 lines 10.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Modules\History;
3
4 use Elementor\Core\Base\Document;
5 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
6 use Elementor\Core\Files\CSS\Post as Post_CSS;
7 use Elementor\Plugin;
8 use Elementor\Utils;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly.
12 }
13
14 /**
15 * Elementor history revisions manager.
16 *
17 * Elementor history revisions manager handler class is responsible for
18 * registering and managing Elementor revisions manager.
19 *
20 * @since 1.7.0
21 */
22 class Revisions_Manager {
23
24 /**
25 * Maximum number of revisions to display.
26 */
27 const MAX_REVISIONS_TO_DISPLAY = 100;
28
29 /**
30 * Authors list.
31 *
32 * Holds all the authors.
33 *
34 * @access private
35 *
36 * @var array
37 */
38 private static $authors = [];
39
40 /**
41 * History revisions manager constructor.
42 *
43 * Initializing Elementor history revisions manager.
44 *
45 * @since 1.7.0
46 * @access public
47 */
48 public function __construct() {
49 self::register_actions();
50 }
51
52 /**
53 * @since 1.7.0
54 * @access public
55 * @static
56 */
57 public static function handle_revision() {
58 add_filter( 'wp_save_post_revision_check_for_changes', '__return_false' );
59 }
60
61 /**
62 * @since 2.0.0
63 * @access public
64 * @static
65 *
66 * @param $post_content
67 * @param $post_id
68 *
69 * @return string
70 */
71 public static function avoid_delete_auto_save( $post_content, $post_id ) {
72 // Add a temporary string in order the $post will not be equal to the $autosave
73 // in edit-form-advanced.php:210
74 $document = Plugin::$instance->documents->get( $post_id );
75
76 if ( $document && $document->is_built_with_elementor() ) {
77 $post_content .= '<!-- Created with Elementor -->';
78 }
79
80 return $post_content;
81 }
82
83 /**
84 * @since 2.0.0
85 * @access public
86 * @static
87 */
88 public static function remove_temp_post_content() {
89 global $post;
90
91 $document = Plugin::$instance->documents->get( $post->ID );
92
93 if ( ! $document || ! $document->is_built_with_elementor() ) {
94 return;
95 }
96
97 $post->post_content = str_replace( '<!-- Created with Elementor -->', '', $post->post_content );
98 }
99
100 /**
101 * @since 1.7.0
102 * @access public
103 * @static
104 *
105 * @param int $post_id
106 * @param array $query_args
107 * @param bool $parse_result
108 *
109 * @return array
110 */
111 public static function get_revisions( $post_id = 0, $query_args = [], $parse_result = true ) {
112 $post = get_post( $post_id );
113
114 if ( ! $post || empty( $post->ID ) ) {
115 return [];
116 }
117
118 $revisions = [];
119
120 $default_query_args = [
121 'posts_per_page' => self::MAX_REVISIONS_TO_DISPLAY,
122 'meta_key' => '_elementor_data',
123 ];
124
125 $query_args = array_merge( $default_query_args, $query_args );
126
127 $posts = wp_get_post_revisions( $post->ID, $query_args );
128
129 if ( ! wp_revisions_enabled( $post ) ) {
130 $autosave = Utils::get_post_autosave( $post->ID );
131 if ( $autosave ) {
132 if ( $parse_result ) {
133 array_unshift( $posts, $autosave );
134 } else {
135 array_unshift( $posts, $autosave->ID );
136 }
137 }
138 }
139
140 if ( $parse_result ) {
141 array_unshift( $posts, $post );
142 } else {
143 array_unshift( $posts, $post->ID );
144 return $posts;
145 }
146
147 $current_time = current_time( 'timestamp' );
148
149 /** @var \WP_Post $revision */
150 foreach ( $posts as $revision ) {
151 $date = date_i18n( _x( 'M j @ H:i', 'revision date format', 'elementor' ), strtotime( $revision->post_modified ) );
152
153 $human_time = human_time_diff( strtotime( $revision->post_modified ), $current_time );
154
155 if ( $revision->ID === $post->ID ) {
156 $type = 'current';
157 $type_label = esc_html__( 'Current Version', 'elementor' );
158 } elseif ( false !== strpos( $revision->post_name, 'autosave' ) ) {
159 $type = 'autosave';
160 $type_label = esc_html__( 'Autosave', 'elementor' );
161 } else {
162 $type = 'revision';
163 $type_label = esc_html__( 'Revision', 'elementor' );
164 }
165
166 if ( ! isset( self::$authors[ $revision->post_author ] ) ) {
167 self::$authors[ $revision->post_author ] = [
168 'avatar' => get_avatar( $revision->post_author, 22 ),
169 'display_name' => get_the_author_meta( 'display_name', $revision->post_author ),
170 ];
171 }
172
173 $revisions[] = [
174 'id' => $revision->ID,
175 'author' => self::$authors[ $revision->post_author ]['display_name'],
176 'timestamp' => strtotime( $revision->post_modified ),
177 'date' => sprintf(
178 /* translators: 1: Human readable time difference, 2: Date. */
179 __( '%1$s ago (%2$s)', 'elementor' ),
180 $human_time,
181 $date
182 ),
183 'type' => $type,
184 'typeLabel' => $type_label,
185 'gravatar' => self::$authors[ $revision->post_author ]['avatar'],
186 ];
187 }
188
189 return $revisions;
190 }
191
192 /**
193 * @since 1.9.2
194 * @access public
195 * @static
196 */
197 public static function update_autosave( $autosave_data ) {
198 self::save_revision( $autosave_data['ID'] );
199 }
200
201 /**
202 * @since 1.7.0
203 * @access public
204 * @static
205 */
206 public static function save_revision( $revision_id ) {
207 $parent_id = wp_is_post_revision( $revision_id );
208
209 if ( $parent_id ) {
210 Plugin::$instance->db->safe_copy_elementor_meta( $parent_id, $revision_id );
211 }
212 }
213
214 /**
215 * @since 1.7.0
216 * @access public
217 * @static
218 */
219 public static function restore_revision( $parent_id, $revision_id ) {
220 $parent = Plugin::$instance->documents->get( $parent_id );
221 $revision = Plugin::$instance->documents->get( $revision_id );
222
223 if ( ! $parent || ! $revision ) {
224 return;
225 }
226
227 $is_built_with_elementor = $revision->is_built_with_elementor();
228
229 $parent->set_is_built_with_elementor( $is_built_with_elementor );
230
231 if ( ! $is_built_with_elementor ) {
232 return;
233 }
234
235 Plugin::$instance->db->copy_elementor_meta( $revision_id, $parent_id );
236
237 $post_css = Post_CSS::create( $parent_id );
238
239 $post_css->update();
240 }
241
242 /**
243 * @since 2.3.0
244 * @access public
245 * @static
246 *
247 * @param $data
248 *
249 * @return array
250 * @throws \Exception
251 */
252 public static function ajax_get_revision_data( array $data ) {
253 if ( ! isset( $data['id'] ) ) {
254 throw new \Exception( 'You must set the revision ID.' );
255 }
256
257 $revision = Plugin::$instance->documents->get( $data['id'] );
258
259 if ( ! $revision ) {
260 throw new \Exception( 'Invalid revision.' );
261 }
262
263 if ( ! current_user_can( 'edit_post', $revision->get_id() ) ) {
264 throw new \Exception( esc_html__( 'Access denied.', 'elementor' ) );
265 }
266
267 $revision_data = [
268 'settings' => $revision->get_settings(),
269 'elements' => $revision->get_elements_data(),
270 ];
271
272 return $revision_data;
273 }
274
275 /**
276 * @since 1.7.0
277 * @access public
278 * @static
279 */
280 public static function add_revision_support_for_all_post_types() {
281 $post_types = get_post_types_by_support( 'elementor' );
282 foreach ( $post_types as $post_type ) {
283 add_post_type_support( $post_type, 'revisions' );
284 }
285 }
286
287 /**
288 * @since 2.0.0
289 * @access public
290 * @static
291 * @param array $return_data
292 * @param Document $document
293 *
294 * @return array
295 */
296 public static function on_ajax_save_builder_data( $return_data, $document ) {
297 $post_id = $document->get_main_id();
298
299 $latest_revisions = self::get_revisions(
300 $post_id, [
301 'posts_per_page' => 1,
302 ]
303 );
304
305 $all_revision_ids = self::get_revisions(
306 $post_id, [
307 'fields' => 'ids',
308 ], false
309 );
310
311 // Send revisions data only if has revisions.
312 if ( ! empty( $latest_revisions ) ) {
313 $current_revision_id = self::current_revision_id( $post_id );
314
315 $return_data = array_replace_recursive( $return_data, [
316 'config' => [
317 'document' => [
318 'revisions' => [
319 'current_id' => $current_revision_id,
320 ],
321 ],
322 ],
323 'latest_revisions' => $latest_revisions,
324 'revisions_ids' => $all_revision_ids,
325 ] );
326 }
327
328 return $return_data;
329 }
330
331 /**
332 * @since 1.7.0
333 * @access public
334 * @static
335 */
336 public static function db_before_save( $status, $has_changes ) {
337 if ( $has_changes ) {
338 self::handle_revision();
339 }
340 }
341
342 public static function document_config( $settings, $post_id ) {
343 $settings['revisions'] = [
344 'enabled' => ( $post_id && wp_revisions_enabled( get_post( $post_id ) ) ),
345 'current_id' => self::current_revision_id( $post_id ),
346 ];
347
348 return $settings;
349 }
350
351 /**
352 * Localize settings.
353 *
354 * Add new localized settings for the revisions manager.
355 *
356 * Fired by `elementor/editor/editor_settings` filter.
357 *
358 * @since 1.7.0
359 * @access public
360 * @static
361 * @deprecated 3.1.0
362 */
363 public static function editor_settings() {
364 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0' );
365
366 return [];
367 }
368
369 public static function ajax_get_revisions() {
370 return self::get_revisions();
371 }
372
373 /**
374 * @since 2.3.0
375 * @access public
376 * @static
377 */
378 public static function register_ajax_actions( Ajax $ajax ) {
379 $ajax->register_ajax_action( 'get_revisions', [ __CLASS__, 'ajax_get_revisions' ] );
380 $ajax->register_ajax_action( 'get_revision_data', [ __CLASS__, 'ajax_get_revision_data' ] );
381 }
382
383 /**
384 * @since 1.7.0
385 * @access private
386 * @static
387 */
388 private static function register_actions() {
389 add_action( 'wp_restore_post_revision', [ __CLASS__, 'restore_revision' ], 10, 2 );
390 add_action( 'init', [ __CLASS__, 'add_revision_support_for_all_post_types' ], 9999 );
391 add_filter( 'elementor/document/config', [ __CLASS__, 'document_config' ], 10, 2 );
392 add_action( 'elementor/db/before_save', [ __CLASS__, 'db_before_save' ], 10, 2 );
393 add_action( '_wp_put_post_revision', [ __CLASS__, 'save_revision' ] );
394 add_action( 'wp_creating_autosave', [ __CLASS__, 'update_autosave' ] );
395 add_action( 'elementor/ajax/register_actions', [ __CLASS__, 'register_ajax_actions' ] );
396
397 // Hack to avoid delete the auto-save revision in WP editor.
398 add_filter( 'edit_post_content', [ __CLASS__, 'avoid_delete_auto_save' ], 10, 2 );
399 add_action( 'edit_form_after_title', [ __CLASS__, 'remove_temp_post_content' ] );
400
401 if ( wp_doing_ajax() ) {
402 add_filter( 'elementor/documents/ajax_save/return_data', [ __CLASS__, 'on_ajax_save_builder_data' ], 10, 2 );
403 }
404 }
405
406 /**
407 * @since 1.9.0
408 * @access private
409 * @static
410 */
411 private static function current_revision_id( $post_id ) {
412 $current_revision_id = $post_id;
413 $autosave = Utils::get_post_autosave( $post_id );
414
415 if ( is_object( $autosave ) ) {
416 $current_revision_id = $autosave->ID;
417 }
418
419 return $current_revision_id;
420 }
421 }
422