PluginProbe
Edit Flow / 0.9.3
Edit Flow v0.9.3
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.3, at modules/notifications/notifications.php

1,296 lines 47.7 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 $old_status_post_obj = get_post_status_object( $old_status );
591 $new_status_post_obj = get_post_status_object( $new_status );
592 $old_status_friendly_name = '';
593 $new_status_friendly_name = '';
594
595 /**
596 * get_post_status_object will return null for certain statuses (i.e., 'new')
597 * The mega if/else block below should catch all cases, but just in case, we
598 * make sure to at least set $old_status_friendly_name and $new_status_friendly_name
599 * to an empty string to ensure they're at least set.
600 *
601 * Then, we attempt to set them to a sensible default before we start the
602 * mega if/else block
603 */
604 if ( ! is_null( $old_status_post_obj ) ) {
605 $old_status_friendly_name = $old_status_post_obj->label;
606 }
607
608 if ( ! is_null( $new_status_post_obj ) ) {
609 $new_status_friendly_name = $new_status_post_obj->label;
610 }
611
612 // Email subject and first line of body
613 // Set message subjects according to what action is being taken on the Post
614 if ( $old_status == 'new' || $old_status == 'auto-draft' ) {
615 $old_status_friendly_name = "New";
616 /* translators: 1: site name, 2: post type, 3. post title */
617 $subject = sprintf( __( '[%1$s] New %2$s Created: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
618 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
619 $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";
620 } else if ( $new_status == 'trash' ) {
621 /* translators: 1: site name, 2: post type, 3. post title */
622 $subject = sprintf( __( '[%1$s] %2$s Trashed: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
623 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
624 $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";
625 } else if ( $old_status == 'trash' ) {
626 /* translators: 1: site name, 2: post type, 3. post title */
627 $subject = sprintf( __( '[%1$s] %2$s Restored (from Trash): "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
628 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
629 $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";
630 } else if ( $new_status == 'future' ) {
631 /* translators: 1: site name, 2: post type, 3. post title */
632 $subject = sprintf( __('[%1$s] %2$s Scheduled: "%3$s"'), $blogname, $post_type, $post_title );
633 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email 6. scheduled date */
634 $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";
635 } else if ( $new_status == 'publish' ) {
636 /* translators: 1: site name, 2: post type, 3. post title */
637 $subject = sprintf( __( '[%1$s] %2$s Published: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
638 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
639 $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";
640 } else if ( $old_status == 'publish' ) {
641 /* translators: 1: site name, 2: post type, 3. post title */
642 $subject = sprintf( __( '[%1$s] %2$s Unpublished: "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
643 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
644 $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";
645 } else {
646 /* translators: 1: site name, 2: post type, 3. post title */
647 $subject = sprintf( __( '[%1$s] %2$s Status Changed for "%3$s"', 'edit-flow' ), $blogname, $post_type, $post_title );
648 /* translators: 1: post type, 2: post id, 3. post title, 4. user name, 5. user email */
649 $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";
650 }
651
652 /* translators: 1: date, 2: time, 3: timezone */
653 $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";
654
655 // Email body
656 $body .= "\r\n";
657 /* translators: 1: old status, 2: new status */
658 $body .= sprintf( __( '%1$s => %2$s', 'edit-flow' ), $old_status_friendly_name, $new_status_friendly_name );
659 $body .= "\r\n\r\n";
660
661 $body .= "--------------------\r\n\r\n";
662
663 $body .= sprintf( __( '== %s Details ==', 'edit-flow' ), $post_type ) . "\r\n";
664 $body .= sprintf( __( 'Title: %s', 'edit-flow' ), $post_title ) . "\r\n";
665 if ( ! empty( $post_author ) ) {
666 /* translators: 1: author name, 2: author email */
667 $body .= sprintf( __( 'Author: %1$s (%2$s)', 'edit-flow' ), $post_author->display_name, $post_author->user_email ) . "\r\n";
668 }
669
670 $edit_link = htmlspecialchars_decode( get_edit_post_link( $post_id ) );
671 if ( $new_status != 'publish' ) {
672 $view_link = add_query_arg( array( 'preview' => 'true' ), wp_get_shortlink( $post_id ) );
673 } else {
674 $view_link = htmlspecialchars_decode( get_permalink( $post_id ) );
675 }
676 $body .= "\r\n";
677 $body .= __( '== Actions ==', 'edit-flow' ) . "\r\n";
678 $body .= sprintf( __( 'Add editorial comment: %s', 'edit-flow' ), $edit_link . '#editorialcomments/add' ) . "\r\n";
679 $body .= sprintf( __( 'Edit: %s', 'edit-flow' ), $edit_link ) . "\r\n";
680 $body .= sprintf( __( 'View: %s', 'edit-flow' ), $view_link ) . "\r\n";
681
682 $body .= $this->get_notification_footer($post);
683
684 $this->send_email( 'status-change', $post, $subject, $body );
685 }
686
687 }
688
689 /**
690 * Set up and set editorial comment notification email
691 *
692 * @param WP_Comment $comment
693 * @return boolean|null|void
694 */
695 function notification_comment( $comment ) {
696
697 $post = get_post($comment->comment_post_ID);
698
699 $supported_post_types = $this->get_post_types_for_module( $this->module );
700 if ( !in_array( $post->post_type, $supported_post_types ) )
701 return;
702
703 // Kill switch for notification
704 if ( ! apply_filters( 'ef_notification_editorial_comment', $comment, $post ) )
705 return false;
706
707 $user = get_userdata( $post->post_author );
708 $current_user = wp_get_current_user();
709
710 $post_id = $post->ID;
711 $post_type = get_post_type_object( $post->post_type )->labels->singular_name;
712 $post_title = ef_draft_or_post_title( $post_id );
713
714 // Fetch the text list of people who were notified from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
715 $notification_list = get_comment_meta( $comment->comment_ID, 'notification_list', true );
716
717 // Check if this a reply
718 //$parent_ID = isset( $comment->comment_parent_ID ) ? $comment->comment_parent_ID : 0;
719 //if($parent_ID) $parent = get_comment($parent_ID);
720
721 // Set user to follow post, but make it filterable
722 if ( apply_filters( 'ef_notification_auto_subscribe_current_user', true, 'comment' ) )
723 $this->follow_post_user($post, (int) $current_user->ID);
724
725 // Set the post author to follow the post but make it filterable
726 if ( apply_filters( 'ef_notification_auto_subscribe_post_author', true, 'comment' ) )
727 $this->follow_post_user( $post, (int) $post->post_author );
728
729 $blogname = get_option('blogname');
730
731 /* translators: 1: blog name, 2: post title */
732 $subject = sprintf( __( '[%1$s] New Editorial Comment: "%2$s"', 'edit-flow' ), $blogname, $post_title );
733
734 /* translators: 1: post id, 2: post title, 3. post type */
735 $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";
736 /* translators: 1: comment author, 2: author email, 3: date, 4: time */
737 $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";
738 $body .= "\r\n" . $comment->comment_content . "\r\n";
739
740 // @TODO: mention if it was a reply
741 /*
742 if($parent) {
743
744 }
745 */
746
747
748 $body .= "\r\n--------------------\r\n";
749 // Insert the notification list from comment meta @see EF_Editorial_Comments->maybe_output_comment_meta()
750 if ($notification_list) {
751 $body .= esc_html__( 'Notified', 'edit-flow' ) . ": " . esc_html( $notification_list ) . "\n";
752 }
753
754 $edit_link = htmlspecialchars_decode( get_edit_post_link( $post_id ) );
755 $view_link = htmlspecialchars_decode( get_permalink( $post_id ) );
756
757 $body .= "\r\n";
758 $body .= __( '== Actions ==', 'edit-flow' ) . "\r\n";
759 $body .= sprintf( __( 'Reply: %s', 'edit-flow' ), $edit_link . '#editorialcomments/reply/' . $comment->comment_ID ) . "\r\n";
760 $body .= sprintf( __( 'Add editorial comment: %s', 'edit-flow' ), $edit_link . '#editorialcomments/add' ) . "\r\n";
761 $body .= sprintf( __( 'Edit: %s', 'edit-flow' ), $edit_link ) . "\r\n";
762 $body .= sprintf( __( 'View: %s', 'edit-flow' ), $view_link ) . "\r\n";
763
764 $body .= "\r\n" . sprintf( __( 'You can see all editorial comments on this %s here: ', 'edit-flow' ), $post_type ). "\r\n";
765 $body .= $edit_link . "#editorialcomments" . "\r\n\r\n";
766
767 $body .= $this->get_notification_footer($post);
768
769 $this->send_email( 'comment', $post, $subject, $body );
770 }
771
772 function get_notification_footer( $post ) {
773 $body = "";
774 $body .= "\r\n--------------------\r\n";
775 $body .= sprintf( __( 'You are receiving this email because you are subscribed to "%s".', 'edit-flow' ), ef_draft_or_post_title ($post->ID ) );
776 $body .= "\r\n";
777 $body .= sprintf( __( 'This email was sent %s.', 'edit-flow' ), date( 'r' ) );
778 $body .= "\r\n \r\n";
779 $body .= get_option('blogname') ." | ". get_bloginfo('url') . " | " . admin_url('/') . "\r\n";
780 return $body;
781 }
782
783 /**
784 * send_email()
785 */
786 function send_email( $action, $post, $subject, $message, $message_headers = '' ) {
787
788 // Get list of email recipients -- set them CC
789 $recipients = $this->_get_notification_recipients( $post, true );
790
791 if( $recipients && ! is_array( $recipients ) )
792 $recipients = explode( ',', $recipients );
793
794 $subject = apply_filters( 'ef_notification_send_email_subject', $subject, $action, $post );
795 $message = apply_filters( 'ef_notification_send_email_message', $message, $action, $post );
796 $message_headers = apply_filters( 'ef_notification_send_email_message_headers', $message_headers, $action, $post );
797
798 if( EF_NOTIFICATION_USE_CRON ) {
799 $this->schedule_emails( $recipients, $subject, $message, $message_headers );
800 } else if ( !empty( $recipients ) ) {
801 foreach( $recipients as $recipient ) {
802 $this->send_single_email( $recipient, $subject, $message, $message_headers );
803 }
804 }
805 }
806
807 /**
808 * Schedules emails to be sent in succession
809 *
810 * @param mixed $recipients Individual email or array of emails
811 * @param string $subject Subject of the email
812 * @param string $message Body of the email
813 * @param string $message_headers. (optional) Message headers
814 * @param int $time_offset (optional) Delay in seconds per email
815 */
816 function schedule_emails( $recipients, $subject, $message, $message_headers = '', $time_offset = 1 ) {
817 $recipients = (array) $recipients;
818
819 $send_time = time();
820
821 foreach( $recipients as $recipient ) {
822 wp_schedule_single_event( $send_time, 'ef_send_scheduled_email', array( $recipient, $subject, $message, $message_headers ) );
823 $send_time += $time_offset;
824 }
825
826 }
827
828 /**
829 * Sends an individual email
830 *
831 * @param mixed $to Email to send to
832 * @param string $subject Subject of the email
833 * @param string $message Body of the email
834 * @param string $message_headers. (optional) Message headers
835 */
836 function send_single_email( $to, $subject, $message, $message_headers = '' ) {
837 wp_mail( $to, $subject, $message, $message_headers );
838 }
839
840 /**
841 * Returns a list of recipients for a given post.
842 *
843 * @param WP_Post $post
844 * @param bool $string Whether to return recipients as comma-delimited string or array.
845 * @return string|array Recipients to receive notification.
846 */
847 private function _get_notification_recipients( $post, $string = false ) {
848 global $edit_flow;
849
850 $post_id = $post->ID;
851 if ( ! $post_id ) {
852 return $string ? '' : array();
853 }
854
855 // Email all admins if enabled.
856 $admins = array();
857 if ( 'on' === $this->module->options->always_notify_admin ) {
858 $admins[] = get_option('admin_email');
859 }
860
861 $usergroup_recipients = array();
862 if ( $this->module_enabled( 'user_groups' ) ) {
863 $usergroups = $this->get_following_usergroups( $post_id, 'ids' );
864 foreach ( (array) $usergroups as $usergroup_id ) {
865 $usergroup = $edit_flow->user_groups->get_usergroup_by( 'id', $usergroup_id );
866 foreach ( (array) $usergroup->user_ids as $user_id ) {
867 $usergroup_user = get_user_by( 'id', $user_id );
868 if ( $this->user_can_be_notified( $usergroup_user, $post_id ) ) {
869 $usergroup_recipients[] = $usergroup_user->user_email;
870 }
871 }
872 }
873 }
874
875 $user_recipients = $this->get_following_users( $post_id, 'user_email' );
876 foreach( $user_recipients as $key => $user ) {
877 $user_object = get_user_by( 'email', $user );
878 if ( ! $this->user_can_be_notified( $user_object, $post_id ) ) {
879 unset( $user_recipients[ $key ] );
880 }
881 }
882
883 // Merge arrays, filter any duplicates, and remove empty entries.
884 $recipients = array_filter( array_unique( array_merge( $admins, $user_recipients, $usergroup_recipients ) ) );
885
886 // Process the recipients for this email to be sent.
887 foreach( $recipients as $key => $user_email ) {
888 // Don't send the email to the current user unless we've explicitly indicated they should receive it.
889 if ( false === apply_filters( 'ef_notification_email_current_user', false ) && wp_get_current_user()->user_email == $user_email ) {
890 unset( $recipients[ $key ] );
891 }
892 }
893
894 /**
895 * Filters the list of notification recipients.
896 *
897 * @param array $recipients List of recipient email addresses.
898 * @param WP_Post $post
899 * @param bool $string True if the recipients list will later be returned as a string.
900 */
901 $recipients = apply_filters( 'ef_notification_recipients', $recipients, $post, $string );
902
903 // If string set to true, return comma-delimited.
904 if ( $string && is_array( $recipients ) ) {
905 return implode( ',', $recipients );
906 } else {
907 return $recipients;
908 }
909 }
910
911 /**
912 * Check if a user can be notified.
913 * This is based off of the ability to edit the post/page by default.
914 *
915 * @since 0.8.3
916 * @param WP_User $user
917 * @param int $post_id
918 * @return bool True if the user can be notified, false otherwise.
919 */
920 function user_can_be_notified( $user, $post_id ) {
921 $can_be_notified = false;
922
923 if ( $user instanceof WP_User && is_user_member_of_blog( $user->ID ) && is_numeric( $post_id ) ) {
924 // The 'edit_post' cap check also covers the undocumented 'edit_page' cap.
925 $can_be_notified = $user->has_cap( 'edit_post', $post_id );
926 }
927
928 /**
929 * Filters if a user can be notified. Defaults to true if they can edit the post/page.
930 *
931 * @param bool $can_be_notified True if the user can be notified.
932 * @param WP_User|bool $user The user object, otherwise false.
933 * @param int $post_id The post the user will be notified about.
934 */
935 return (bool) apply_filters( 'ef_notification_user_can_be_notified', $can_be_notified, $user, $post_id );
936 }
937
938 /**
939 * Set a user or users to follow a post
940 *
941 * @param int|object $post Post object or ID
942 * @param string|array $users User or users to subscribe to post updates
943 * @param bool $append Whether users should be added to following_users list or replace existing list
944 *
945 * @return true|WP_Error $response True on success, WP_Error on failure
946 */
947 function follow_post_user( $post, $users, $append = true ) {
948
949 $post = get_post( $post );
950 if ( ! $post )
951 return new WP_Error( 'missing-post', $this->module->messages['missing-post'] );
952
953 if ( ! is_array( $users ) )
954 $users = array( $users );
955
956 $user_terms = array();
957 foreach( $users as $user ) {
958
959 if ( is_int( $user ) )
960 $user = get_user_by( 'id', $user );
961 elseif ( is_string( $user ) )
962 $user = get_user_by( 'login', $user );
963
964 if ( ! is_object( $user ) )
965 continue;
966
967 $name = $user->user_login;
968
969 // Add user as a term if they don't exist
970 $term = $this->add_term_if_not_exists( $name, $this->following_users_taxonomy );
971
972 if ( ! is_wp_error( $term ) ) {
973 $user_terms[] = $name;
974 }
975 }
976 $set = wp_set_object_terms( $post->ID, $user_terms, $this->following_users_taxonomy, $append );
977
978 if ( is_wp_error( $set ) )
979 return $set;
980 else
981 return true;
982 }
983
984 /**
985 * Removes user from following_users taxonomy for the given Post,
986 * so they no longer receive future notifications.
987 *
988 * @param object $post Post object or ID
989 * @param int|string|array $users One or more users to unfollow from the post
990 * @return true|WP_Error $response True on success, WP_Error on failure
991 */
992 function unfollow_post_user( $post, $users ) {
993
994 $post = get_post( $post );
995 if ( ! $post )
996 return new WP_Error( 'missing-post', $this->module->messages['missing-post'] );
997
998 if ( ! is_array( $users ) )
999 $users = array( $users );
1000
1001 $terms = get_the_terms( $post->ID, $this->following_users_taxonomy );
1002 if ( is_wp_error( $terms ) )
1003 return $terms;
1004
1005 $user_terms = wp_list_pluck( $terms, 'slug' );
1006 foreach( $users as $user ) {
1007
1008 if ( is_int( $user ) )
1009 $user = get_user_by( 'id', $user );
1010 elseif ( is_string( $user ) )
1011 $user = get_user_by( 'login', $user );
1012
1013 if ( ! is_object( $user ) )
1014 continue;
1015
1016 $key = array_search( $user->user_login, $user_terms );
1017 if ( false !== $key )
1018 unset( $user_terms[$key] );
1019 }
1020 $set = wp_set_object_terms( $post->ID, $user_terms, $this->following_users_taxonomy, false );
1021
1022 if ( is_wp_error( $set ) )
1023 return $set;
1024 else
1025 return true;
1026 }
1027
1028 /**
1029 * follow_post_usergroups()
1030 *
1031 */
1032 function follow_post_usergroups( $post, $usergroups = 0, $append = true ) {
1033 if ( !$this->module_enabled( 'user_groups' ) )
1034 return;
1035
1036 $post_id = ( is_int($post) ) ? $post : $post->ID;
1037 if( !is_array($usergroups) )
1038 $usergroups = array($usergroups);
1039
1040 // make sure each usergroup id is an integer and not a number stored as a string
1041 foreach( $usergroups as $key => $usergroup ) {
1042 $usergroups[$key] = intval($usergroup);
1043 }
1044
1045 wp_set_object_terms( $post_id, $usergroups, $this->following_usergroups_taxonomy, $append );
1046 return;
1047 }
1048
1049 /**
1050 * Removes users that are deleted from receiving future notifications (i.e. makes them unfollow posts FOREVER!)
1051 *
1052 * @param $id int ID of the user
1053 */
1054 function delete_user_action( $id ) {
1055 if( !$id ) return;
1056
1057 // get user data
1058 $user = get_userdata($id);
1059
1060 if( $user ) {
1061 // Delete term from the following_users taxonomy
1062 $user_following_term = get_term_by('name', $user->user_login, $this->following_users_taxonomy);
1063 if( $user_following_term ) wp_delete_term($user_following_term->term_id, $this->following_users_taxonomy);
1064 }
1065 return;
1066 }
1067
1068 /**
1069 * Add user as a term if they aren't already
1070 * @param $term string term to be added
1071 * @param $taxonomy string taxonomy to add term to
1072 * @return WP_error if insert fails, true otherwise
1073 */
1074 function add_term_if_not_exists( $term, $taxonomy ) {
1075 if ( !term_exists($term, $taxonomy) ) {
1076 $args = array( 'slug' => sanitize_title($term) );
1077 return wp_insert_term( $term, $taxonomy, $args );
1078 }
1079 return true;
1080 }
1081
1082 /**
1083 * Gets a list of the users following the specified post
1084 *
1085 * @param int $post_id The ID of the post
1086 * @param string $return The field to return
1087 * @return array $users Users following the specified posts
1088 */
1089 function get_following_users( $post_id, $return = 'user_login' ) {
1090
1091 // Get following_users terms for the post
1092 $users = wp_get_object_terms( $post_id, $this->following_users_taxonomy, array('fields' => 'names') );
1093
1094 // Don't have any following users
1095 if( !$users || is_wp_error($users) )
1096 return array();
1097
1098 // if just want user_login, return as is
1099 if ( $return == 'user_login' )
1100 return $users;
1101
1102 foreach( (array)$users as $key => $user ) {
1103 switch( $user ) {
1104 case is_int( $user ):
1105 $search = 'id';
1106 break;
1107 case is_email( $user ):
1108 $search = 'email';
1109 break;
1110 default:
1111 $search = 'login';
1112 break;
1113 }
1114 $new_user = get_user_by( $search, $user );
1115 if ( ! $new_user || ! is_user_member_of_blog( $new_user->ID ) ) {
1116 unset( $users[ $key ] );
1117 continue;
1118 }
1119 switch( $return ) {
1120 case 'user_login':
1121 $users[$key] = $new_user->user_login;
1122 break;
1123 case 'id':
1124 $users[$key] = $new_user->ID;
1125 break;
1126 case 'user_email':
1127 $users[$key] = $new_user->user_email;
1128 break;
1129 }
1130 }
1131 if( !$users || is_wp_error($users) )
1132 $users = array();
1133 return $users;
1134
1135 }
1136
1137 /**
1138 * Gets a list of the usergroups that are following specified post
1139 *
1140 * @param int $post_id
1141 * @return array $usergroups All of the usergroup slugs
1142 */
1143 function get_following_usergroups( $post_id, $return = 'all' ) {
1144 global $edit_flow;
1145
1146 // Workaround for the fact that get_object_terms doesn't return just slugs
1147 if( $return == 'slugs' )
1148 $fields = 'all';
1149 else
1150 $fields = $return;
1151
1152 $usergroups = wp_get_object_terms( $post_id, $this->following_usergroups_taxonomy, array( 'fields' => $fields ) );
1153
1154 if( $return == 'slugs' ) {
1155 $slugs = array();
1156 foreach($usergroups as $usergroup) {
1157 $slugs[] = $usergroup->slug;
1158 }
1159 $usergroups = $slugs;
1160 }
1161 return $usergroups;
1162 }
1163
1164 /**
1165 * Gets a list of posts that a user is following
1166 *
1167 * @param string|int $user user_login or id of user
1168 * @param array $args
1169 * @return array $posts Posts a user is following
1170 */
1171 function get_user_following_posts( $user = 0, $args = null ) {
1172 if ( !$user )
1173 $user = (int) wp_get_current_user()->ID;
1174
1175 if ( is_int($user) )
1176 $user = get_userdata($user)->user_login;
1177
1178 $post_args = array(
1179 'tax_query' => array(
1180 array(
1181 'taxonomy' => $this->following_users_taxonomy,
1182 'field' => 'slug',
1183 'terms' => $user,
1184 )
1185 ),
1186 'posts_per_page' => '10',
1187 'orderby' => 'modified',
1188 'order' => 'DESC',
1189 'post_status' => 'any',
1190 );
1191 $post_args = apply_filters( 'ef_user_following_posts_query_args', $post_args );
1192 $posts = get_posts( $post_args );
1193 return $posts;
1194
1195 }
1196
1197 /**
1198 * Register settings for notifications so we can partially use the Settings API
1199 * (We use the Settings API for form generation, but not saving)
1200 *
1201 * @since 0.7
1202 */
1203 function register_settings() {
1204 add_settings_section( $this->module->options_group_name . '_general', false, '__return_false', $this->module->options_group_name );
1205 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' );
1206 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' );
1207 }
1208
1209 /**
1210 * Chose the post types for notifications
1211 *
1212 * @since 0.7
1213 */
1214 function settings_post_types_option() {
1215 global $edit_flow;
1216 $edit_flow->settings->helper_option_custom_post_type( $this->module );
1217 }
1218
1219 /**
1220 * Option for whether the blog admin email address should be always notified or not
1221 *
1222 * @since 0.7
1223 */
1224 function settings_always_notify_admin_option() {
1225 $options = array(
1226 'off' => __( 'Disabled', 'edit-flow' ),
1227 'on' => __( 'Enabled', 'edit-flow' ),
1228 );
1229 echo '<select id="always_notify_admin" name="' . $this->module->options_group_name . '[always_notify_admin]">';
1230 foreach ( $options as $value => $label ) {
1231 echo '<option value="' . esc_attr( $value ) . '"';
1232 echo selected( $this->module->options->always_notify_admin, $value );
1233 echo '>' . esc_html( $label ) . '</option>';
1234 }
1235 echo '</select>';
1236 }
1237
1238 /**
1239 * Validate our user input as the settings are being saved
1240 *
1241 * @since 0.7
1242 */
1243 function settings_validate( $new_options ) {
1244
1245 // Whitelist validation for the post type options
1246 if ( !isset( $new_options['post_types'] ) )
1247 $new_options['post_types'] = array();
1248 $new_options['post_types'] = $this->clean_post_type_options( $new_options['post_types'], $this->module->post_type_support );
1249
1250 // Whitelist validation for the 'always_notify_admin' options
1251 if ( !isset( $new_options['always_notify_admin'] ) || $new_options['always_notify_admin'] != 'on' )
1252 $new_options['always_notify_admin'] = 'off';
1253
1254 return $new_options;
1255
1256 }
1257
1258 /**
1259 * Settings page for notifications
1260 *
1261 * @since 0.7
1262 */
1263 function print_configure_view() {
1264 ?>
1265 <form class="basic-settings" action="<?php echo esc_url( menu_page_url( $this->module->settings_slug, false ) ); ?>" method="post">
1266 <?php settings_fields( $this->module->options_group_name ); ?>
1267 <?php do_settings_sections( $this->module->options_group_name ); ?>
1268 <?php
1269 echo '<input id="edit_flow_module_name" name="edit_flow_module_name" type="hidden" value="' . esc_attr( $this->module->name ) . '" />';
1270 ?>
1271 <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>
1272 </form>
1273 <?php
1274 }
1275
1276 /**
1277 * Gets a simple phrase containing the formatted date and time that the post is scheduled for.
1278 *
1279 * @since 0.8
1280 *
1281 * @param obj $post Post object
1282 * @return str $scheduled_datetime The scheduled datetime in human-readable format
1283 */
1284 private function get_scheduled_datetime( $post ) {
1285
1286 $scheduled_ts = strtotime( $post->post_date );
1287
1288 $date = date_i18n( get_option( 'date_format' ), $scheduled_ts );
1289 $time = date_i18n( get_option( 'time_format' ), $scheduled_ts );
1290
1291 return sprintf( __( '%1$s at %2$s', 'edit-flow' ), $date, $time );
1292 }
1293 }
1294
1295 }
1296