PluginProbe
Edit Flow / 0.9.1
Edit Flow v0.9.1
0.11.1 0.11.0 0.7.2 0.7.3 0.7.4 0.7.5 0.7.6 0.8 0.8.1 0.8.2 0.9 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 trunk 0.1.5 0.10.0 0.10.1 0.10.2 All 44 releases
edit-flow / modules / notifications / notifications.php

notifications.php in Edit Flow 0.9.1, at modules/notifications/notifications.php

1,279 lines 47.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * class EF_Notifications
4 * Email notifications for Edit Flow and more
5 */
6
7 if( ! defined( 'EF_NOTIFICATION_USE_CRON' ) )
8 define( 'EF_NOTIFICATION_USE_CRON', false );
9
10 if ( !class_exists('EF_Notifications') ) {
11
12 class EF_Notifications extends EF_Module {
13
14 // Taxonomy name used to store users following posts
15 var $following_users_taxonomy = 'following_users';
16 // Taxonomy name used to store user groups following posts
17 var $following_usergroups_taxonomy = EF_User_Groups::taxonomy_key;
18
19 var $module;
20
21 var $edit_post_subscriptions_cap = 'edit_post_subscriptions';
22
23 /**
24 * Register the module with Edit Flow but don't do anything else
25 */
26 function __construct () {
27
28 // Register the module with Edit Flow
29 $this->module_url = $this->get_module_url( __FILE__ );
30 $args = array(
31 'title' => __( 'Notifications', 'edit-flow' ),
32 'short_description' => __( 'Update your team of important changes to your content.', 'edit-flow' ),
33 'extended_description' => __( 'With email notifications, you can keep everyone updated about what’s happening with a given content. Each status change or editorial comment sends out an email notification to users subscribed to a post. User groups can be used to manage who receives notifications on what.', 'edit-flow' ),
34 'module_url' => $this->module_url,
35 'img_url' => $this->module_url . 'lib/notifications_s128.png',
36 'slug' => 'notifications',
37 'default_options' => array(
38 'enabled' => 'on',
39 'post_types' => array(
40 'post' => 'on',
41 'page' => 'on',
42 ),
43 'always_notify_admin' => 'off',
44 ),
45 'configure_page_cb' => 'print_configure_view',
46 'post_type_support' => 'ef_notification',
47 'autoload' => false,
48 'settings_help_tab' => array(
49 'id' => 'ef-notifications-overview',
50 'title' => __('Overview', 'edit-flow'),
51 'content' => __('<p>Notifications ensure you keep up to date with progress your most important content. Users can be subscribed to notifications on a post one by one or by selecting user groups.</p><p>When enabled, email notifications can be sent when a post changes status or an editorial comment is left by a writer or an editor.</p>', 'edit-flow'),
52 ),
53 'settings_help_sidebar' => __( '<p><strong>For more information:</strong></p><p><a href="http://editflow.org/features/notifications/">Notifications Documentation</a></p><p><a href="http://wordpress.org/tags/edit-flow?forum_id=10">Edit Flow Forum</a></p><p><a href="https://github.com/danielbachhuber/Edit-Flow">Edit Flow on Github</a></p>', 'edit-flow' ),
54 );
55 $this->module = EditFlow()->register_module( 'notifications', $args );
56
57 }
58
59 /**
60 * Initialize the notifications class if the plugin is enabled
61 */
62 function init() {
63
64 // Register our taxonomies for managing relationships
65 $this->register_taxonomies();
66
67 // Allow users to use a different user capability for editing post subscriptions
68 $this->edit_post_subscriptions_cap = apply_filters( 'ef_edit_post_subscriptions_cap', $this->edit_post_subscriptions_cap );
69
70 // Set up metabox and related actions
71 add_action( 'add_meta_boxes', array( $this, 'add_post_meta_box' ) );
72
73 // Add "access badge" to the subscribers list.
74 add_action( 'ef_user_subscribe_actions', array( $this, 'display_subscriber_warning_badges' ), 10, 2 );
75
76 // Saving post actions
77 // self::save_post_subscriptions() is hooked into transition_post_status so we can ensure usergroup data
78 // is properly saved before sending notifs
79 add_action( 'transition_post_status', array( $this, 'save_post_subscriptions' ), 0, 3 );
80 add_action( 'transition_post_status', array( $this, 'notification_status_change' ), 10, 3 );
81 add_action( 'ef_post_insert_editorial_comment', array( $this, 'notification_comment') );
82 add_action( 'delete_user', array($this, 'delete_user_action') );
83 add_action( 'ef_send_scheduled_email', array( $this, 'send_single_email' ), 10, 4 );
84
85 add_action( 'admin_init', array( $this, 'register_settings' ) );
86
87 // Javascript and CSS if we need it
88 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
89 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
90
91 // Add a "Follow" link to posts
92 if ( apply_filters( 'ef_notifications_show_follow_link', true ) ) {
93 // A little extra JS for the follow button
94 add_action( 'admin_head', array( $this, 'action_admin_head_follow_js' ) );
95 // Manage Posts
96 add_filter( 'post_row_actions', array( $this, 'filter_post_row_actions' ), 10, 2 );
97 add_filter( 'page_row_actions', array( $this, 'filter_post_row_actions' ), 10, 2 );
98 // Calendar and Story Budget
99 add_filter( 'ef_calendar_item_actions', array( $this, 'filter_post_row_actions' ), 10, 2 );
100 add_filter( 'ef_story_budget_item_actions', array( $this, 'filter_post_row_actions' ), 10, 2 );
101 }
102
103 //Ajax for saving notifiction updates
104 add_action( 'wp_ajax_save_notifications', array( $this, 'ajax_save_post_subscriptions' ) );
105 add_action( 'wp_ajax_ef_notifications_user_post_subscription', array( $this, 'handle_user_post_subscription' ) );
106
107 }
108
109 /**
110 * Load the capabilities onto users the first time the module is run
111 *
112 * @since 0.7
113 */
114 function install() {
115
116 // Add necessary capabilities to allow management of notifications
117 $notifications_roles = array(
118 'administrator' => array('edit_post_subscriptions'),
119 'editor' => array('edit_post_subscriptions'),
120 'author' => array('edit_post_subscriptions'),
121 );
122
123 foreach ( $notifications_roles as $role => $caps ) {
124 $this->add_caps_to_role( $role, $caps );
125 }
126
127 }
128
129 /**
130 * Upgrade our data in case we need to
131 *
132 * @since 0.7
133 */
134 function upgrade( $previous_version ) {
135 global $edit_flow;
136
137 // Upgrade path to v0.7
138 if ( version_compare( $previous_version, '0.7' , '<' ) ) {
139 // Migrate whether notifications were enabled or not
140 if ( $enabled = get_option( 'edit_flow_notifications_enabled' ) )
141 $enabled = 'on';
142 else
143 $enabled = 'off';
144 $edit_flow->update_module_option( $this->module->name, 'enabled', $enabled );
145 delete_option( 'edit_flow_notifications_enabled' );
146 // Migrate whether to always notify the admin
147 if ( $always_notify_admin = get_option( 'edit_flow_always_notify_admin' ) )
148 $always_notify_admin = 'on';
149 else
150 $always_notify_admin = 'off';
151 $edit_flow->update_module_option( $this->module->name, 'always_notify_admin', $always_notify_admin );
152 delete_option( 'edit_flow_always_notify_admin' );
153
154 // Technically we've run this code before so we don't want to auto-install new data
155 $edit_flow->update_module_option( $this->module->name, 'loaded_once', true );
156 }
157
158 }
159
160 /**
161 * Register the taxonomies we use to manage relationships
162 *
163 * @since 0.7
164 *
165 * @uses register_taxonomy()
166 */
167 function register_taxonomies() {
168
169 // Load the currently supported post types so we only register against those
170 $supported_post_types = $this->get_post_types_for_module( $this->module );
171
172 $args = array(
173 'hierarchical' => false,
174 'update_count_callback' => '_update_post_term_count',
175 'label' => false,
176 'query_var' => false,
177 'rewrite' => false,
178 'public' => false,
179 'show_ui' => false
180 );
181 register_taxonomy( $this->following_users_taxonomy, $supported_post_types, $args );
182 }
183
184 /**
185 * Enqueue necessary admin scripts
186 *
187 * @since 0.7
188 *
189 * @uses wp_enqueue_script()
190 */
191 function enqueue_admin_scripts() {
192
193 if ( $this->is_whitelisted_functional_view() ) {
194 wp_enqueue_script( 'jquery-listfilterizer' );
195 wp_enqueue_script( 'jquery-quicksearch' );
196 wp_enqueue_script( 'edit-flow-notifications-js', $this->module_url . 'lib/notifications.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true );
197 wp_localize_script(
198 'edit-flow-notifications-js',
199 'ef_notifications_localization',
200 array(
201 'no_access' => esc_html__( 'No Access', 'edit-flow' ),
202 'no_email' => esc_html__( 'No Email', 'edit-flow' )
203 )
204 );
205 }
206 }
207
208 /**
209 * Enqueue necessary admin styles, but only on the proper pages
210 *
211 * @since 0.7
212 *
213 * @uses wp_enqueue_style()
214 */
215 function enqueue_admin_styles() {
216
217 if ( $this->is_whitelisted_functional_view() || $this->is_whitelisted_settings_view() ) {
218 wp_enqueue_style( 'jquery-listfilterizer' );
219 wp_enqueue_style( 'edit-flow-notifications-css', $this->module->module_url . 'lib/notifications.css', false, EDIT_FLOW_VERSION );
220 }
221 }
222
223 /**
224 * JS required for the Follow link to work
225 *
226 * @since 0.8
227 */
228 public function action_admin_head_follow_js() {
229 ?>
230 <script type='text/Javascript'>
231 jQuery(document).ready(function($) {
232 /**
233 * Action to Follow / Unfollow posts on the manage posts screen
234 */
235 $('.wp-list-table, #ef-calendar-view, #ef-story-budget-wrap').on( 'click', '.ef_follow_link a', function(e){
236
237 e.preventDefault();
238
239 var link = $(this);
240
241 $.ajax({
242 type : 'GET',
243 url : link.attr( 'href' ),
244 success : function( data ) {
245 if ( 'success' == data.status ) {
246 link.attr( 'href', data.message.link );
247 link.attr( 'title', data.message.title );
248 link.text( data.message.text );
249 }
250 // @todo expose the error somehow
251 }
252 });
253 return false;
254 });
255 });
256 </script><?php
257 }
258
259 /**
260 * Add a "Follow" link to supported post types Manage Posts view
261 *
262 * @since 0.8
263 *
264 * @param array $actions Any existing item actions
265 * @param int|object $post Post id or object
266 * @return array $actions The follow link has been appended
267 */
268 public function filter_post_row_actions( $actions, $post ) {
269
270 $post = get_post( $post );
271
272 if ( ! in_array( $post->post_type, $this->get_post_types_for_module( $this->module ) ) )
273 return $actions;
274
275 if ( ! current_user_can( $this->edit_post_subscriptions_cap ) || ! current_user_can( 'edit_post', $post->ID ) )
276 return $actions;
277
278 $parts = $this->get_follow_action_parts( $post );
279 $actions['ef_follow_link'] = '<a title="' . esc_attr( $parts['title'] ) . '" href="' . esc_url( $parts['link'] ) . '">' . $parts['text'] . '</a>';
280
281 return $actions;
282 }
283
284 /**
285 * Get an action parts for a user to follow or unfollow a post
286 *
287 * @since 0.8
288 */
289 private function get_follow_action_parts( $post ) {
290
291 $args = array(
292 'action' => 'ef_notifications_user_post_subscription',
293 'post_id' => $post->ID,
294 );
295 $following_users = $this->get_following_users( $post->ID );
296 if ( in_array( wp_get_current_user()->user_login, $following_users ) ) {
297 $args['method'] = 'unfollow';
298 $title_text = __( 'Click to unfollow updates to this post', 'edit-flow' );
299 $follow_text = __( 'Following', 'edit-flow' );
300 } else {
301 $args['method'] = 'follow';
302 $title_text = __( 'Follow updates to this post', 'edit-flow' );
303 $follow_text = __( 'Follow', 'edit-flow' );
304 }
305
306 // wp_nonce_url() has encoding issues: http://core.trac.wordpress.org/ticket/20771
307 $args['_wpnonce'] = wp_create_nonce( 'ef_notifications_user_post_subscription' );
308
309 return array(
310 'title' => $title_text,
311 'text' => $follow_text,
312 'link' => add_query_arg( $args, admin_url( 'admin-ajax.php' ) ),
313 );
314 }
315
316 /**
317 * Add the subscriptions meta box to relevant post types
318 */
319 function add_post_meta_box() {
320
321 if ( !current_user_can( $this->edit_post_subscriptions_cap ) )
322 return;
323
324 $usergroup_post_types = $this->get_post_types_for_module( $this->module );
325 foreach ( $usergroup_post_types as $post_type ) {
326 add_meta_box( 'edit-flow-notifications', __( 'Notifications', 'edit-flow'), array( $this, 'notifications_meta_box'), $post_type, 'advanced' );
327 }
328 }
329
330 /**
331 * Outputs box used to subscribe users and usergroups to Posts
332 *
333 * @todo add_cap to set subscribers for posts; default to Admin and editors
334 */
335 function notifications_meta_box() {
336 global $post, $post_ID, $edit_flow;
337 ?>
338 <div id="ef-post_following_box">
339 <a name="subscriptions"></a>
340
341 <p><?php _e( 'Select the users and user groups that should receive notifications when the status of this post is updated or when an editorial comment is added.', 'edit-flow' ); ?></p>
342 <div id="ef-post_following_users_box">
343 <h4><?php _e( 'Users', 'edit-flow' ); ?></h4>
344 <?php
345 $followers = $this->get_following_users( $post->ID, 'id' );
346 $select_form_args = array(
347 'list_class' => 'ef-post_following_list',
348 );
349 $this->users_select_form( $followers, $select_form_args ); ?>
350 </div>
351
352 <?php if ( $this->module_enabled( 'user_groups' ) && in_array( $this->get_current_post_type(), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ) ): ?>
353 <div id="ef-post_following_usergroups_box">
354 <h4><?php _e('User Groups', 'edit-flow') ?></h4>
355 <?php
356 $following_usergroups = $this->get_following_usergroups( $post->ID, 'ids' );
357 $edit_flow->user_groups->usergroups_select_form( $following_usergroups ); ?>
358 </div>
359 <?php endif; ?>
360 <div class="clear"></div>
361 <input type="hidden" name="ef-save_followers" value="1" /> <?php // Extra protection against autosaves ?>
362 <?php wp_nonce_field('save_user_usergroups', 'ef_notifications_nonce', false); ?>
363 </div>
364
365 <?php
366 }
367
368 /**
369 * Show warning badges next to a subscriber's name if they won't receive notifications
370 *
371 * Applies on initial loading of list via. PHP. JS will set these spans based on AJAX response when box is ticked/unticked.
372 *
373 * @param int $user_id
374 * @param bool $checked True if the user is subscribed already, false otherwise.
375 * @return void
376 */
377 function display_subscriber_warning_badges( $user_id, $checked ) {
378 global $post;
379
380 if (!isset( $post ) OR !$checked ) {
381 return;
382 }
383
384 // Add No Access span if they won't be notified
385 if (! $this->user_can_be_notified( get_user_by( 'id', $user_id ), $post->ID )) {
386 // span.post_following_list-no_access is also added in notifications.js after AJAX that ticks/unticks a user
387 echo '<span class="post_following_list-no_access">' . esc_html__( 'No Access', 'edit-flow' ) . '</span>';
388 }
389
390 // Add No Email span if they have no email
391 $user_object = get_user_by( 'id', $user_id );
392 if ( !is_a( $user_object, 'WP_User') OR empty( $user_object->user_email ) ) {
393 // span.post_following_list-no_email is also added in notifications.js after AJAX that ticks/unticks a user
394 echo '<span class="post_following_list-no_email">' . esc_html__( 'No Email', 'edit-flow' ) . '</span>';
395 }
396 }
397
398 /**
399 * Called when a notification editorial metadata checkbox is checked. Handles saving of a user/usergroup to a post.
400 */
401 function ajax_save_post_subscriptions() {
402 global $edit_flow;
403
404 // Verify nonce.
405 if ( ! isset( $_POST['_nonce'] ) || ! wp_verify_nonce( $_POST['_nonce'], 'save_user_usergroups' ) ) {
406 die( __( 'Nonce check failed. Please ensure you can add users or user groups to a post.', 'edit-flow' ) );
407 }
408
409 $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
410 $post = get_post( $post_id );
411
412 $valid_post = ! is_null( $post ) && ! wp_is_post_revision( $post_id ) && ! wp_is_post_autosave( $post_id );
413 if ( ! isset( $_POST['ef_notifications_name'] ) || ! $valid_post || ! current_user_can( $this->edit_post_subscriptions_cap ) ) {
414 die();
415 }
416
417 $user_group_ids = array();
418 if ( isset( $_POST['user_group_ids'] ) && is_array( $_POST['user_group_ids'] ) ) {
419 $user_group_ids = array_map( 'intval', $_POST['user_group_ids'] );
420 }
421
422 if ( 'ef-selected-users[]' === $_POST['ef_notifications_name'] ) {
423 // Prevent auto-subscribing users that have opted out of notifications.
424 add_filter( 'ef_notification_auto_subscribe_current_user', '__return_false', PHP_INT_MAX );
425 $this->save_post_following_users( $post, $user_group_ids );
426
427 if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_POST['post_id'] ) ) {
428
429 // Determine if any of the selected users won't have notification access
430 $subscribers_with_no_access = array_filter( $user_group_ids, function( $user_id ) {
431 return ! $this->user_can_be_notified( get_user_by( 'id', $user_id ), $_POST['post_id'] );
432 } );
433
434 // Determine if any of the selected users are missing their emails
435 $subscribers_with_no_email = array();
436 foreach ( $user_group_ids AS $user_id ) {
437 $user_object = get_user_by( 'id', $user_id );
438 if ( !is_a( $user_object, 'WP_User') OR empty( $user_object->user_email ) ) {
439 $subscribers_with_no_email[] = $user_id;
440 }
441 }
442
443 // Assemble the json reply with various lists of problematic users
444 $json_success = array(
445 'subscribers_with_no_access' => array_values( $subscribers_with_no_access ),
446 'subscribers_with_no_email' => array_values( $subscribers_with_no_email ),
447 );
448
449 wp_send_json_success( $json_success );
450 }
451 // Remove auto-subscribe prevention behavior from earlier.
452 remove_filter( 'ef_notification_auto_subscribe_current_user', '__return_false', PHP_INT_MAX );
453 }
454
455 $groups_enabled = $this->module_enabled( 'user_groups' ) && in_array( get_post_type( $post_id ), $this->get_post_types_for_module( $edit_flow->user_groups->module ) );
456 if ( 'following_usergroups[]' === $_POST['ef_notifications_name'] && $groups_enabled ) {
457 $this->save_post_following_usergroups( $post, $user_group_ids );
458 }
459
460 die();
461 }
462
463 /**
464 * Handle a request to update a user's post subscription
465 *
466 * @since 0.8
467 */
468 public function handle_user_post_subscription() {
469
470 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'ef_notifications_user_post_subscription' ) )
471 $this->print_ajax_response( 'error', $this->module->messages['nonce-failed'] );
472
473 if ( ! current_user_can( $this->edit_post_subscriptions_cap ) )
474 $this->print_ajax_response( 'error', $this->module->messages['invalid-permissions'] );
475
476 $post = get_post( ( $post_id = $_GET['post_id'] ) );
477
478 if ( ! $post )
479 $this->print_ajax_response( 'error', $this->module->messages['missing-post'] );
480
481 if ( 'follow' == $_GET['method'] )
482 $retval = $this->follow_post_user( $post, get_current_user_id() );
483 else
484 $retval = $this->unfollow_post_user( $post, get_current_user_id() );
485
486 if ( is_wp_error( $retval ) )
487 $this->print_ajax_response( 'error', $retval->get_error_message() );
488
489 $this->print_ajax_response( 'success', (object)$this->get_follow_action_parts( $post ) );
490 }
491
492
493 /**
494 * Called when post is saved. Handles saving of user/usergroup followers
495 *
496 * @param int $post ID of the post
497 */
498 function save_post_subscriptions( $new_status, $old_status, $post ) {
499 global $edit_flow;
500 // only if has edit_post_subscriptions cap
501 if( ( !wp_is_post_revision($post) && !wp_is_post_autosave($post) ) && isset($_POST['ef-save_followers']) && current_user_can( $this->edit_post_subscriptions_cap ) ) {
502 $users = isset( $_POST['ef-selected-users'] ) ? $_POST['ef-selected-users'] : array();
503 $usergroups = isset( $_POST['following_usergroups'] ) ? $_POST['following_usergroups'] : array();
504 $this->save_post_following_users( $post, $users );
505 if ( $this->module_enabled( 'user_groups' ) && in_array( $this->get_current_post_type(), $this->get_post_types_for_module( $edit_flow->user_groups->module ) ) )
506 $this->save_post_following_usergroups( $post, $usergroups );
507 }
508
509 }
510
511 /**
512 * Sets users to follow specified post
513 *
514 * @param int $post ID of the post
515 */
516 function save_post_following_users( $post, $users = null ) {
517 if( !is_array( $users ) )
518 $users = array();
519
520 // Add current user to following users
521 $user = wp_get_current_user();
522 if ( $user && apply_filters( 'ef_notification_auto_subscribe_current_user', true, 'subscription_action' ) )
523 $users[] = $user->ID;
524
525 // Add post author to following users
526 if ( apply_filters( 'ef_notification_auto_subscribe_post_author', true, 'subscription_action' ) )
527 $users[] = $post->post_author;
528
529 $users = array_unique( array_map( 'intval', $users ) );
530
531 $follow = $this->follow_post_user( $post, $users, false );
532
533 }
534
535 /**
536 * Sets usergroups to follow specified post
537 *
538 * @param int $post ID of the post
539 * @param array $usergroups Usergroups to follow posts
540 */
541 function save_post_following_usergroups( $post, $usergroups = null ) {
542
543 if( !is_array($usergroups) ) $usergroups = array();
544 $usergroups = array_map( 'intval', $usergroups );
545
546 $follow = $this->follow_post_usergroups($post, $usergroups, false);
547 }
548
549 /**
550 * Set up and send post status change notification email
551 */
552 function notification_status_change( $new_status, $old_status, $post ) {
553 global $edit_flow;
554
555 // Kill switch for notification
556 if ( ! apply_filters( 'ef_notification_status_change', $new_status, $old_status, $post ) || ! apply_filters( "ef_notification_{$post->post_type}_status_change", $new_status, $old_status, $post ) )
557 return false;
558
559 $supported_post_types = $this->get_post_types_for_module( $this->module );
560 if ( !in_array( $post->post_type, $supported_post_types ) )
561 return;
562
563 // No need to notify if it's a revision, auto-draft, or if post status wasn't changed
564 $ignored_statuses = apply_filters( 'ef_notification_ignored_statuses', array( $old_status, 'inherit', 'auto-draft' ), $post->post_type );
565
566 if ( !in_array( $new_status, $ignored_statuses ) ) {
567
568 // Get current user
569 $current_user = wp_get_current_user();
570
571 $post_author = get_userdata( $post->post_author );
572 //$duedate = $edit_flow->post_metadata->get_post_meta($post->ID, 'duedate', true);
573
574 $blogname = get_option('blogname');
575
576 $body = '';
577
578 $post_id = $post->ID;
579 $post_title = ef_draft_or_post_title( $post_id );
580 $post_type = get_post_type_object( $post->post_type )->labels->singular_name;
581
582 if( 0 != $current_user->ID ) {
583 $current_user_display_name = $current_user->display_name;
584 $current_user_email = sprintf( '(%s)', $current_user->user_email );
585 } else {
586 $current_user_display_name = __( 'WordPress Scheduler', 'edit-flow' );
587 $current_user_email = '';
588 }
589
590 // Email subject and first line of body
591 // Set message subjects according to what action is being taken on the Post
592 if ( $old_status == 'new' || $old_status == 'auto-draft' ) {
593 $old_status_friendly_name = "New";
594 /* translators: 1: site name, 2: post type, 3. post title */
595 $subject = sprintf( __( '[%1$s] New %2$s Created: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
596 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
597 $body .= sprintf( __( 'A new %1$s (#%2$s "%3$s") was created by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user->display_name, $current_user->user_email ) . "\r\n";
598 } else if ( $new_status == 'trash' ) {
599 /* translators: 1: site name, 2: post type, 3. post title */
600 $subject = sprintf( __( '[%1$s] %2$s Trashed: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
601 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
602 $body .= sprintf( __( '%1$s #%2$s "%3$s" was moved to the trash by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
603 } else if ( $old_status == 'trash' ) {
604 /* translators: 1: site name, 2: post type, 3. post title */
605 $subject = sprintf( __( '[%1$s] %2$s Restored (from Trash): "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
606 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
607 $body .= sprintf( __( '%1$s #%2$s "%3$s" was restored from trash by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
608 } else if ( $new_status == 'future' ) {
609 /* translators: 1: site name, 2: post type, 3. post title */
610 $subject = sprintf( __('[%1$s] %2$s Scheduled: "%3$s"'), $blogname, $post_type, $post_title );
611 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email 6. scheduled date */
612 $body .= sprintf( __( '%1$s #%2$s "%3$s" was scheduled by %4$s %5$s. It will be published on %6$s' ), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email, $this->get_scheduled_datetime( $post ) ) . "\r\n";
613 } else if ( $new_status == 'publish' ) {
614 /* translators: 1: site name, 2: post type, 3. post title */
615 $subject = sprintf( __( '[%1$s] %2$s Published: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
616 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
617 $body .= sprintf( __( '%1$s #%2$s "%3$s" was published by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
618 } else if ( $old_status == 'publish' ) {
619 /* translators: 1: site name, 2: post type, 3. post title */
620 $subject = sprintf( __( '[%1$s] %2$s Unpublished: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
621 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
622 $body .= sprintf( __( '%1$s #%2$s "%3$s" was unpublished by %4$s %5$s', 'edit-flow' ), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
623 } else {
624 /* translators: 1: site name, 2: post type, 3. post title */
625 $subject = sprintf( __( '[%1$s] %2$s Status Changed for "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
626 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
627 $body .= sprintf( __( 'Status was changed for %1$s #%2$s "%3$s" by %4$s %5$s', 'edit-flow'), $post_type, $post_id, $post_title, $current_user_display_name, $current_user_email ) . "\r\n";
628 $old_status_post_obj = get_post_status_object( $old_status );
629 $old_status_friendly_name = $old_status_post_obj->label;
630 }
631
632 /* translators: 1: date, 2: time, 3: timezone */
633 $body .= sprintf( __( 'This action was taken on %1$s at %2$s %3$s', 'edit-flow' ), date_i18n( get_option( 'date_format' ) ), date_i18n( get_option( 'time_format' ) ), get_option( 'timezone_string' ) ) . "\r\n";
634
635 $new_status_post_obj = get_post_status_object( $new_status );
636 $new_status_friendly_name = $new_status_post_obj->label;
637
638 // Email body
639 $body .= "\r\n";
640 /* translators: 1: old status, 2: new status */
641 $body .= sprintf( __( '%1$s => %2$s', 'edit-flow' ), $old_status_friendly_name, $new_status_friendly_name );
642 $body .= "\r\n\r\n";
643
644 $body .= "--------------------\r\n\r\n";
645
646 $body .= sprintf( __( '== %s Details ==', 'edit-flow' ), $post_type ) . "\r\n";
647 $body .= sprintf( __( 'Title: %s', 'edit-flow' ), $post_title ) . "\r\n";
648 if ( ! empty( $post_author ) ) {
649 /* translators: 1: author name, 2: author email */
650 $body .= sprintf( __( 'Author: %1$s (%2$s)', 'edit-flow' ), $post_author->display_name, $post_author->user_email ) . "\r\n";
651 }
652
653 $edit_link = htmlspecialchars_decode( get_edit_post_link( $post_id ) );
654 if ( $new_status != 'publish' ) {
655 $view_link = add_query_arg( array( 'preview' => 'true' ), wp_get_shortlink( $post_id ) );
656 } else {
657 $view_link = htmlspecialchars_decode( get_permalink( $post_id ) );
658 }
659 $body .= "\r\n";
660 $body .= __( '== Actions ==', 'edit-flow' ) . "\r\n";
661 $body .= sprintf( __( 'Add editorial comment: %s', 'edit-flow' ), $edit_link . '#editorialcomments/add' ) . "\r\n";
662 $body .= sprintf( __( 'Edit: %s', 'edit-flow' ), $edit_link ) . "\r\n";
663 $body .= sprintf( __( 'View: %s', 'edit-flow' ), $view_link ) . "\r\n";
664
665 $body .= $this->get_notification_footer($post);
666
667 $this->send_email( 'status-change', $post, $subject, $body );
668 }
669
670 }
671
672 /**
673 * Set up and set editorial comment notification email
674 *
675 * @param WP_Comment $comment
676 * @return boolean|null|void
677 */
678 function notification_comment( $comment ) {
679
680 $post = get_post($comment->comment_post_ID);
681
682 $supported_post_types = $this->get_post_types_for_module( $this->module );
683 if ( !in_array( $post->post_type, $supported_post_types ) )
684 return;
685
686 // Kill switch for notification
687 if ( ! apply_filters( 'ef_notification_editorial_comment', $comment, $post ) )
688 return false;
689
690 $user = get_userdata( $post->post_author );
691 $current_user = wp_get_current_user();
692
693 $post_id = $post->ID;
694 $post_type = get_post_type_object( $post->post_type )->labels->singular_name;
695 $post_title = ef_draft_or_post_title( $post_id );
696
697 // Fetch the text list of people who were notified from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
698 $notification_list = get_comment_meta( $comment->comment_ID, 'notification_list', true );
699
700 // Check if this a reply
701 //$parent_ID = isset( $comment->comment_parent_ID ) ? $comment->comment_parent_ID : 0;
702 //if($parent_ID) $parent = get_comment($parent_ID);
703
704 // Set user to follow post, but make it filterable
705 if ( apply_filters( 'ef_notification_auto_subscribe_current_user', true, 'comment' ) )
706 $this->follow_post_user($post, (int) $current_user->ID);
707
708 // Set the post author to follow the post but make it filterable
709 if ( apply_filters( 'ef_notification_auto_subscribe_post_author', true, 'comment' ) )
710 $this->follow_post_user( $post, (int) $post->post_author );
711
712 $blogname = get_option('blogname');
713
714 /* translators: 1: blog name, 2: post title */
715 $subject = sprintf( __( '[%1$s] New Editorial Comment: "%2$s"', 'edit-flow' ), $blogname, $post_title );
716
717 /* translators: 1: post id, 2: post title, 3. post type */
718 $body = sprintf( __( 'A new editorial comment was added to %3$s #%1$s "%2$s"', 'edit-flow' ), $post_id, $post_title, $post_type ) . "\r\n\r\n";
719 /* translators: 1: comment author, 2: author email, 3: date, 4: time */
720 $body .= sprintf( __( '%1$s (%2$s) said on %3$s at %4$s:', 'edit-flow' ), $current_user->display_name, $current_user->user_email, mysql2date(get_option('date_format'), $comment->comment_date), mysql2date(get_option('time_format'), $comment->comment_date) ) . "\r\n";
721 $body .= "\r\n" . $comment->comment_content . "\r\n";
722
723 // @TODO: mention if it was a reply
724 /*
725 if($parent) {
726
727 }
728 */
729
730
731 $body .= "\r\n--------------------\r\n";
732 // Insert the notification list from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
733 if ($notification_list) {
734 $body .= esc_html__( 'Notified', 'edit-flow' ) . ": " . esc_html( $notification_list ) . "\n";
735 }
736
737 $edit_link = htmlspecialchars_decode( get_edit_post_link( $post_id ) );
738 $view_link = htmlspecialchars_decode( get_permalink( $post_id ) );
739
740 $body .= "\r\n";
741 $body .= __( '== Actions ==', 'edit-flow' ) . "\r\n";
742 $body .= sprintf( __( 'Reply: %s', 'edit-flow' ), $edit_link . '#editorialcomments/reply/' . $comment->comment_ID ) . "\r\n";
743 $body .= sprintf( __( 'Add editorial comment: %s', 'edit-flow' ), $edit_link . '#editorialcomments/add' ) . "\r\n";
744 $body .= sprintf( __( 'Edit: %s', 'edit-flow' ), $edit_link ) . "\r\n";
745 $body .= sprintf( __( 'View: %s', 'edit-flow' ), $view_link ) . "\r\n";
746
747 $body .= "\r\n" . sprintf( __( 'You can see all editorial comments on this %s here: ', 'edit-flow' ), $post_type ). "\r\n";
748 $body .= $edit_link . "#editorialcomments" . "\r\n\r\n";
749
750 $body .= $this->get_notification_footer($post);
751
752 $this->send_email( 'comment', $post, $subject, $body );
753 }
754
755 function get_notification_footer( $post ) {
756 $body = "";
757 $body .= "\r\n--------------------\r\n";
758 $body .= sprintf( __( 'You are receiving this email because you are subscribed to "%s".', 'edit-flow' ), ef_draft_or_post_title ($post->ID ) );
759 $body .= "\r\n";
760 $body .= sprintf( __( 'This email was sent %s.', 'edit-flow' ), date( 'r' ) );
761 $body .= "\r\n \r\n";
762 $body .= get_option('blogname') ." | ". get_bloginfo('url') . " | " . admin_url('/') . "\r\n";
763 return $body;
764 }
765
766 /**
767 * send_email()
768 */
769 function send_email( $action, $post, $subject, $message, $message_headers = '' ) {
770
771 // Get list of email recipients -- set them CC
772 $recipients = $this->_get_notification_recipients( $post, true );
773
774 if( $recipients && ! is_array( $recipients ) )
775 $recipients = explode( ',', $recipients );
776
777 $subject = apply_filters( 'ef_notification_send_email_subject', $subject, $action, $post );
778 $message = apply_filters( 'ef_notification_send_email_message', $message, $action, $post );
779 $message_headers = apply_filters( 'ef_notification_send_email_message_headers', $message_headers, $action, $post );
780
781 if( EF_NOTIFICATION_USE_CRON ) {
782 $this->schedule_emails( $recipients, $subject, $message, $message_headers );
783 } else if ( !empty( $recipients ) ) {
784 foreach( $recipients as $recipient ) {
785 $this->send_single_email( $recipient, $subject, $message, $message_headers );
786 }
787 }
788 }
789
790 /**
791 * Schedules emails to be sent in succession
792 *
793 * @param mixed $recipients Individual email or array of emails
794 * @param string $subject Subject of the email
795 * @param string $message Body of the email
796 * @param string $message_headers. (optional) Message headers
797 * @param int $time_offset (optional) Delay in seconds per email
798 */
799 function schedule_emails( $recipients, $subject, $message, $message_headers = '', $time_offset = 1 ) {
800 $recipients = (array) $recipients;
801
802 $send_time = time();
803
804 foreach( $recipients as $recipient ) {
805 wp_schedule_single_event( $send_time, 'ef_send_scheduled_email', array( $recipient, $subject, $message, $message_headers ) );
806 $send_time += $time_offset;
807 }
808
809 }
810
811 /**
812 * Sends an individual email
813 *
814 * @param mixed $to Email to send to
815 * @param string $subject Subject of the email
816 * @param string $message Body of the email
817 * @param string $message_headers. (optional) Message headers
818 */
819 function send_single_email( $to, $subject, $message, $message_headers = '' ) {
820 wp_mail( $to, $subject, $message, $message_headers );
821 }
822
823 /**
824 * Returns a list of recipients for a given post.
825 *
826 * @param WP_Post $post
827 * @param bool $string Whether to return recipients as comma-delimited string or array.
828 * @return string|array Recipients to receive notification.
829 */
830 private function _get_notification_recipients( $post, $string = false ) {
831 global $edit_flow;
832
833 $post_id = $post->ID;
834 if ( ! $post_id ) {
835 return $string ? '' : array();
836 }
837
838 // Email all admins if enabled.
839 $admins = array();
840 if ( 'on' === $this->module->options->always_notify_admin ) {
841 $admins[] = get_option('admin_email');
842 }
843
844 $usergroup_recipients = array();
845 if ( $this->module_enabled( 'user_groups' ) ) {
846 $usergroups = $this->get_following_usergroups( $post_id, 'ids' );
847 foreach ( (array) $usergroups as $usergroup_id ) {
848 $usergroup = $edit_flow->user_groups->get_usergroup_by( 'id', $usergroup_id );
849 foreach ( (array) $usergroup->user_ids as $user_id ) {
850 $usergroup_user = get_user_by( 'id', $user_id );
851 if ( $this->user_can_be_notified( $usergroup_user, $post_id ) ) {
852 $usergroup_recipients[] = $usergroup_user->user_email;
853 }
854 }
855 }
856 }
857
858 $user_recipients = $this->get_following_users( $post_id, 'user_email' );
859 foreach( $user_recipients as $key => $user ) {
860 $user_object = get_user_by( 'email', $user );
861 if ( ! $this->user_can_be_notified( $user_object, $post_id ) ) {
862 unset( $user_recipients[ $key ] );
863 }
864 }
865
866 // Merge arrays, filter any duplicates, and remove empty entries.
867 $recipients = array_filter( array_unique( array_merge( $admins, $user_recipients, $usergroup_recipients ) ) );
868
869 // Process the recipients for this email to be sent.
870 foreach( $recipients as $key => $user_email ) {
871 // Don't send the email to the current user unless we've explicitly indicated they should receive it.
872 if ( false === apply_filters( 'ef_notification_email_current_user', false ) && wp_get_current_user()->user_email == $user_email ) {
873 unset( $recipients[ $key ] );
874 }
875 }
876
877 /**
878 * Filters the list of notification recipients.
879 *
880 * @param array $recipients List of recipient email addresses.
881 * @param WP_Post $post
882 * @param bool $string True if the recipients list will later be returned as a string.
883 */
884 $recipients = apply_filters( 'ef_notification_recipients', $recipients, $post, $string );
885
886 // If string set to true, return comma-delimited.
887 if ( $string && is_array( $recipients ) ) {
888 return implode( ',', $recipients );
889 } else {
890 return $recipients;
891 }
892 }
893
894 /**
895 * Check if a user can be notified.
896 * This is based off of the ability to edit the post/page by default.
897 *
898 * @since 0.8.3
899 * @param WP_User $user
900 * @param int $post_id
901 * @return bool True if the user can be notified, false otherwise.
902 */
903 function user_can_be_notified( $user, $post_id ) {
904 $can_be_notified = false;
905
906 if ( $user instanceof WP_User && is_user_member_of_blog( $user->ID ) && is_numeric( $post_id ) ) {
907 // The 'edit_post' cap check also covers the undocumented 'edit_page' cap.
908 $can_be_notified = $user->has_cap( 'edit_post', $post_id );
909 }
910
911 /**
912 * Filters if a user can be notified. Defaults to true if they can edit the post/page.
913 *
914 * @param bool $can_be_notified True if the user can be notified.
915 * @param WP_User|bool $user The user object, otherwise false.
916 * @param int $post_id The post the user will be notified about.
917 */
918 return (bool) apply_filters( 'ef_notification_user_can_be_notified', $can_be_notified, $user, $post_id );
919 }
920
921 /**
922 * Set a user or users to follow a post
923 *
924 * @param int|object $post Post object or ID
925 * @param string|array $users User or users to subscribe to post updates
926 * @param bool $append Whether users should be added to following_users list or replace existing list
927 *
928 * @return true|WP_Error $response True on success, WP_Error on failure
929 */
930 function follow_post_user( $post, $users, $append = true ) {
931
932 $post = get_post( $post );
933 if ( ! $post )
934 return new WP_Error( 'missing-post', $this->module->messages['missing-post'] );
935
936 if ( ! is_array( $users ) )
937 $users = array( $users );
938
939 $user_terms = array();
940 foreach( $users as $user ) {
941
942 if ( is_int( $user ) )
943 $user = get_user_by( 'id', $user );
944 elseif ( is_string( $user ) )
945 $user = get_user_by( 'login', $user );
946
947 if ( ! is_object( $user ) )
948 continue;
949
950 $name = $user->user_login;
951
952 // Add user as a term if they don't exist
953 $term = $this->add_term_if_not_exists( $name, $this->following_users_taxonomy );
954
955 if ( ! is_wp_error( $term ) ) {
956 $user_terms[] = $name;
957 }
958 }
959 $set = wp_set_object_terms( $post->ID, $user_terms, $this->following_users_taxonomy, $append );
960
961 if ( is_wp_error( $set ) )
962 return $set;
963 else
964 return true;
965 }
966
967 /**
968 * Removes user from following_users taxonomy for the given Post,
969 * so they no longer receive future notifications.
970 *
971 * @param object $post Post object or ID
972 * @param int|string|array $users One or more users to unfollow from the post
973 * @return true|WP_Error $response True on success, WP_Error on failure
974 */
975 function unfollow_post_user( $post, $users ) {
976
977 $post = get_post( $post );
978 if ( ! $post )
979 return new WP_Error( 'missing-post', $this->module->messages['missing-post'] );
980
981 if ( ! is_array( $users ) )
982 $users = array( $users );
983
984 $terms = get_the_terms( $post->ID, $this->following_users_taxonomy );
985 if ( is_wp_error( $terms ) )
986 return $terms;
987
988 $user_terms = wp_list_pluck( $terms, 'slug' );
989 foreach( $users as $user ) {
990
991 if ( is_int( $user ) )
992 $user = get_user_by( 'id', $user );
993 elseif ( is_string( $user ) )
994 $user = get_user_by( 'login', $user );
995
996 if ( ! is_object( $user ) )
997 continue;
998
999 $key = array_search( $user->user_login, $user_terms );
1000 if ( false !== $key )
1001 unset( $user_terms[$key] );
1002 }
1003 $set = wp_set_object_terms( $post->ID, $user_terms, $this->following_users_taxonomy, false );
1004
1005 if ( is_wp_error( $set ) )
1006 return $set;
1007 else
1008 return true;
1009 }
1010
1011 /**
1012 * follow_post_usergroups()
1013 *
1014 */
1015 function follow_post_usergroups( $post, $usergroups = 0, $append = true ) {
1016 if ( !$this->module_enabled( 'user_groups' ) )
1017 return;
1018
1019 $post_id = ( is_int($post) ) ? $post : $post->ID;
1020 if( !is_array($usergroups) )
1021 $usergroups = array($usergroups);
1022
1023 // make sure each usergroup id is an integer and not a number stored as a string
1024 foreach( $usergroups as $key => $usergroup ) {
1025 $usergroups[$key] = intval($usergroup);
1026 }
1027
1028 wp_set_object_terms( $post_id, $usergroups, $this->following_usergroups_taxonomy, $append );
1029 return;
1030 }
1031
1032 /**
1033 * Removes users that are deleted from receiving future notifications (i.e. makes them unfollow posts FOREVER!)
1034 *
1035 * @param $id int ID of the user
1036 */
1037 function delete_user_action( $id ) {
1038 if( !$id ) return;
1039
1040 // get user data
1041 $user = get_userdata($id);
1042
1043 if( $user ) {
1044 // Delete term from the following_users taxonomy
1045 $user_following_term = get_term_by('name', $user->user_login, $this->following_users_taxonomy);
1046 if( $user_following_term ) wp_delete_term($user_following_term->term_id, $this->following_users_taxonomy);
1047 }
1048 return;
1049 }
1050
1051 /**
1052 * Add user as a term if they aren't already
1053 * @param $term string term to be added
1054 * @param $taxonomy string taxonomy to add term to
1055 * @return WP_error if insert fails, true otherwise
1056 */
1057 function add_term_if_not_exists( $term, $taxonomy ) {
1058 if ( !term_exists($term, $taxonomy) ) {
1059 $args = array( 'slug' => sanitize_title($term) );
1060 return wp_insert_term( $term, $taxonomy, $args );
1061 }
1062 return true;
1063 }
1064
1065 /**
1066 * Gets a list of the users following the specified post
1067 *
1068 * @param int $post_id The ID of the post
1069 * @param string $return The field to return
1070 * @return array $users Users following the specified posts
1071 */
1072 function get_following_users( $post_id, $return = 'user_login' ) {
1073
1074 // Get following_users terms for the post
1075 $users = wp_get_object_terms( $post_id, $this->following_users_taxonomy, array('fields' => 'names') );
1076
1077 // Don't have any following users
1078 if( !$users || is_wp_error($users) )
1079 return array();
1080
1081 // if just want user_login, return as is
1082 if ( $return == 'user_login' )
1083 return $users;
1084
1085 foreach( (array)$users as $key => $user ) {
1086 switch( $user ) {
1087 case is_int( $user ):
1088 $search = 'id';
1089 break;
1090 case is_email( $user ):
1091 $search = 'email';
1092 break;
1093 default:
1094 $search = 'login';
1095 break;
1096 }
1097 $new_user = get_user_by( $search, $user );
1098 if ( ! $new_user || ! is_user_member_of_blog( $new_user->ID ) ) {
1099 unset( $users[ $key ] );
1100 continue;
1101 }
1102 switch( $return ) {
1103 case 'user_login':
1104 $users[$key] = $new_user->user_login;
1105 break;
1106 case 'id':
1107 $users[$key] = $new_user->ID;
1108 break;
1109 case 'user_email':
1110 $users[$key] = $new_user->user_email;
1111 break;
1112 }
1113 }
1114 if( !$users || is_wp_error($users) )
1115 $users = array();
1116 return $users;
1117
1118 }
1119
1120 /**
1121 * Gets a list of the usergroups that are following specified post
1122 *
1123 * @param int $post_id
1124 * @return array $usergroups All of the usergroup slugs
1125 */
1126 function get_following_usergroups( $post_id, $return = 'all' ) {
1127 global $edit_flow;
1128
1129 // Workaround for the fact that get_object_terms doesn't return just slugs
1130 if( $return == 'slugs' )
1131 $fields = 'all';
1132 else
1133 $fields = $return;
1134
1135 $usergroups = wp_get_object_terms( $post_id, $this->following_usergroups_taxonomy, array( 'fields' => $fields ) );
1136
1137 if( $return == 'slugs' ) {
1138 $slugs = array();
1139 foreach($usergroups as $usergroup) {
1140 $slugs[] = $usergroup->slug;
1141 }
1142 $usergroups = $slugs;
1143 }
1144 return $usergroups;
1145 }
1146
1147 /**
1148 * Gets a list of posts that a user is following
1149 *
1150 * @param string|int $user user_login or id of user
1151 * @param array $args
1152 * @return array $posts Posts a user is following
1153 */
1154 function get_user_following_posts( $user = 0, $args = null ) {
1155 if ( !$user )
1156 $user = (int) wp_get_current_user()->ID;
1157
1158 if ( is_int($user) )
1159 $user = get_userdata($user)->user_login;
1160
1161 $post_args = array(
1162 'tax_query' => array(
1163 array(
1164 'taxonomy' => $this->following_users_taxonomy,
1165 'field' => 'slug',
1166 'terms' => $user,
1167 )
1168 ),
1169 'posts_per_page' => '10',
1170 'orderby' => 'modified',
1171 'order' => 'DESC',
1172 'post_status' => 'any',
1173 );
1174 $post_args = apply_filters( 'ef_user_following_posts_query_args', $post_args );
1175 $posts = get_posts( $post_args );
1176 return $posts;
1177
1178 }
1179
1180 /**
1181 * Register settings for notifications so we can partially use the Settings API
1182 * (We use the Settings API for form generation, but not saving)
1183 *
1184 * @since 0.7
1185 */
1186 function register_settings() {
1187 add_settings_section( $this->module->options_group_name . '_general', false, '__return_false', $this->module->options_group_name );
1188 add_settings_field( 'post_types', __( 'Post types for notifications:', 'edit-flow' ), array( $this, 'settings_post_types_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' );
1189 add_settings_field( 'always_notify_admin', __( 'Always notify blog admin', 'edit-flow' ), array( $this, 'settings_always_notify_admin_option'), $this->module->options_group_name, $this->module->options_group_name . '_general' );
1190 }
1191
1192 /**
1193 * Chose the post types for notifications
1194 *
1195 * @since 0.7
1196 */
1197 function settings_post_types_option() {
1198 global $edit_flow;
1199 $edit_flow->settings->helper_option_custom_post_type( $this->module );
1200 }
1201
1202 /**
1203 * Option for whether the blog admin email address should be always notified or not
1204 *
1205 * @since 0.7
1206 */
1207 function settings_always_notify_admin_option() {
1208 $options = array(
1209 'off' => __( 'Disabled', 'edit-flow' ),
1210 'on' => __( 'Enabled', 'edit-flow' ),
1211 );
1212 echo '<select id="always_notify_admin" name="' . $this->module->options_group_name . '[always_notify_admin]">';
1213 foreach ( $options as $value => $label ) {
1214 echo '<option value="' . esc_attr( $value ) . '"';
1215 echo selected( $this->module->options->always_notify_admin, $value );
1216 echo '>' . esc_html( $label ) . '</option>';
1217 }
1218 echo '</select>';
1219 }
1220
1221 /**
1222 * Validate our user input as the settings are being saved
1223 *
1224 * @since 0.7
1225 */
1226 function settings_validate( $new_options ) {
1227
1228 // Whitelist validation for the post type options
1229 if ( !isset( $new_options['post_types'] ) )
1230 $new_options['post_types'] = array();
1231 $new_options['post_types'] = $this->clean_post_type_options( $new_options['post_types'], $this->module->post_type_support );
1232
1233 // Whitelist validation for the 'always_notify_admin' options
1234 if ( !isset( $new_options['always_notify_admin'] ) || $new_options['always_notify_admin'] != 'on' )
1235 $new_options['always_notify_admin'] = 'off';
1236
1237 return $new_options;
1238
1239 }
1240
1241 /**
1242 * Settings page for notifications
1243 *
1244 * @since 0.7
1245 */
1246 function print_configure_view() {
1247 ?>
1248 <form class="basic-settings" action="<?php echo esc_url( menu_page_url( $this->module->settings_slug, false ) ); ?>" method="post">
1249 <?php settings_fields( $this->module->options_group_name ); ?>
1250 <?php do_settings_sections( $this->module->options_group_name ); ?>
1251 <?php
1252 echo '<input id="edit_flow_module_name" name="edit_flow_module_name" type="hidden" value="' . esc_attr( $this->module->name ) . '" />';
1253 ?>
1254 <p class="submit"><?php submit_button( null, 'primary', 'submit', false ); ?><a class="cancel-settings-link" href="<?php echo EDIT_FLOW_SETTINGS_PAGE; ?>"><?php _e( 'Back to Edit Flow', 'edit-flow' ); ?></a></p>
1255 </form>
1256 <?php
1257 }
1258
1259 /**
1260 * Gets a simple phrase containing the formatted date and time that the post is scheduled for.
1261 *
1262 * @since 0.8
1263 *
1264 * @param obj $post Post object
1265 * @return str $scheduled_datetime The scheduled datetime in human-readable format
1266 */
1267 private function get_scheduled_datetime( $post ) {
1268
1269 $scheduled_ts = strtotime( $post->post_date );
1270
1271 $date = date_i18n( get_option( 'date_format' ), $scheduled_ts );
1272 $time = date_i18n( get_option( 'time_format' ), $scheduled_ts );
1273
1274 return sprintf( __( '%1$s at %2$s', 'edit-flow' ), $date, $time );
1275 }
1276 }
1277
1278 }
1279