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

416 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 = 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 $type_label = __( 'Current Version', 'elementor' );
152 } elseif ( false !== strpos( $revision->post_name, 'autosave' ) ) {
153 $type = 'autosave';
154 $type_label = __( 'Autosave', 'elementor' );
155 } else {
156 $type = 'revision';
157 $type_label = __( 'Revision', 'elementor' );
158 }
159
160 if ( ! isset( self::$authors[ $revision->post_author ] ) ) {
161 self::$authors[ $revision->post_author ] = [
162 'avatar' => get_avatar( $revision->post_author, 22 ),
163 'display_name' => get_the_author_meta( 'display_name', $revision->post_author ),
164 ];
165 }
166
167 $revisions[] = [
168 'id' => $revision->ID,
169 'author' => self::$authors[ $revision->post_author ]['display_name'],
170 'timestamp' => strtotime( $revision->post_modified ),
171 'date' => sprintf(
172 /* translators: 1: Human readable time difference, 2: Date */
173 __( '%1$s ago (%2$s)', 'elementor' ),
174 $human_time,
175 $date
176 ),
177 'type' => $type,
178 'typeLabel' => $type_label,
179 'gravatar' => self::$authors[ $revision->post_author ]['avatar'],
180 ];
181 }
182
183 return $revisions;
184 }
185
186 /**
187 * @since 1.9.2
188 * @access public
189 * @static
190 */
191 public static function update_autosave( $autosave_data ) {
192 self::save_revision( $autosave_data['ID'] );
193 }
194
195 /**
196 * @since 1.7.0
197 * @access public
198 * @static
199 */
200 public static function save_revision( $revision_id ) {
201 $parent_id = wp_is_post_revision( $revision_id );
202
203 if ( $parent_id ) {
204 Plugin::$instance->db->safe_copy_elementor_meta( $parent_id, $revision_id );
205 }
206 }
207
208 /**
209 * @since 1.7.0
210 * @access public
211 * @static
212 */
213 public static function restore_revision( $parent_id, $revision_id ) {
214 $parent = Plugin::$instance->documents->get( $parent_id );
215 $revision = Plugin::$instance->documents->get( $revision_id );
216
217 if ( ! $parent || ! $revision ) {
218 return;
219 }
220
221 $is_built_with_elementor = $revision->is_built_with_elementor();
222
223 $parent->set_is_built_with_elementor( $is_built_with_elementor );
224
225 if ( ! $is_built_with_elementor ) {
226 return;
227 }
228
229 Plugin::$instance->db->copy_elementor_meta( $revision_id, $parent_id );
230
231 $post_css = Post_CSS::create( $parent_id );
232
233 $post_css->update();
234 }
235
236 /**
237 * @since 2.3.0
238 * @access public
239 * @static
240 *
241 * @param $data
242 *
243 * @return array
244 * @throws \Exception
245 */
246 public static function ajax_get_revision_data( array $data ) {
247 if ( ! isset( $data['id'] ) ) {
248 throw new \Exception( 'You must set the revision ID.' );
249 }
250
251 $revision = Plugin::$instance->documents->get( $data['id'] );
252
253 if ( ! $revision ) {
254 throw new \Exception( 'Invalid revision.' );
255 }
256
257 if ( ! current_user_can( 'edit_post', $revision->get_id() ) ) {
258 throw new \Exception( __( 'Access denied.', 'elementor' ) );
259 }
260
261 $revision_data = [
262 'settings' => $revision->get_settings(),
263 'elements' => $revision->get_elements_data(),
264 ];
265
266 return $revision_data;
267 }
268
269 /**
270 * @since 1.7.0
271 * @access public
272 * @static
273 */
274 public static function add_revision_support_for_all_post_types() {
275 $post_types = get_post_types_by_support( 'elementor' );
276 foreach ( $post_types as $post_type ) {
277 add_post_type_support( $post_type, 'revisions' );
278 }
279 }
280
281 /**
282 * @since 2.0.0
283 * @access public
284 * @static
285 * @param array $return_data
286 * @param Document $document
287 *
288 * @return array
289 */
290 public static function on_ajax_save_builder_data( $return_data, $document ) {
291 $post_id = $document->get_main_id();
292
293 $latest_revisions = self::get_revisions(
294 $post_id, [
295 'posts_per_page' => 1,
296 ]
297 );
298
299 $all_revision_ids = self::get_revisions(
300 $post_id, [
301 'fields' => 'ids',
302 ], false
303 );
304
305 // Send revisions data only if has revisions.
306 if ( ! empty( $latest_revisions ) ) {
307 $current_revision_id = self::current_revision_id( $post_id );
308
309 $return_data = array_replace_recursive( $return_data, [
310 'config' => [
311 'document' => [
312 'revisions' => [
313 'current_id' => $current_revision_id,
314 ],
315 ],
316 ],
317 'latest_revisions' => $latest_revisions,
318 'revisions_ids' => $all_revision_ids,
319 ] );
320 }
321
322 return $return_data;
323 }
324
325 /**
326 * @since 1.7.0
327 * @access public
328 * @static
329 */
330 public static function db_before_save( $status, $has_changes ) {
331 if ( $has_changes ) {
332 self::handle_revision();
333 }
334 }
335
336 public static function document_config( $settings, $post_id ) {
337 $settings['revisions'] = [
338 'enabled' => ( $post_id && wp_revisions_enabled( get_post( $post_id ) ) ),
339 'current_id' => self::current_revision_id( $post_id ),
340 ];
341
342 return $settings;
343 }
344
345 /**
346 * Localize settings.
347 *
348 * Add new localized settings for the revisions manager.
349 *
350 * Fired by `elementor/editor/editor_settings` filter.
351 *
352 * @since 1.7.0
353 * @access public
354 * @static
355 * @deprecated 3.1.0
356 */
357 public static function editor_settings() {
358 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0' );
359
360 return [];
361 }
362
363 public static function ajax_get_revisions() {
364 return self::get_revisions();
365 }
366
367 /**
368 * @since 2.3.0
369 * @access public
370 * @static
371 */
372 public static function register_ajax_actions( Ajax $ajax ) {
373 $ajax->register_ajax_action( 'get_revisions', [ __CLASS__, 'ajax_get_revisions' ] );
374 $ajax->register_ajax_action( 'get_revision_data', [ __CLASS__, 'ajax_get_revision_data' ] );
375 }
376
377 /**
378 * @since 1.7.0
379 * @access private
380 * @static
381 */
382 private static function register_actions() {
383 add_action( 'wp_restore_post_revision', [ __CLASS__, 'restore_revision' ], 10, 2 );
384 add_action( 'init', [ __CLASS__, 'add_revision_support_for_all_post_types' ], 9999 );
385 add_filter( 'elementor/document/config', [ __CLASS__, 'document_config' ], 10, 2 );
386 add_action( 'elementor/db/before_save', [ __CLASS__, 'db_before_save' ], 10, 2 );
387 add_action( '_wp_put_post_revision', [ __CLASS__, 'save_revision' ] );
388 add_action( 'wp_creating_autosave', [ __CLASS__, 'update_autosave' ] );
389 add_action( 'elementor/ajax/register_actions', [ __CLASS__, 'register_ajax_actions' ] );
390
391 // Hack to avoid delete the auto-save revision in WP editor.
392 add_filter( 'edit_post_content', [ __CLASS__, 'avoid_delete_auto_save' ], 10, 2 );
393 add_action( 'edit_form_after_title', [ __CLASS__, 'remove_temp_post_content' ] );
394
395 if ( wp_doing_ajax() ) {
396 add_filter( 'elementor/documents/ajax_save/return_data', [ __CLASS__, 'on_ajax_save_builder_data' ], 10, 2 );
397 }
398 }
399
400 /**
401 * @since 1.9.0
402 * @access private
403 * @static
404 */
405 private static function current_revision_id( $post_id ) {
406 $current_revision_id = $post_id;
407 $autosave = Utils::get_post_autosave( $post_id );
408
409 if ( is_object( $autosave ) ) {
410 $current_revision_id = $autosave->ID;
411 }
412
413 return $current_revision_id;
414 }
415 }
416