PluginProbe
Email Post Changes / 0.7
Email Post Changes v0.7
trunk 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.7.1 1.7.2
← All changes | class.email-post-changes.php +52 -191 1.50.7 View file →
@@ -11,9 +11,9 @@
11 11 const ADMIN_PAGE = 'email_post_changes';
12 12 const OPTION_GROUP = 'email_post_changes';
13 13 const OPTION = 'email_post_changes';
14 14
15 - function init() {
15 + function &init() {
16 16 static $instance = null;
17 17
18 18 if ( $instance )
19 19 return $instance;
@@ -23,34 +23,23 @@
23 23 return $instance;
24 24 }
25 25
26 26 function __construct() {
27 - $this->defaults = apply_filters( 'email_post_changes_default_options', array(
28 - 'enable' => 1,
29 - 'users' => array(),
27 + $this->defaults = array(
30 28 'emails' => array( get_option( 'admin_email' ) ),
31 29 'post_types' => array( 'post', 'page' ),
32 30 'drafts' => 0,
33 - ) );
31 + );
34 32
35 - $options = $this->get_options();
36 -
37 - if ( $options['enable'] )
38 - add_action( 'post_updated', array( $this, 'post_updated' ), 10, 3 );
39 - if ( current_user_can( 'manage_options' ) )
40 - add_action( 'admin_menu', array( $this, 'admin_menu' ), 115 );
33 + add_action( 'wp_insert_post', array( &$this, 'wp_insert_post' ), 10, 2 );
34 + add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
41 35 }
42 36
43 37 function get_post_types() {
44 - $post_types = get_post_types( array( 'public' => true ) );
45 - $_post_types = array();
46 -
47 - foreach ( $post_types as $post_type ) {
48 - if ( post_type_supports( $post_type, 'revisions' ) )
49 - $_post_types[] = $post_type;
50 - }
51 -
52 - return $_post_types;
38 + $post_types = get_post_types();
39 + if ( false !== $pos = array_search( 'revision', $post_types ) )
40 + unset( $post_types[$pos] );
41 + return $post_types;
53 42 }
54 43
55 44 function get_options( $just_defaults = false ) {
56 45 if ( $just_defaults )
@@ -61,27 +50,22 @@
61 50 return wp_parse_args( $options, $this->defaults );
62 51 }
63 52
64 53 // The meat of the plugin
65 - function post_updated( $post_id, $post_after, $post_before ) {
54 + function wp_insert_post( $post_id, $post ) {
66 55 $options = $this->get_options();
67 - // If we're purely saving a draft, and don't have the draft option enabled, skip. If we're transitioning one way or the other, send a notification.
68 - if ( 0 == $options['drafts'] && 'draft' == $post_before->post_status && 'draft' == $post_after->post_status )
69 - return;
70 -
71 - if ( isset( $_POST['autosave'] ) )
72 - return;
73 56
74 - if ( !in_array( $post_before->post_type, $options['post_types'] ) )
57 + if ( !$options['drafts'] && 'draft' == $post->post_status )
75 58 return;
76 59
77 - $this->left_post = $post_before;
78 - $this->right_post = $post_after;
79 -
80 - // If this is a new post, set an empty title for $this->left_post so that it appears in the diff.
81 - $child_posts = wp_get_post_revisions( $post_id, array( 'numberposts' => 1 ) );
82 - if ( count( $child_posts ) == 0 ) {
83 - $this->left_post->post_title = '';
60 + if ( 'revision' == $post->post_type ) { // Revision is saved first
61 + if ( wp_is_post_autosave( $post ) )
62 + return;
63 + $this->left_post = $post;
64 + } elseif ( !empty( $this->left_post ) && $this->left_post->post_parent == $post->ID ) { // Then new post
65 + if ( !in_array( $post->post_type, $options['post_types'] ) )
66 + return;
67 + $this->right_post = $post;
84 68 }
85 69
86 70 if ( !$this->left_post || !$this->right_post )
87 71 return;
@@ -92,9 +76,9 @@
92 76 foreach ( _wp_post_revision_fields() as $field => $field_title ) {
93 77 $left = apply_filters( "_wp_post_revision_field_$field", $this->left_post->$field, $field );
94 78 $right = apply_filters( "_wp_post_revision_field_$field", $this->right_post->$field, $field );
95 79
96 - if ( !$diff = $this->wp_text_diff( $left, $right ) )
80 + if ( !$diff = wp_text_diff( $left, $right ) )
97 81 continue;
98 82 $html_diffs[$field_title] = $diff;
99 83
100 84 $left = normalize_whitespace( $left );
@@ -111,16 +95,13 @@
111 95
112 96 $identical = false;
113 97 }
114 98
115 - if ( $identical ) {
116 - $this->left_post = null;
117 - $this->right_post = null;
99 + if ( $identical )
118 100 return;
119 - }
120 101
121 102 // Grab the meta data
122 - $the_author = get_the_author_meta( 'display_name', get_current_user_id() ); // The revision
103 + $the_author = get_the_author_meta( 'display_name', $this->left_post->post_author ); // The revision
123 104 $the_title = get_the_title( $this->right_post->ID ); // New title (may be same as old title)
124 105 $the_date = gmdate( 'j F, Y \a\t G:i \U\T\C', strtotime( $this->right_post->post_modified_gmt . '+0000' ) ); // Modified time
125 106 $the_permalink = clean_url( get_permalink( $this->right_post->ID ) );
126 107 $the_edit_link = clean_url( get_edit_post_link( $this->right_post->ID ) );
@@ -195,9 +176,9 @@
195 176 $charset = apply_filters( 'wp_mail_charset', get_option( 'blog_charset' ) );
196 177 $blogname = html_entity_decode( get_option( 'blogname' ), ENT_QUOTES, $charset );
197 178 $title = html_entity_decode( $the_title, ENT_QUOTES, $charset );
198 179
199 - add_action( 'phpmailer_init', array( $this, 'phpmailer_init_once' ) );
180 + add_action( 'phpmailer_init', array( &$this, 'phpmailer_init_once' ) );
200 181
201 182 wp_mail(
202 183 null, // see hack in ::phpmailer_init_once()
203 184 sprintf( __( '[%s] %s changed: %s' ), $blogname, $post_type, $title ),
@@ -202,45 +183,19 @@
202 183 null, // see hack in ::phpmailer_init_once()
203 184 sprintf( __( '[%s] %s changed: %s' ), $blogname, $post_type, $title ),
204 185 $html_diff
205 186 );
206 -
207 - $this->left_post = null;
208 - $this->right_post = null;
209 -
210 - do_action( 'email_post_changes_email_sent' );
211 187 }
212 188
213 189 /* Email hook */
214 - function phpmailer_init_once( $phpmailer ) {
215 - global $blog_id;
216 -
217 - remove_action( 'phpmailer_init', array( $this, 'phpmailer_init_once' ) );
190 + function phpmailer_init_once( &$phpmailer ) {
191 + remove_action( 'phpmailer_init', array( &$this, 'phpmailer_init_once' ) );
218 192 $phpmailer->AltBody = $this->text_diff;
219 193
220 - $phpmailer->ClearAddresses(); // hack
194 + $phpmailer->to = array(); // Hack
221 195
222 196 $options = $this->get_options();
223 -
224 - $user_emails = array();
225 - foreach( $options['users'] as $user_id ) {
226 - if ( function_exists( 'is_multisite' ) && is_multisite() ) {
227 - if ( is_user_member_of_blog( $user_id, $blog_id ) )
228 - $user_emails[] = get_user_option( 'user_email', $user_id );
229 - } else {
230 - if ( $user_email = get_user_option( 'user_email', $user_id ) )
231 - $user_emails[] = $user_email;
232 - }
233 - }
234 -
235 - $emails = array_unique( array_merge( $options['emails'], $user_emails ) );
236 -
237 - if ( !count( $emails ) )
238 - $emails[] = get_option( 'admin_email');
239 -
240 - $emails = apply_filters( 'email_post_changes_emails', $emails, $this->left_post->ID, $this->right_post->ID );
241 -
242 - foreach ( $emails as $email )
197 + foreach ( $options['emails'] as $email )
243 198 $phpmailer->AddAddress( $email );
244 199
245 200 $phpmailer->AddReplyTo(
246 201 get_the_author_meta( 'email', $this->right_post->post_author ),
@@ -256,23 +211,22 @@
256 211 // 3.0
257 212 $post_type_object = get_post_type_object( $post_type );
258 213 if ( empty( $post_type_object->label ) )
259 214 return ucwords( str_replace( '_', ' ', $post_type ) );
215 +
260 216 return $post_type_object->label;
261 217 }
262 218
263 219 /* Admin */
264 220 function admin_menu() {
265 - register_setting( self::OPTION_GROUP, self::OPTION, array( $this, 'validate_options' ) );
221 + register_setting( self::OPTION_GROUP, self::OPTION, array( &$this, 'validate_options' ) );
266 222
267 - add_settings_section( self::ADMIN_PAGE, __( 'Email Post Changes' ), array( $this, 'settings_section' ), self::ADMIN_PAGE );
268 - add_settings_field( self::ADMIN_PAGE . '_enable', __( 'Enable' ), array( $this, 'enable_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
269 - add_settings_field( self::ADMIN_PAGE . '_users', __( 'Users to Email' ), array( $this, 'users_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
270 - add_settings_field( self::ADMIN_PAGE . '_emails', __( 'Additional Email Addresses' ), array( $this, 'emails_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
271 - add_settings_field( self::ADMIN_PAGE . '_post_types', __( 'Post Types' ), array( $this, 'post_types_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
272 - add_settings_field( self::ADMIN_PAGE . '_drafts', __( 'Drafts' ), array( $this, 'drafts_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
223 + add_settings_section( self::ADMIN_PAGE, __( 'Email Post Changes' ), array( &$this, 'settings_section' ), self::ADMIN_PAGE );
224 + add_settings_field( self::ADMIN_PAGE . '_emails', __( 'Email Addresses' ), array( &$this, 'emails_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
225 + add_settings_field( self::ADMIN_PAGE . '_post_types', __( 'Post Types' ), array( &$this, 'post_types_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
226 + add_settings_field( self::ADMIN_PAGE . '_drafts', __( 'Drafts' ), array( &$this, 'drafts_setting' ), self::ADMIN_PAGE, self::ADMIN_PAGE );
273 227
274 - add_options_page( __( 'Email Post Changes' ), __( 'Email Post Changes' ), 'manage_options', self::ADMIN_PAGE, array( $this, 'admin_page' ) );
228 + add_options_page( __( 'Email Post Changes' ), __( 'Email Post Changes' ), 'manage_options', self::ADMIN_PAGE, array( &$this, 'admin_page' ) );
275 229 }
276 230
277 231 function validate_options( $options ) {
278 232 if ( !$options || !is_array( $options ) )
@@ -279,48 +233,18 @@
279 233 return $this->defaults;
280 234
281 235 $return = array();
282 236
283 - $return['enable'] = ( empty( $options['enable'] ) ) ? 0 : 1;
284 -
285 - if ( empty( $options['users'] ) || !is_array( $options ) ) {
286 - $return['users'] = $this->defaults['users'];
287 - } else {
288 - $return['users'] = $options['users'];
289 - }
290 -
291 237 if ( empty( $options['emails'] ) ) {
292 - if ( count( $return['users'] ) )
293 - $return['emails'] = array();
294 - else
295 - $return['emails'] = $this->defaults['emails'];
238 + $return['emails'] = $this->defaults['emails'];
296 239 } else {
297 240 if ( is_string( $options['emails'] ) )
298 241 $_emails = preg_split( '(\n|\r)', $options['emails'], -1, PREG_SPLIT_NO_EMPTY );
299 242 $_emails = array_unique( (array) $_emails );
300 243 $emails = array_filter( $_emails, 'is_email' );
301 -
302 - $invalid_emails = array_diff( $_emails, $emails );
303 - if ( $invalid_emails )
304 - $return['invalid_emails'] = $invalid_emails;
305 -
306 - if ( $emails )
307 - $return['emails'] = $emails;
308 - elseif ( count( $return['users'] ) )
309 - $return['emails'] = array();
310 - else
311 - $return['emails'] = $this->defaults['emails'];
312 -
313 - // Don't store a huge list of invalid emails addresses in the option
314 - if ( count( $return['invalid_emails'] ) > 200 ) {
315 - $return['invalid_emails'] = array_slice( $return['invalid_emails'], 0, 200 );
316 - $return['invalid_emails'][] = __( 'and many more not listed here' );
317 - }
318 -
319 - // Cap to at max 200 email addresses
320 - if ( count( $return['emails'] ) > 200 ) {
321 - $return['emails'] = array_slice( $return['emails'], 0, 200 );
322 - }
244 + if ( $diff = array_diff( $_emails, $emails ) )
245 + $return['invalid_emails'] = $diff;
246 + $return['emails'] = $emails ? $emails : $this->defaults['emails'];
323 247 }
324 248
325 249 if ( empty( $options['post_types'] ) || !is_array( $options ) ) {
326 250 $return['post_types'] = $this->defaults['post_types'];
@@ -330,10 +254,8 @@
330 254 }
331 255
332 256 $return['drafts'] = ( empty( $options['drafts'] ) ) ? 0 : 1;
333 257
334 - do_action( 'email_post_changes_validate_options', $this->get_options(), $return );
335 -
336 258 return $return;
337 259 }
338 260
339 261 function admin_page() {
@@ -341,9 +263,10 @@
341 263 ?>
342 264
343 265 <div class="wrap">
344 266 <h2><?php _e( 'Email Post Changes' ); ?></h2>
345 -<?php if ( !empty( $options['invalid_emails'] ) && $_GET['settings-updated'] ) : ?>
267 +<?php if ( !empty( $options['invalid_emails'] ) ) : ?>
268 +
346 269 <div class="error">
347 270 <p><?php printf( _n( 'Invalid Email: %s', 'Invalid Emails: %s', count( $options['invalid_emails'] ) ), '<kbd>' . join( '</kbd>, <kbd>', array_map( 'esc_html', $options['invalid_emails'] ) ) ); ?></p>
348 271 </div>
349 272 <?php endif; ?>
@@ -360,41 +283,17 @@
360 283 }
361 284
362 285 function settings_section() {} // stub
363 286
364 - function enable_setting() {
365 - $options = $this->get_options();
366 -?>
367 - <p><label><input type="checkbox" name="email_post_changes[enable]" value="1"<?php checked( $options['enable'], 1 ); ?> /> <?php _e( 'Send an email when a post or page changes.' ); ?></label></p>
368 -<?php
369 - }
370 -
371 - function users_setting() {
372 - $options = $this->get_options();
373 -?>
374 - <div style="overflow: auto; max-height: 300px;">
375 - <ul>
376 -<?php $users = get_users();
377 - usort( $users, array( $this, 'sort_users_by_display_name' ) );
378 -
379 - foreach ( $users as $user ) : ?>
380 - <li><label><input type="checkbox" name="email_post_changes[users][]" value="<?php echo (int) $user->ID; ?>"<?php checked( in_array( $user->ID, $options['users'] ) ); ?> /> <?php echo esc_html( $user->display_name ); ?> ( <?php echo esc_html( $user->user_login ); ?> - <?php echo esc_html( $user->user_email ); ?> )</label></li>
381 -
382 -<?php endforeach; ?>
383 - </ul>
384 - </div>
385 -<?php
386 - }
387 -
388 - function sort_users_by_display_name( $a, $b ) {
389 - return strcmp( strtolower( $a->display_name ), strtolower( $b->display_name ) );
390 - }
391 -
392 287 function emails_setting() {
393 288 $options = $this->get_options();
394 289 ?>
395 290 <textarea rows="4" cols="40" style="width: 40em;" name="email_post_changes[emails]"><?php echo esc_html( join( "\n", $options['emails'] ) ); ?></textarea>
396 - <p class="description"><?php _e( 'One email address per line.' ); ?></p>
291 + <p class="description"><?php _e( 'Send emails to these addresses. One per line.' ); ?></p>
292 + <p class="description"><?php printf(
293 + __( "If blank, send emails to this site&#8217;s <a href='%s'>admin email address</a>." ),
294 + clean_url( get_bloginfo( 'wpurl' ) . '/wp-admin/options-general.php#admin_email' )
295 + ); ?></p>
397 296 <?php
398 297 }
399 298
400 299 function post_types_setting() {
@@ -399,15 +298,20 @@
399 298
400 299 function post_types_setting() {
401 300 $options = $this->get_options();
402 301 ?>
302 +
403 303 <ul>
404 -<?php foreach ( $this->get_post_types() as $post_type ) :
304 +<?php
305 + foreach ( $this->get_post_types() as $post_type ) :
405 306 $label = $this->get_post_type_label( $post_type );
406 307 ?>
407 308 <li><label><input type="checkbox" name="email_post_changes[post_types][]" value="<?php echo esc_attr( $post_type ); ?>"<?php checked( in_array( $post_type, $options['post_types'] ) ); ?> /> <?php echo esc_html( $label ); ?></label></li>
408 309 <?php endforeach; ?>
310 +
409 311 </ul>
312 + <p class="description"><?php _e( 'Send emails when a post of these post types changes.' ); ?></p>
313 + <p class="description"><?php _e( 'If none are selected, &#8220;post&#8221; and &#8220;page&#8221; will be checked by default.' ); ?></p>
410 314 <?php
411 315 }
412 316
413 317 function drafts_setting() {
@@ -412,52 +316,9 @@
412 316
413 317 function drafts_setting() {
414 318 $options = $this->get_options();
415 319 ?>
320 +
416 321 <p><label><input type="checkbox" name="email_post_changes[drafts]" value="1"<?php checked( $options['drafts'], 1 ); ?> /> <?php _e( 'Email changes to drafts, not just published items.' ); ?></label></p>
417 322 <?php
418 323 }
419 -
420 - function wp_text_diff( $left_string, $right_string, $args = null ) {
421 - $defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
422 - $args = wp_parse_args( $args, $defaults );
423 -
424 - $left_string = normalize_whitespace( $left_string );
425 - $right_string = normalize_whitespace( $right_string );
426 - $left_lines = explode( "\n", $left_string );
427 - $right_lines = explode( "\n", $right_string );
428 -
429 - $text_diff = new Text_Diff( $left_lines, $right_lines );
430 - $renderer = new Email_Post_Changes_Diff();
431 - $diff = $renderer->render( $text_diff );
432 -
433 - if ( !$diff )
434 - return '';
435 -
436 - $r = "<table class='diff'>\n";
437 - $r .= "<col class='ltype' /><col class='content' /><col class='ltype' /><col class='content' />";
438 -
439 - if ( $args['title'] || $args['title_left'] || $args['title_right'] )
440 - $r .= "<thead>";
441 - if ( $args['title'] )
442 - $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
443 - if ( $args['title_left'] || $args['title_right'] ) {
444 - $r .= "<tr class='diff-sub-title'>\n";
445 - $r .= "\t<td></td><th>$args[title_left]</th>\n";
446 - $r .= "\t<td></td><th>$args[title_right]</th>\n";
447 - $r .= "</tr>\n";
448 - }
449 - if ( $args['title'] || $args['title_left'] || $args['title_right'] )
450 - $r .= "</thead>\n";
451 - $r .= "<tbody>\n$diff\n</tbody>\n";
452 - $r .= "</table>";
453 - return $r;
454 - }
455 -}
456 -
457 -if ( !class_exists( 'WP_Text_Diff_Renderer_Table' ) )
458 - require( ABSPATH . WPINC . '/wp-diff.php' );
459 -
460 -class Email_Post_Changes_Diff extends WP_Text_Diff_Renderer_Table {
461 - var $_leading_context_lines = 2;
462 - var $_trailing_context_lines = 2;
463 324 }