PluginProbe
Edit Flow / 0.9
Edit Flow v0.9
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, at modules/notifications/notifications.php

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