PluginProbe
Elementor Website Builder – more than just a page builder / 3.1.0-dev1
Elementor Website Builder – more than just a page builder v3.1.0-dev1
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.1.0-dev1, at modules/history/revisions-manager.php

424 lines 10.8 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 if ( $post_id && Plugin::$instance->db->is_built_with_elementor( $post_id ) ) {
75 $post_content .= '<!-- Created with Elementor -->';
76 }
77
78 return $post_content;
79 }
80
81 /**
82 * @since 2.0.0
83 * @access public
84 * @static
85 */
86 public static function remove_temp_post_content() {
87 global $post;
88
89 if ( Plugin::$instance->db->is_built_with_elementor( $post->ID ) ) {
90 $post->post_content = str_replace( '<!-- Created with Elementor -->', '', $post->post_content );
91 }
92 }
93
94 /**
95 * @since 1.7.0
96 * @access public
97 * @static
98 *
99 * @param int $post_id
100 * @param array $query_args
101 * @param bool $parse_result
102 *
103 * @return array
104 */
105 public static function get_revisions( $post_id = 0, $query_args = [], $parse_result = true ) {
106 $post = get_post( $post_id );
107
108 if ( ! $post || empty( $post->ID ) ) {
109 return [];
110 }
111
112 $revisions = [];
113
114 $default_query_args = [
115 'posts_per_page' => self::MAX_REVISIONS_TO_DISPLAY,
116 'meta_key' => '_elementor_data',
117 ];
118
119 $query_args = array_merge( $default_query_args, $query_args );
120
121 $posts = wp_get_post_revisions( $post->ID, $query_args );
122
123 if ( ! wp_revisions_enabled( $post ) ) {
124 $autosave = Utils::get_post_autosave( $post->ID );
125 if ( $autosave ) {
126 if ( $parse_result ) {
127 array_unshift( $posts, $autosave );
128 } else {
129 array_unshift( $posts, $autosave->ID );
130 }
131 }
132 }
133
134 if ( $parse_result ) {
135 array_unshift( $posts, $post );
136 } else {
137 array_unshift( $posts, $post->ID );
138 return $posts;
139 }
140
141 $current_time = current_time( 'timestamp' );
142
143 /** @var \WP_Post $revision */
144 foreach ( $posts as $revision ) {
145 $date = date_i18n( _x( 'M j @ H:i', 'revision date format', 'elementor' ), strtotime( $revision->post_modified ) );
146
147 $human_time = human_time_diff( strtotime( $revision->post_modified ), $current_time );
148
149 if ( $revision->ID === $post->ID ) {
150 $type = 'current';
151 } elseif ( false !== strpos( $revision->post_name, 'autosave' ) ) {
152 $type = 'autosave';
153 } else {
154 $type = 'revision';
155 }
156
157 if ( ! isset( self::$authors[ $revision->post_author ] ) ) {
158 self::$authors[ $revision->post_author ] = [
159 'avatar' => get_avatar( $revision->post_author, 22 ),
160 'display_name' => get_the_author_meta( 'display_name', $revision->post_author ),
161 ];
162 }
163
164 $revisions[] = [
165 'id' => $revision->ID,
166 'author' => self::$authors[ $revision->post_author ]['display_name'],
167 'timestamp' => strtotime( $revision->post_modified ),
168 'date' => sprintf(
169 /* translators: 1: Human readable time difference, 2: Date */
170 __( '%1$s ago (%2$s)', 'elementor' ),
171 $human_time,
172 $date
173 ),
174 'type' => $type,
175 'gravatar' => self::$authors[ $revision->post_author ]['avatar'],
176 ];
177 }
178
179 return $revisions;
180 }
181
182 /**
183 * @since 1.9.2
184 * @access public
185 * @static
186 */
187 public static function update_autosave( $autosave_data ) {
188 self::save_revision( $autosave_data['ID'] );
189 }
190
191 /**
192 * @since 1.7.0
193 * @access public
194 * @static
195 */
196 public static function save_revision( $revision_id ) {
197 $parent_id = wp_is_post_revision( $revision_id );
198
199 if ( $parent_id ) {
200 Plugin::$instance->db->safe_copy_elementor_meta( $parent_id, $revision_id );
201 }
202 }
203
204 /**
205 * @since 1.7.0
206 * @access public
207 * @static
208 */
209 public static function restore_revision( $parent_id, $revision_id ) {
210 $is_built_with_elementor = Plugin::$instance->db->is_built_with_elementor( $revision_id );
211
212 Plugin::$instance->db->set_is_elementor_page( $parent_id, $is_built_with_elementor );
213
214 if ( ! $is_built_with_elementor ) {
215 return;
216 }
217
218 Plugin::$instance->db->copy_elementor_meta( $revision_id, $parent_id );
219
220 $post_css = Post_CSS::create( $parent_id );
221
222 $post_css->update();
223 }
224
225 /**
226 * @since 2.3.0
227 * @access public
228 * @static
229 *
230 * @param $data
231 *
232 * @return array
233 * @throws \Exception
234 */
235 public static function ajax_get_revision_data( array $data ) {
236 if ( ! isset( $data['id'] ) ) {
237 throw new \Exception( 'You must set the revision ID.' );
238 }
239
240 $revision = Plugin::$instance->documents->get( $data['id'] );
241
242 if ( ! $revision ) {
243 throw new \Exception( 'Invalid revision.' );
244 }
245
246 if ( ! current_user_can( 'edit_post', $revision->get_id() ) ) {
247 throw new \Exception( __( 'Access denied.', 'elementor' ) );
248 }
249
250 $revision_data = [
251 'settings' => $revision->get_settings(),
252 'elements' => $revision->get_elements_data(),
253 ];
254
255 return $revision_data;
256 }
257
258 /**
259 * @since 1.7.0
260 * @access public
261 * @static
262 */
263 public static function add_revision_support_for_all_post_types() {
264 $post_types = get_post_types_by_support( 'elementor' );
265 foreach ( $post_types as $post_type ) {
266 add_post_type_support( $post_type, 'revisions' );
267 }
268 }
269
270 /**
271 * @since 2.0.0
272 * @access public
273 * @static
274 * @param array $return_data
275 * @param Document $document
276 *
277 * @return array
278 */
279 public static function on_ajax_save_builder_data( $return_data, $document ) {
280 $post_id = $document->get_main_id();
281
282 $latest_revisions = self::get_revisions(
283 $post_id, [
284 'posts_per_page' => 1,
285 ]
286 );
287
288 $all_revision_ids = self::get_revisions(
289 $post_id, [
290 'fields' => 'ids',
291 ], false
292 );
293
294 // Send revisions data only if has revisions.
295 if ( ! empty( $latest_revisions ) ) {
296 $current_revision_id = self::current_revision_id( $post_id );
297
298 $return_data = array_replace_recursive( $return_data, [
299 'config' => [
300 'document' => [
301 'revisions' => [
302 'current_id' => $current_revision_id,
303 ],
304 ],
305 ],
306 'latest_revisions' => $latest_revisions,
307 'revisions_ids' => $all_revision_ids,
308 ] );
309 }
310
311 return $return_data;
312 }
313
314 /**
315 * @since 1.7.0
316 * @access public
317 * @static
318 */
319 public static function db_before_save( $status, $has_changes ) {
320 if ( $has_changes ) {
321 self::handle_revision();
322 }
323 }
324
325 public static function document_config( $settings, $post_id ) {
326 $settings['revisions'] = [
327 'enabled' => ( $post_id && wp_revisions_enabled( get_post( $post_id ) ) ),
328 'current_id' => self::current_revision_id( $post_id ),
329 ];
330
331 return $settings;
332 }
333
334 /**
335 * Localize settings.
336 *
337 * Add new localized settings for the revisions manager.
338 *
339 * Fired by `elementor/editor/editor_settings` filter.
340 *
341 * @since 1.7.0
342 * @access public
343 * @static
344 */
345 public static function editor_settings( $settings ) {
346 $settings = array_replace_recursive( $settings, [
347 'i18n' => [
348 'edit_draft' => __( 'Edit Draft', 'elementor' ),
349 'edit_published' => __( 'Edit Published', 'elementor' ),
350 'no_revisions_1' => __( 'Revision history lets you save your previous versions of your work, and restore them any time.', 'elementor' ),
351 'no_revisions_2' => __( 'Start designing your page and you\'ll be able to see the entire revision history here.', 'elementor' ),
352 'current' => __( 'Current Version', 'elementor' ),
353 'restore' => __( 'Restore', 'elementor' ),
354 'restore_auto_saved_data' => __( 'Restore Auto Saved Data', 'elementor' ),
355 'restore_auto_saved_data_message' => __( 'There is an autosave of this post that is more recent than the version below. You can restore the saved data fron the Revisions panel', 'elementor' ),
356 'revision' => __( 'Revision', 'elementor' ),
357 'revision_history' => __( 'Revision History', 'elementor' ),
358 'revisions_disabled_1' => __( 'It looks like the post revision feature is unavailable in your website.', 'elementor' ),
359 'revisions_disabled_2' => sprintf(
360 /* translators: %s: Codex URL */
361 __( 'Learn more about <a target="_blank" href="%s">WordPress revisions</a>', 'elementor' ),
362 'https://go.elementor.com/wordpress-revisions/'
363 ),
364 ],
365 ] );
366
367 return $settings;
368 }
369
370 public static function ajax_get_revisions() {
371 return self::get_revisions();
372 }
373
374 /**
375 * @since 2.3.0
376 * @access public
377 * @static
378 */
379 public static function register_ajax_actions( Ajax $ajax ) {
380 $ajax->register_ajax_action( 'get_revisions', [ __CLASS__, 'ajax_get_revisions' ] );
381 $ajax->register_ajax_action( 'get_revision_data', [ __CLASS__, 'ajax_get_revision_data' ] );
382 }
383
384 /**
385 * @since 1.7.0
386 * @access private
387 * @static
388 */
389 private static function register_actions() {
390 add_action( 'wp_restore_post_revision', [ __CLASS__, 'restore_revision' ], 10, 2 );
391 add_action( 'init', [ __CLASS__, 'add_revision_support_for_all_post_types' ], 9999 );
392 add_filter( 'elementor/editor/localize_settings', [ __CLASS__, 'editor_settings' ] );
393 add_filter( 'elementor/document/config', [ __CLASS__, 'document_config' ], 10, 2 );
394 add_action( 'elementor/db/before_save', [ __CLASS__, 'db_before_save' ], 10, 2 );
395 add_action( '_wp_put_post_revision', [ __CLASS__, 'save_revision' ] );
396 add_action( 'wp_creating_autosave', [ __CLASS__, 'update_autosave' ] );
397 add_action( 'elementor/ajax/register_actions', [ __CLASS__, 'register_ajax_actions' ] );
398
399 // Hack to avoid delete the auto-save revision in WP editor.
400 add_filter( 'edit_post_content', [ __CLASS__, 'avoid_delete_auto_save' ], 10, 2 );
401 add_action( 'edit_form_after_title', [ __CLASS__, 'remove_temp_post_content' ] );
402
403 if ( wp_doing_ajax() ) {
404 add_filter( 'elementor/documents/ajax_save/return_data', [ __CLASS__, 'on_ajax_save_builder_data' ], 10, 2 );
405 }
406 }
407
408 /**
409 * @since 1.9.0
410 * @access private
411 * @static
412 */
413 private static function current_revision_id( $post_id ) {
414 $current_revision_id = $post_id;
415 $autosave = Utils::get_post_autosave( $post_id );
416
417 if ( is_object( $autosave ) ) {
418 $current_revision_id = $autosave->ID;
419 }
420
421 return $current_revision_id;
422 }
423 }
424