PluginProbe
Edit Flow / 0.9.9
Edit Flow v0.9.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 / editorial-comments / editorial-comments.php

editorial-comments.php in Edit Flow 0.9.9, at modules/editorial-comments/editorial-comments.php

450 lines 15.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_Editorial_Comments
4 * Threaded commenting in the admin for discussion between writers and editors
5 *
6 * @author batmoo
7 */
8
9 if ( !class_exists( 'EF_Editorial_Comments' ) ) {
10
11 class EF_Editorial_Comments extends EF_Module
12 {
13 // This is comment type used to differentiate editorial comments
14 const comment_type = 'editorial-comment';
15
16 function __construct() {
17
18 $this->module_url = $this->get_module_url( __FILE__ );
19 // Register the module with Edit Flow
20 $args = array(
21 'title' => __( 'Editorial Comments', 'edit-flow' ),
22 'short_description' => __( 'Share internal notes with your team.', 'edit-flow' ),
23 'extended_description' => __( 'Use editorial comments to hold a private discussion about a post. Communicate directly with your writers or editors about what works and what needs to be improved for each piece.', 'edit-flow' ),
24 'module_url' => $this->module_url,
25 'img_url' => $this->module_url . 'lib/editorial_comments_s128.png',
26 'slug' => 'editorial-comments',
27 'default_options' => array(
28 'enabled' => 'on',
29 'post_types' => array(
30 'post' => 'on',
31 'page' => 'on',
32 ),
33 ),
34 'configure_page_cb' => 'print_configure_view',
35 'configure_link_text' => __( 'Choose Post Types', 'edit-flow' ),
36 'autoload' => false,
37 'settings_help_tab' => array(
38 'id' => 'ef-editorial-comments-overview',
39 'title' => __('Overview', 'edit-flow'),
40 'content' => __('<p>Editorial comments help you cut down on email overload and keep the conversation close to where it matters: your content. Threaded commenting in the admin, similar to what you find at the end of a blog post, allows writers and editors to privately leave feedback and discuss what needs to be changed before publication.</p><p>Anyone with access to view the story in progress will also have the ability to comment on it. If you have notifications enabled, those following the post will receive an email every time a comment is left.</p>', 'edit-flow'),
41 ),
42 'settings_help_sidebar' => __( '<p><strong>For more information:</strong></p><p><a href="http://editflow.org/features/editorial-comments/">Editorial Comments 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' ),
43 );
44 $this->module = EditFlow()->register_module( 'editorial_comments', $args );
45 }
46
47 /**
48 * Initialize the rest of the stuff in the class if the module is active
49 */
50 function init() {
51 add_action( 'add_meta_boxes', array ( $this, 'add_post_meta_box' ) );
52 add_action( 'admin_init', array( $this, 'register_settings' ) );
53 add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_scripts' ) );
54 add_action( 'wp_ajax_editflow_ajax_insert_comment', array( $this, 'ajax_insert_comment' ) );
55 }
56
57 /**
58 * Upgrade our data in case we need to
59 *
60 * @since 0.7
61 */
62 function upgrade( $previous_version ) {
63 global $edit_flow;
64
65 // Upgrade path to v0.7
66 if ( version_compare( $previous_version, '0.7' , '<' ) ) {
67 // Technically we've run this code before so we don't want to auto-install new data
68 $edit_flow->update_module_option( $this->module->name, 'loaded_once', true );
69 }
70
71 }
72
73 /**
74 * Load any of the admin scripts we need but only on the pages we need them
75 */
76 function add_admin_scripts( ) {
77 global $pagenow;
78
79 $post_type = $this->get_current_post_type();
80 $supported_post_types = $this->get_post_types_for_module( $this->module );
81 if ( !in_array( $post_type, $supported_post_types ) )
82 return;
83
84 if ( !in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'page-new.php' ) ) )
85 return;
86
87 wp_enqueue_script( 'edit_flow-post_comment', $this->module_url . 'lib/editorial-comments.js', array( 'jquery', 'wp-ajax-response' ), EDIT_FLOW_VERSION, true );
88 wp_localize_script( 'edit_flow-post_comment', '__ef_localize_post_comment', array(
89 'and' => esc_html__( 'and', 'edit-flow' ),
90 'none_notified' => esc_html__( 'No one will be notified.', 'edit-flow' ),
91 ) );
92
93 wp_enqueue_style( 'edit-flow-editorial-comments-css', $this->module_url . 'lib/editorial-comments.css', false, EDIT_FLOW_VERSION, 'all' );
94
95 $thread_comments = (int) get_option('thread_comments');
96 ?>
97 <script type="text/javascript">
98 var ef_thread_comments = <?php echo ($thread_comments) ? $thread_comments : 0; ?>;
99 </script>
100 <?php
101
102 }
103
104 /**
105 * Add the editorial comments metabox to enabled post types
106 *
107 * @uses add_meta_box()
108 */
109 function add_post_meta_box() {
110
111 $supported_post_types = $this->get_post_types_for_module( $this->module );
112 foreach ( $supported_post_types as $post_type )
113 add_meta_box('edit-flow-editorial-comments', __('Editorial Comments', 'edit-flow'), array($this, 'editorial_comments_meta_box'), $post_type, 'normal' );
114
115 }
116
117 function editorial_comments_meta_box( ) {
118 global $post, $post_ID;
119 ?>
120 <div id="ef-comments_wrapper">
121 <a name="editorialcomments"></a>
122
123 <?php
124 // Show comments only if not a new post
125 if ( ! in_array( $post->post_status, array( 'new', 'auto-draft' ) ) ) :
126
127 // Unused since switched to wp_list_comments
128 $editorial_comments = get_comments(
129 array(
130 'post_id' => $post->ID,
131 'comment_type' => self::comment_type,
132 'orderby' => 'comment_date',
133 'order' => 'ASC',
134 'status' => self::comment_type
135 )
136 );
137 ?>
138
139 <ul id="ef-comments">
140 <?php
141 // We use this so we can take advantage of threading and such
142
143 wp_list_comments(
144 array(
145 'type' => self::comment_type,
146 'callback' => array($this, 'the_comment'),
147 'end-callback' => '__return_false'
148 ),
149 $editorial_comments
150 );
151 ?>
152 </ul>
153
154 <?php $this->the_comment_form(); ?>
155
156 <?php
157 else :
158 ?>
159 <p><?php _e( 'You can add editorial comments to a post once you\'ve saved it for the first time.', 'edit-flow' ); ?></p>
160 <?php
161 endif;
162 ?>
163 <div class="clear"></div>
164 </div>
165 <div class="clear"></div>
166 <?php
167 }
168
169 /**
170 * Displays the main commenting form
171 */
172 function the_comment_form( ) {
173 global $post;
174
175 ?>
176 <a href="#" id="ef-comment_respond" onclick="editorialCommentReply.open();return false;" class="button-primary alignright hide-if-no-js" title=" <?php _e( 'Respond to this post', 'edit-flow' ); ?>"><span><?php _e( 'Respond to this post', 'edit-flow' ); ?></span></a>
177
178 <!-- Reply form, hidden until reply clicked by user -->
179 <div id="ef-replyrow" style="display: none;">
180 <div id="ef-replycontainer">
181 <textarea id="ef-replycontent" name="replycontent" cols="40" rows="5"></textarea>
182 </div>
183
184 <?php if ( $this->module_enabled( 'notifications' ) ) : ?>
185 <label for="ef-reply-notifier"><?php esc_html_e( 'The following will be notified:', 'edit-flow' ); ?>
186 <input id="ef-reply-notifier" class="ef-reply-notifier-message" readonly>
187 </label>
188 <?php endif; ?>
189
190 <p id="ef-replysubmit">
191 <a class="ef-replysave button-primary alignright" href="#comments-form">
192 <span id="ef-replybtn"><?php _e('Submit Response', 'edit-flow') ?></span>
193 </a>
194 <a class="ef-replycancel button-secondary alignright" href="#comments-form"><?php _e( 'Cancel', 'edit-flow' ); ?></a>
195 <img alt="Sending comment..." src="<?php echo admin_url('/images/wpspin_light.gif') ?>" class="alignright" style="display: none;" id="ef-comment_loading" />
196 <br class="clear" style="margin-bottom:35px;" />
197 <span style="display: none;" class="error"></span>
198 </p>
199
200 <input type="hidden" value="" id="ef-comment_parent" name="ef-comment_parent" />
201 <input type="hidden" name="ef-post_id" id="ef-post_id" value="<?php echo esc_attr( $post->ID ); ?>" />
202
203 <?php wp_nonce_field('comment', 'ef_comment_nonce', false); ?>
204
205 <br class="clear" />
206 </div>
207
208 <?php
209 }
210
211 /**
212 * Maybe display who was notified underneath an editorial comment.
213 *
214 * @param int $comment_id
215 * @return void
216 */
217 function maybe_output_comment_meta( $comment_id ) {
218 if ( ! $this->module_enabled( 'notifications' ) || ! apply_filters( 'ef_editorial_comments_show_notified_users', true ) ) {
219 return;
220 }
221
222 $notification = get_comment_meta( $comment_id, 'notification_list', true );
223
224 if ( empty( $notification ) ) {
225 $message = esc_html__( 'No users or groups were notified.', 'edit-flow' );
226 } else {
227 $message = '<strong>'. esc_html__( 'Notified', 'edit-flow' ) . ':</strong> ' . esc_html( $notification );
228 }
229
230 echo '<p class="ef-notification-meta">' . $message . '</p>';
231 }
232
233 /**
234 * Displays a single comment
235 */
236 function the_comment($comment, $args, $depth) {
237 global $current_user, $userdata;
238
239 // Get current user
240 wp_get_current_user() ;
241
242 $GLOBALS['comment'] = $comment;
243
244 $actions = array();
245
246 $actions_string = '';
247 // Comments can only be added by users that can edit the post
248 if ( current_user_can('edit_post', $comment->comment_post_ID) ) {
249 $actions['reply'] = '<a onclick="editorialCommentReply.open(\''.$comment->comment_ID.'\',\''.$comment->comment_post_ID.'\');return false;" class="vim-r hide-if-no-js" title="'.__( 'Reply to this comment', 'edit-flow' ).'" href="#">' . __( 'Reply', 'edit-flow' ) . '</a>';
250
251 $sep = ' ';
252 $i = 0;
253 foreach ( $actions as $action => $link ) {
254 ++$i;
255 // Reply and quickedit need a hide-if-no-js span
256 if ( 'reply' == $action || 'quickedit' == $action )
257 $action .= ' hide-if-no-js';
258
259 $actions_string .= "<span class='$action'>$sep$link</span>";
260 }
261 }
262
263 ?>
264
265 <li id="comment-<?php echo esc_attr( $comment->comment_ID ); ?>" <?php comment_class( array( 'comment-item', wp_get_comment_status($comment->comment_ID) ) ); ?>>
266
267 <?php echo get_avatar( $comment->comment_author_email, 50 ); ?>
268
269 <div class="post-comment-wrap">
270 <h5 class="comment-meta">
271 <?php printf( __('<span class="comment-author">%1$s</span><span class="meta"> said on %2$s at %3$s</span>', 'edit-flow'),
272 comment_author_email_link( $comment->comment_author ),
273 get_comment_date( get_option( 'date_format' ) ),
274 get_comment_time() ); ?>
275 </h5>
276
277 <div class="comment-content"><?php comment_text(); ?></div>
278 <?php $this->maybe_output_comment_meta( $comment->comment_ID ); ?>
279 <p class="row-actions"><?php echo $actions_string; ?></p>
280
281 </div>
282 </li>
283 <?php
284 }
285
286 /**
287 * Handles AJAX insert comment
288 */
289 function ajax_insert_comment( ) {
290 global $current_user, $user_ID, $wpdb;
291
292 // Verify nonce
293 if ( !wp_verify_nonce( $_POST['_nonce'], 'comment') )
294 die( __( "Nonce check failed. Please ensure you're supposed to be adding editorial comments.", 'edit-flow' ) );
295
296 // Get user info
297 wp_get_current_user();
298
299 // Set up comment data
300 $post_id = absint( $_POST['post_id'] );
301 $parent = absint( $_POST['parent'] );
302
303 // Only allow the comment if user can edit post
304 // @TODO: allow contributers to add comments as well (?)
305 if ( ! current_user_can( 'edit_post', $post_id ) )
306 die( __('Sorry, you don\'t have the privileges to add editorial comments. Please talk to your Administrator.', 'edit-flow' ) );
307
308 // Verify that comment was actually entered
309 $comment_content = trim($_POST['content']);
310 if( !$comment_content )
311 die( __( "Please enter a comment.", 'edit-flow' ) );
312
313 // Check that we have a post_id and user logged in
314 if( $post_id && $current_user ) {
315
316 // set current time
317 $time = current_time('mysql', $gmt = 0);
318
319 // Set comment data
320 $data = array(
321 'comment_post_ID' => (int) $post_id,
322 'comment_author' => esc_sql($current_user->display_name),
323 'comment_author_email' => esc_sql($current_user->user_email),
324 'comment_author_url' => esc_sql($current_user->user_url),
325 'comment_content' => wp_kses($comment_content, array('a' => array('href' => array(),'title' => array()),'b' => array(),'i' => array(),'strong' => array(),'em' => array(),'u' => array(),'del' => array(), 'blockquote' => array(), 'sub' => array(), 'sup' => array() )),
326 'comment_type' => self::comment_type,
327 'comment_parent' => (int) $parent,
328 'user_id' => (int) $user_ID,
329 'comment_author_IP' => esc_sql($_SERVER['REMOTE_ADDR']),
330 'comment_agent' => esc_sql($_SERVER['HTTP_USER_AGENT']),
331 'comment_date' => $time,
332 'comment_date_gmt' => $time,
333 // Set to -1?
334 'comment_approved' => self::comment_type,
335 );
336
337 $data = apply_filters( 'ef_pre_insert_editorial_comment', $data );
338
339 // Insert Comment
340 $comment_id = wp_insert_comment($data);
341 $comment = get_comment($comment_id);
342
343 // Save the list of notified users/usergroups.
344 if ( $this->module_enabled( 'notifications' ) && apply_filters( 'ef_editorial_comments_show_notified_users', true ) ) {
345 $notification = isset( $_POST['notification'] ) ? sanitize_text_field( $_POST['notification'] ) : '';
346
347 if ( ! empty( $notification ) && __( 'No one will be notified.', 'edit-flow' ) !== $notification ) {
348 add_comment_meta( $comment_id, 'notification_list', $notification );
349 }
350 }
351
352 // Register actions -- will be used to set up notifications and other modules can hook into this
353 if ( $comment_id )
354 do_action( 'ef_post_insert_editorial_comment', $comment );
355
356 // Prepare response
357 $response = new WP_Ajax_Response();
358
359 ob_start();
360 $this->the_comment( $comment, '', '' );
361 $comment_list_item = ob_get_contents();
362 ob_end_clean();
363
364 $response->add( array(
365 'what' => 'comment',
366 'id' => $comment_id,
367 'data' => $comment_list_item,
368 'action' => ($parent) ? 'reply' : 'new'
369 ));
370
371 $response->send();
372
373 } else {
374 die( __('There was a problem of some sort. Try again or contact your administrator.', 'edit-flow') );
375 }
376 }
377
378 /**
379 * Register settings for editorial comments so we can partially use the Settings API
380 * (We use the Settings API for form generation, but not saving)
381 *
382 * @since 0.7
383 */
384 function register_settings() {
385 add_settings_section( $this->module->options_group_name . '_general', false, '__return_false', $this->module->options_group_name );
386 add_settings_field( 'post_types', __( 'Enable for these post types:', 'edit-flow' ), array( $this, 'settings_post_types_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' );
387 }
388
389 /**
390 * Chose the post types for editorial comments
391 *
392 * @since 0.7
393 */
394 function settings_post_types_option() {
395 global $edit_flow;
396 $edit_flow->settings->helper_option_custom_post_type( $this->module );
397 }
398
399 /**
400 * Validate our user input as the settings are being saved
401 *
402 * @since 0.7
403 */
404 function settings_validate( $new_options ) {
405
406 // Whitelist validation for the post type options
407 if ( !isset( $new_options['post_types'] ) )
408 $new_options['post_types'] = array();
409 $new_options['post_types'] = $this->clean_post_type_options( $new_options['post_types'], $this->module->post_type_support );
410
411 return $new_options;
412
413 }
414
415 /**
416 * Settings page for editorial comments
417 *
418 * @since 0.7
419 */
420 function print_configure_view() {
421 ?>
422
423 <form class="basic-settings" action="<?php echo add_query_arg( 'page', $this->module->settings_slug, get_admin_url( null, 'admin.php' ) ); ?>" method="post">
424 <?php settings_fields( $this->module->options_group_name ); ?>
425 <?php do_settings_sections( $this->module->options_group_name ); ?>
426 <?php
427 echo '<input id="edit_flow_module_name" name="edit_flow_module_name" type="hidden" value="' . esc_attr( $this->module->name ) . '" />';
428 ?>
429 <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>
430
431 </form>
432 <?php
433 }
434
435 }
436
437 }
438
439 /**
440 * Deprecated. Used to retrieve a list of comments.
441 * Was needed before https://core.trac.wordpress.org/ticket/10668 was available.
442 *
443 * @param mixed $args Optional. Array or string of options.
444 * @return array List of comments.
445 */
446 function ef_get_comments_plus( $args = '' ) {
447 _deprecated_function( 'ef_get_comments_plus', '1.0', 'get_comments' );
448 return get_comments( $args );
449 }
450