~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-admin/includes/revision.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress Administration Revisions API
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Administration
 
7
 */
 
8
 
 
9
/**
 
10
 * Get the revision UI diff.
 
11
 *
 
12
 * @since 3.6.0
 
13
 *
 
14
 * @param object|int $post         The post object. Also accepts a post ID.
 
15
 * @param int        $compare_from The revision ID to compare from.
 
16
 * @param int        $compare_to   The revision ID to come to.
 
17
 *
 
18
 * @return array|bool Associative array of a post's revisioned fields and their diffs.
 
19
 *                    Or, false on failure.
 
20
 */
 
21
function wp_get_revision_ui_diff( $post, $compare_from, $compare_to ) {
 
22
        if ( ! $post = get_post( $post ) )
 
23
                return false;
 
24
 
 
25
        if ( $compare_from ) {
 
26
                if ( ! $compare_from = get_post( $compare_from ) )
 
27
                        return false;
 
28
        } else {
 
29
                // If we're dealing with the first revision...
 
30
                $compare_from = false;
 
31
        }
 
32
 
 
33
        if ( ! $compare_to = get_post( $compare_to ) )
 
34
                return false;
 
35
 
 
36
        // If comparing revisions, make sure we're dealing with the right post parent.
 
37
        // The parent post may be a 'revision' when revisions are disabled and we're looking at autosaves.
 
38
        if ( $compare_from && $compare_from->post_parent !== $post->ID && $compare_from->ID !== $post->ID )
 
39
                return false;
 
40
        if ( $compare_to->post_parent !== $post->ID && $compare_to->ID !== $post->ID )
 
41
                return false;
 
42
 
 
43
        if ( $compare_from && strtotime( $compare_from->post_date_gmt ) > strtotime( $compare_to->post_date_gmt ) ) {
 
44
                $temp = $compare_from;
 
45
                $compare_from = $compare_to;
 
46
                $compare_to = $temp;
 
47
        }
 
48
 
 
49
        // Add default title if title field is empty
 
50
        if ( $compare_from && empty( $compare_from->post_title ) )
 
51
                $compare_from->post_title = __( '(no title)' );
 
52
        if ( empty( $compare_to->post_title ) )
 
53
                $compare_to->post_title = __( '(no title)' );
 
54
 
 
55
        $return = array();
 
56
 
 
57
        foreach ( _wp_post_revision_fields() as $field => $name ) {
 
58
                /**
 
59
                 * Contextually filter a post revision field.
 
60
                 *
 
61
                 * The dynamic portion of the hook name, $field, corresponds to each of the post
 
62
                 * fields of the revision object being iterated over in a foreach statement.
 
63
                 *
 
64
                 * @since 3.6.0
 
65
                 *
 
66
                 * @param string  $compare_from->$field The current revision field to compare to or from.
 
67
                 * @param string  $field                The current revision field.
 
68
                 * @param WP_Post $compare_from         The revision post object to compare to or from.
 
69
                 * @param string  null                  The context of whether the current revision is the old or the new one. Values are 'to' or 'from'.
 
70
                 */
 
71
                $content_from = $compare_from ? apply_filters( "_wp_post_revision_field_$field", $compare_from->$field, $field, $compare_from, 'from' ) : '';
 
72
 
 
73
                /** This filter is documented in wp-admin/includes/revision.php */
 
74
                $content_to = apply_filters( "_wp_post_revision_field_$field", $compare_to->$field, $field, $compare_to, 'to' );
 
75
 
 
76
                $diff = wp_text_diff( $content_from, $content_to, array( 'show_split_view' => true ) );
 
77
 
 
78
                if ( ! $diff && 'post_title' === $field ) {
 
79
                        // It's a better user experience to still show the Title, even if it didn't change.
 
80
                        // No, you didn't see this.
 
81
                        $diff = '<table class="diff"><colgroup><col class="content diffsplit left"><col class="content diffsplit middle"><col class="content diffsplit right"></colgroup><tbody><tr>';
 
82
                        $diff .= '<td>' . esc_html( $compare_from->post_title ) . '</td><td></td><td>' . esc_html( $compare_to->post_title ) . '</td>';
 
83
                        $diff .= '</tr></tbody>';
 
84
                        $diff .= '</table>';
 
85
                }
 
86
 
 
87
                if ( $diff ) {
 
88
                        $return[] = array(
 
89
                                'id' => $field,
 
90
                                'name' => $name,
 
91
                                'diff' => $diff,
 
92
                        );
 
93
                }
 
94
        }
 
95
        return $return;
 
96
}
 
97
 
 
98
/**
 
99
 * Prepare revisions for JavaScript.
 
100
 *
 
101
 * @since 3.6.0
 
102
 *
 
103
 * @param object|int $post                 The post object. Also accepts a post ID.
 
104
 * @param int        $selected_revision_id The selected revision ID.
 
105
 * @param int        $from                 Optional. The revision ID to compare from.
 
106
 *
 
107
 * @return array An associative array of revision data and related settings.
 
108
 */
 
109
function wp_prepare_revisions_for_js( $post, $selected_revision_id, $from = null ) {
 
110
        $post = get_post( $post );
 
111
        $authors = array();
 
112
        $now_gmt = time();
 
113
 
 
114
        $revisions = wp_get_post_revisions( $post->ID, array( 'order' => 'ASC', 'check_enabled' => false ) );
 
115
        // If revisions are disabled, we only want autosaves and the current post.
 
116
        if ( ! wp_revisions_enabled( $post ) ) {
 
117
                foreach ( $revisions as $revision_id => $revision ) {
 
118
                        if ( ! wp_is_post_autosave( $revision ) )
 
119
                                unset( $revisions[ $revision_id ] );
 
120
                }
 
121
                $revisions = array( $post->ID => $post ) + $revisions;
 
122
        }
 
123
 
 
124
        $show_avatars = get_option( 'show_avatars' );
 
125
 
 
126
        cache_users( wp_list_pluck( $revisions, 'post_author' ) );
 
127
 
 
128
        $can_restore = current_user_can( 'edit_post', $post->ID );
 
129
        $current_id = false;
 
130
 
 
131
        foreach ( $revisions as $revision ) {
 
132
                $modified = strtotime( $revision->post_modified );
 
133
                $modified_gmt = strtotime( $revision->post_modified_gmt );
 
134
                if ( $can_restore ) {
 
135
                        $restore_link = str_replace( '&amp;', '&', wp_nonce_url(
 
136
                                add_query_arg(
 
137
                                        array( 'revision' => $revision->ID,
 
138
                                                'action' => 'restore' ),
 
139
                                                admin_url( 'revision.php' )
 
140
                                ),
 
141
                                "restore-post_{$revision->ID}"
 
142
                        ) );
 
143
                }
 
144
 
 
145
                if ( ! isset( $authors[ $revision->post_author ] ) ) {
 
146
                        $authors[ $revision->post_author ] = array(
 
147
                                'id' => (int) $revision->post_author,
 
148
                                'avatar' => $show_avatars ? get_avatar( $revision->post_author, 32 ) : '',
 
149
                                'name' => get_the_author_meta( 'display_name', $revision->post_author ),
 
150
                        );
 
151
                }
 
152
 
 
153
                $autosave = (bool) wp_is_post_autosave( $revision );
 
154
                $current = ! $autosave && $revision->post_modified_gmt === $post->post_modified_gmt;
 
155
                if ( $current && ! empty( $current_id ) ) {
 
156
                        // If multiple revisions have the same post_modified_gmt, highest ID is current.
 
157
                        if ( $current_id < $revision->ID ) {
 
158
                                $revisions[ $current_id ]['current'] = false;
 
159
                                $current_id = $revision->ID;
 
160
                        } else {
 
161
                                $current = false;
 
162
                        }
 
163
                } elseif ( $current ) {
 
164
                        $current_id = $revision->ID;
 
165
                }
 
166
 
 
167
                $revisions[ $revision->ID ] = array(
 
168
                        'id'         => $revision->ID,
 
169
                        'title'      => get_the_title( $post->ID ),
 
170
                        'author'     => $authors[ $revision->post_author ],
 
171
                        'date'       => date_i18n( __( 'M j, Y @ G:i' ), $modified ),
 
172
                        'dateShort'  => date_i18n( _x( 'j M @ G:i', 'revision date short format' ), $modified ),
 
173
                        'timeAgo'    => sprintf( __( '%s ago' ), human_time_diff( $modified_gmt, $now_gmt ) ),
 
174
                        'autosave'   => $autosave,
 
175
                        'current'    => $current,
 
176
                        'restoreUrl' => $can_restore ? $restore_link : false,
 
177
                );
 
178
        }
 
179
 
 
180
        /*
 
181
         * If a post has been saved since the last revision (no revisioned fields
 
182
         * were changed), we may not have a "current" revision. Mark the latest
 
183
         * revision as "current".
 
184
         */
 
185
        if ( empty( $current_id ) ) {
 
186
                if ( $revisions[ $revision->ID ]['autosave'] ) {
 
187
                        $revision = end( $revisions );
 
188
                        while ( $revision['autosave'] ) {
 
189
                                $revision = prev( $revisions );
 
190
                        }
 
191
                        $current_id = $revision['id'];
 
192
                } else {
 
193
                        $current_id = $revision->ID;
 
194
                }
 
195
                $revisions[ $current_id ]['current'] = true;
 
196
        }
 
197
 
 
198
        // Now, grab the initial diff.
 
199
        $compare_two_mode = is_numeric( $from );
 
200
        if ( ! $compare_two_mode ) {
 
201
                $found = array_search( $selected_revision_id, array_keys( $revisions ) );
 
202
                if ( $found ) {
 
203
                        $from = array_keys( array_slice( $revisions, $found - 1, 1, true ) );
 
204
                        $from = reset( $from );
 
205
                } else {
 
206
                        $from = 0;
 
207
                }
 
208
        }
 
209
 
 
210
        $from = absint( $from );
 
211
 
 
212
        $diffs = array( array(
 
213
                'id' => $from . ':' . $selected_revision_id,
 
214
                'fields' => wp_get_revision_ui_diff( $post->ID, $from, $selected_revision_id ),
 
215
        ));
 
216
 
 
217
        return array(
 
218
                'postId'           => $post->ID,
 
219
                'nonce'            => wp_create_nonce( 'revisions-ajax-nonce' ),
 
220
                'revisionData'     => array_values( $revisions ),
 
221
                'to'               => $selected_revision_id,
 
222
                'from'             => $from,
 
223
                'diffData'         => $diffs,
 
224
                'baseUrl'          => parse_url( admin_url( 'revision.php' ), PHP_URL_PATH ),
 
225
                'compareTwoMode'   => absint( $compare_two_mode ), // Apparently booleans are not allowed
 
226
                'revisionIds'      => array_keys( $revisions ),
 
227
        );
 
228
}