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

417 lines 9.9 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 = 50;
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 esc_html__( '%1$s ago (%2$s)', 'elementor' ),
180 '<time>' . $human_time . '</time>',
181 '<time>' . $date . '</time>'
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_with_permissions( $data['id'] );
258
259 return [
260 'settings' => $revision->get_settings(),
261 'elements' => $revision->get_elements_data(),
262 ];
263 }
264
265 /**
266 * @since 1.7.0
267 * @access public
268 * @static
269 */
270 public static function add_revision_support_for_all_post_types() {
271 $post_types = get_post_types_by_support( 'elementor' );
272 foreach ( $post_types as $post_type ) {
273 add_post_type_support( $post_type, 'revisions' );
274 }
275 }
276
277 /**
278 * @since 2.0.0
279 * @access public
280 * @static
281 * @param array $return_data
282 * @param Document $document
283 *
284 * @return array
285 */
286 public static function on_ajax_save_builder_data( $return_data, $document ) {
287 $post_id = $document->get_main_id();
288
289 $latest_revisions = self::get_revisions(
290 $post_id, [
291 'posts_per_page' => 1,
292 ]
293 );
294
295 $all_revision_ids = self::get_revisions(
296 $post_id, [
297 'fields' => 'ids',
298 ], false
299 );
300
301 // Send revisions data only if has revisions.
302 if ( ! empty( $latest_revisions ) ) {
303 $current_revision_id = self::current_revision_id( $post_id );
304
305 $return_data = array_replace_recursive( $return_data, [
306 'config' => [
307 'document' => [
308 'revisions' => [
309 'current_id' => $current_revision_id,
310 ],
311 ],
312 ],
313 'latest_revisions' => $latest_revisions,
314 'revisions_ids' => $all_revision_ids,
315 ] );
316 }
317
318 return $return_data;
319 }
320
321 /**
322 * @since 1.7.0
323 * @access public
324 * @static
325 */
326 public static function db_before_save( $status, $has_changes ) {
327 if ( $has_changes ) {
328 self::handle_revision();
329 }
330 }
331
332 public static function document_config( $settings, $post_id ) {
333 $settings['revisions'] = [
334 'enabled' => ( $post_id && wp_revisions_enabled( get_post( $post_id ) ) ),
335 'current_id' => self::current_revision_id( $post_id ),
336 ];
337
338 return $settings;
339 }
340
341 /**
342 * Localize settings.
343 *
344 * Add new localized settings for the revisions manager.
345 *
346 * Fired by `elementor/editor/editor_settings` filter.
347 *
348 * @since 1.7.0
349 * @deprecated 3.1.0
350 * @access public
351 * @static
352 */
353 public static function editor_settings() {
354 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0' );
355
356 return [];
357 }
358
359 /**
360 * @throws \Exception
361 */
362 public static function ajax_get_revisions( $data ) {
363 Plugin::$instance->documents->check_permissions( $data['editor_post_id'] );
364
365 return self::get_revisions();
366 }
367
368 /**
369 * @since 2.3.0
370 * @access public
371 * @static
372 */
373 public static function register_ajax_actions( Ajax $ajax ) {
374 $ajax->register_ajax_action( 'get_revisions', [ __CLASS__, 'ajax_get_revisions' ] );
375 $ajax->register_ajax_action( 'get_revision_data', [ __CLASS__, 'ajax_get_revision_data' ] );
376 }
377
378 /**
379 * @since 1.7.0
380 * @access private
381 * @static
382 */
383 private static function register_actions() {
384 add_action( 'wp_restore_post_revision', [ __CLASS__, 'restore_revision' ], 10, 2 );
385 add_action( 'init', [ __CLASS__, 'add_revision_support_for_all_post_types' ], 9999 );
386 add_filter( 'elementor/document/config', [ __CLASS__, 'document_config' ], 10, 2 );
387 add_action( 'elementor/db/before_save', [ __CLASS__, 'db_before_save' ], 10, 2 );
388 add_action( '_wp_put_post_revision', [ __CLASS__, 'save_revision' ] );
389 add_action( 'wp_creating_autosave', [ __CLASS__, 'update_autosave' ] );
390 add_action( 'elementor/ajax/register_actions', [ __CLASS__, 'register_ajax_actions' ] );
391
392 // Hack to avoid delete the auto-save revision in WP editor.
393 add_filter( 'edit_post_content', [ __CLASS__, 'avoid_delete_auto_save' ], 10, 2 );
394 add_action( 'edit_form_after_title', [ __CLASS__, 'remove_temp_post_content' ] );
395
396 if ( wp_doing_ajax() ) {
397 add_filter( 'elementor/documents/ajax_save/return_data', [ __CLASS__, 'on_ajax_save_builder_data' ], 10, 2 );
398 }
399 }
400
401 /**
402 * @since 1.9.0
403 * @access private
404 * @static
405 */
406 private static function current_revision_id( $post_id ) {
407 $current_revision_id = $post_id;
408 $autosave = Utils::get_post_autosave( $post_id );
409
410 if ( is_object( $autosave ) ) {
411 $current_revision_id = $autosave->ID;
412 }
413
414 return $current_revision_id;
415 }
416 }
417