-
Notifications
You must be signed in to change notification settings - Fork 52
/
diff.php
175 lines (130 loc) · 4.93 KB
/
diff.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
/**
* Class to modify rendering of text-diffs on revision.php page
* @todo the table of revisions
*/
class Fork_Diff {
/**
* Hook into WordPress API on init
*/
function __construct( &$parent ) {
$this->parent = &$parent;
add_action( 'load-revision.php', array( $this, 'spoof_revision' ) );
}
/**
* /wp-admin/revision.php checks that the thing we're comparing is a "revision"
* When comparing a fork to a post, prime the object cache with a modified version of the fork
* so that revision.php grabs the post from cache, it thinks it's a revision
*
* Note: this only fires on revision.php, per the hook
*
*/
function spoof_revision() {
$post = (int) $_GET['right'];
$post = get_post( $post );
if ( !get_post_type( $post ) == 'fork' )
return;
$post->post_type = 'revision';
$post->post_modified_gmt = get_post( $post->post_parent )->post_modified_gmt;
wp_cache_set( $post->ID, $post, 'posts' );
wp_cache_set( 'spoofed_revision', $post, 'fork' );
add_action( 'shutdown', array( $this, 'unspoof_revision' ) );
}
/**
* If we spoofed a revision on the start of revision.php, unspoof the revision, in case
* the site has persistent cache, unspoof the post prior to shutdown, so that the cache is
* acurate on subsequent page loads.
*
* Note: this only fires when spoof_revision() was fired on a page
*
*/
function unspoof_revision() {
$post = wp_cache_get( 'spoofed_revision', 'fork' );
if ( !$post || !is_object( $post ) )
return;
$post->post_type = 'fork';
wp_cache_set( $post->ID, $post, 'posts' );
wp_cache_delete( 'spoofed_revision', 'fork' ); //in case we have a persistent cache
}
}
/**
* We really don't want to get in the business of rewriting WP_Text_Diff_Renderer_table
* It's hugely complex, well thought out, and works well.
* Problem is however, it can only render two way diffs
* What we're doing here is running our normaly three-way diff, then passing that to
* renderer as a two way diff. We get better results, without the heavy lift.
*
* The process here is to replace the function wp_text_diff with our own function
* essentially writing a filter into core that doesn't exist.
* Our version of wp_text_diff checks to see if we're comparing a fork,
* and if so, does the three way merge
* otherwise, we're running wp_text_diff essentially unchanged.
* We could do this as one function (and just look for $_GET, but passing
* as an arg is a bit cleaner of a solution in terms of hooking into other plugins, etc.
*
* Note, unless we're on revision.php and action is diff, we're running core's version
*/
if ( !function_exists( 'wp_text_diff' ) ) :
//verify page
if ( stripos( $_SERVER['PHP_SELF'], 'revision.php' ) === false )
return;
//verify action
if ( !isset( $_GET['action'] ) || $_GET['action'] != 'diff' )
return;
/**
* Replace function with check for post_type, pass an arg if so
*/
function wp_text_diff( $left, $right, $args = array() ) {
//not a fork, transparently run a two-way post diff
if ( !isset( $_GET['right'] ) || get_post_type( $_GET['right'] != 'fork' ) )
return _wp_text_diff( $left, $right, $args );
$args['fork'] = isset( $_GET['right'] ) ? $_GET['right'] : false;
return _wp_text_Diff( $left, $right, $args );
}
/**
* Normal wp_text_diff with three lines added as indicated
* @access private
* @version 3.4
*/
function _wp_text_diff( $left_string, $right_string, $args = null ) {
//fork edit: added parent arg
$defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '', 'fork' => false );
$args = wp_parse_args( $args, $defaults );
if ( !class_exists( 'WP_Text_Diff_Renderer_Table' ) )
require ABSPATH . WPINC . '/wp-diff.php';
//begin fork edit
global $fork;
if ( $args['fork'] ) {
global $fork;
$parent = $fork->revisions->get_previous_revision( $args['fork'] );
$left_lines = get_post( $parent )->post_content;
}
//end edit
$left_string = normalize_whitespace($left_string);
$right_string = normalize_whitespace($right_string);
$left_lines = explode("\n", $left_string);
$right_lines = explode("\n", $right_string);
$text_diff = new Text_Diff($left_lines, $right_lines);
$renderer = new WP_Text_Diff_Renderer_Table();
$diff = $renderer->render( $text_diff );
if ( !$diff )
return '';
$r = "<table class='diff'>\n";
$r .= "<col class='ltype' /><col class='content' /><col class='ltype' /><col class='content' />";
if ( $args['title'] || $args['title_left'] || $args['title_right'] )
$r .= "<thead>";
if ( $args['title'] )
$r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
if ( $args['title_left'] || $args['title_right'] ) {
$r .= "<tr class='diff-sub-title'>\n";
$r .= "\t<td></td><th>$args[title_left]</th>\n";
$r .= "\t<td></td><th>$args[title_right]</th>\n";
$r .= "</tr>\n";
}
if ( $args['title'] || $args['title_left'] || $args['title_right'] )
$r .= "</thead>\n";
$r .= "<tbody>\n$diff\n</tbody>\n";
$r .= "</table>";
return $r;
}
endif;