Co-Authors Plus - Version 3.2

Version Description

Various minor bug and security fixes

Download this release

Release Info

Developer automattic
Plugin Icon wp plugin Co-Authors Plus
Version 3.2
Comparing to
See all releases

Code changes from version 3.1.1 to 3.2

bin/install-wp-tests.sh CHANGED
@@ -12,23 +12,50 @@ DB_HOST=${4-localhost}
12
  WP_VERSION=${5-latest}
13
 
14
  WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
15
- WP_CORE_DIR=/tmp/wordpress/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  set -ex
18
 
19
  install_wp() {
 
 
 
 
 
20
  mkdir -p $WP_CORE_DIR
21
 
22
- if [ $WP_VERSION == 'latest' ]; then
23
  local ARCHIVE_NAME='latest'
24
  else
25
  local ARCHIVE_NAME="wordpress-$WP_VERSION"
26
  fi
27
 
28
- wget -nv -O /tmp/wordpress.tar.gz http://wordpress.org/${ARCHIVE_NAME}.tar.gz
29
  tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
30
 
31
- wget -nv -O $WP_CORE_DIR/wp-content/db.php https://raw.github.com/markoheijnen/wp-mysqli/master/db.php
32
  }
33
 
34
  install_test_suite() {
@@ -39,17 +66,24 @@ install_test_suite() {
39
  local ioption='-i'
40
  fi
41
 
42
- # set up testing suite
43
- mkdir -p $WP_TESTS_DIR
 
 
 
 
 
44
  cd $WP_TESTS_DIR
45
- svn co --quiet http://develop.svn.wordpress.org/trunk/tests/phpunit/includes/
46
-
47
- wget -nv -O wp-tests-config.php http://develop.svn.wordpress.org/trunk/wp-tests-config-sample.php
48
- sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" wp-tests-config.php
49
- sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" wp-tests-config.php
50
- sed $ioption "s/yourusernamehere/$DB_USER/" wp-tests-config.php
51
- sed $ioption "s/yourpasswordhere/$DB_PASS/" wp-tests-config.php
52
- sed $ioption "s|localhost|${DB_HOST}|" wp-tests-config.php
 
 
53
  }
54
 
55
  install_db() {
@@ -60,7 +94,7 @@ install_db() {
60
  local EXTRA=""
61
 
62
  if ! [ -z $DB_HOSTNAME ] ; then
63
- if [[ "$DB_SOCK_OR_PORT" =~ ^[0-9]+$ ]] ; then
64
  EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
65
  elif ! [ -z $DB_SOCK_OR_PORT ] ; then
66
  EXTRA=" --socket=$DB_SOCK_OR_PORT"
12
  WP_VERSION=${5-latest}
13
 
14
  WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
15
+ WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
16
+
17
+ download() {
18
+ if [ `which curl` ]; then
19
+ curl -s "$1" > "$2";
20
+ elif [ `which wget` ]; then
21
+ wget -nv -O "$2" "$1"
22
+ fi
23
+ }
24
+
25
+ if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
26
+ WP_TESTS_TAG="tags/$WP_VERSION"
27
+ else
28
+ # http serves a single offer, whereas https serves multiple. we only want one
29
+ download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
30
+ grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
31
+ LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
32
+ if [[ -z "$LATEST_VERSION" ]]; then
33
+ echo "Latest WordPress version could not be found"
34
+ exit 1
35
+ fi
36
+ WP_TESTS_TAG="tags/$LATEST_VERSION"
37
+ fi
38
 
39
  set -ex
40
 
41
  install_wp() {
42
+
43
+ if [ -d $WP_CORE_DIR ]; then
44
+ return;
45
+ fi
46
+
47
  mkdir -p $WP_CORE_DIR
48
 
49
+ if [ $WP_VERSION == 'latest' ]; then
50
  local ARCHIVE_NAME='latest'
51
  else
52
  local ARCHIVE_NAME="wordpress-$WP_VERSION"
53
  fi
54
 
55
+ download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
56
  tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
57
 
58
+ download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
59
  }
60
 
61
  install_test_suite() {
66
  local ioption='-i'
67
  fi
68
 
69
+ # set up testing suite if it doesn't yet exist
70
+ if [ ! -d $WP_TESTS_DIR ]; then
71
+ # set up testing suite
72
+ mkdir -p $WP_TESTS_DIR
73
+ svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
74
+ fi
75
+
76
  cd $WP_TESTS_DIR
77
+
78
+ if [ ! -f wp-tests-config.php ]; then
79
+ download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
80
+ sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
81
+ sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
82
+ sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
83
+ sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
84
+ sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
85
+ fi
86
+
87
  }
88
 
89
  install_db() {
94
  local EXTRA=""
95
 
96
  if ! [ -z $DB_HOSTNAME ] ; then
97
+ if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
98
  EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
99
  elif ! [ -z $DB_SOCK_OR_PORT ] ; then
100
  EXTRA=" --socket=$DB_SOCK_OR_PORT"
co-authors-plus.php CHANGED
@@ -3,9 +3,9 @@
3
  Plugin Name: Co-Authors Plus
4
  Plugin URI: http://wordpress.org/extend/plugins/co-authors-plus/
5
  Description: Allows multiple authors to be assigned to a post. This plugin is an extended version of the Co-Authors plugin developed by Weston Ruter.
6
- Version: 3.1.1
7
  Author: Mohammad Jangda, Daniel Bachhuber, Automattic
8
- Copyright: 2008-2014 Shared and distributed between Mohammad Jangda, Daniel Bachhuber, Weston Ruter
9
 
10
  GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
11
  This program is free software; you can redistribute it and/or modify
@@ -24,17 +24,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
 
25
  */
26
 
27
- define( 'COAUTHORS_PLUS_VERSION', '3.1.1' );
28
 
29
  require_once( dirname( __FILE__ ) . '/template-tags.php' );
30
  require_once( dirname( __FILE__ ) . '/deprecated.php' );
31
 
32
  require_once( dirname( __FILE__ ) . '/php/class-coauthors-template-filters.php' );
 
33
 
34
- if ( defined('WP_CLI') && WP_CLI )
35
  require_once( dirname( __FILE__ ) . '/php/class-wp-cli.php' );
 
36
 
37
- class coauthors_plus {
38
 
39
  // Name for the taxonomy we're using to store relationships
40
  // and the post type we're using to store co-authors
@@ -64,7 +66,7 @@ class coauthors_plus {
64
  add_action( 'init', array( $this, 'action_init_late' ), 100 );
65
 
66
  // Load admin_init function
67
- add_action( 'admin_init', array( $this,'admin_init' ) );
68
 
69
  // Modify SQL queries to include coauthors
70
  add_filter( 'posts_where', array( $this, 'posts_where_filter' ), 10, 2 );
@@ -108,10 +110,12 @@ class coauthors_plus {
108
  // Support Jetpack Open Graph Tags
109
  add_filter( 'jetpack_open_graph_tags', array( $this, 'filter_jetpack_open_graph_tags' ), 10, 2 );
110
 
111
- }
 
 
 
 
112
 
113
- function coauthors_plus() {
114
- $this->__construct();
115
  }
116
 
117
  /**
@@ -134,7 +138,8 @@ class coauthors_plus {
134
 
135
  // Maybe automatically apply our template tags
136
  if ( apply_filters( 'coauthors_auto_apply_template_tags', false ) ) {
137
- new CoAuthors_Template_Filters;
 
138
  }
139
 
140
  }
@@ -153,19 +158,21 @@ class coauthors_plus {
153
  'public' => false,
154
  'sort' => true,
155
  'args' => array( 'orderby' => 'term_order' ),
156
- 'show_ui' => false
157
  );
158
 
159
  // If we use the nasty SQL query, we need our custom callback. Otherwise, we still need to flush cache.
160
- if ( apply_filters( 'coauthors_plus_should_query_post_author', true ) )
161
  $args['update_count_callback'] = array( $this, '_update_users_posts_count' );
162
- else
163
  add_action( 'edited_term_taxonomy', array( $this, 'action_edited_term_taxonomy_flush_cache' ), 10, 2 );
 
164
 
165
  $post_types_with_authors = array_values( get_post_types() );
166
- foreach( $post_types_with_authors as $key => $name ) {
167
- if ( ! post_type_supports( $name, 'author' ) || in_array( $name, array( 'revision', 'attachment' ) ) )
168
- unset( $post_types_with_authors[$key] );
 
169
  }
170
  $this->supported_post_types = apply_filters( 'coauthors_supported_post_types', $post_types_with_authors );
171
  register_taxonomy( $this->coauthor_taxonomy, $this->supported_post_types, $args );
@@ -206,7 +213,7 @@ class coauthors_plus {
206
  * add_filter( 'coauthors_guest_authors_enabled', '__return_false' )
207
  *
208
  * @since 3.0
209
- *
210
  * @return bool
211
  */
212
  public function is_guest_authors_enabled() {
@@ -230,32 +237,38 @@ class coauthors_plus {
230
  }
231
  }
232
 
233
- switch( $key ) {
234
  case 'id':
235
  case 'login':
236
  case 'user_login':
237
  case 'email':
238
  case 'user_nicename':
239
  case 'user_email':
240
- if ( 'user_login' == $key )
241
  $key = 'login';
242
- if ( 'user_email' == $key )
 
243
  $key = 'email';
244
- if ( 'user_nicename' == $key )
 
245
  $key = 'slug';
 
246
  // Ensure we aren't doing the lookup by the prefixed value
247
- if ( 'login' == $key || 'slug' == $key )
248
  $value = preg_replace( '#^cap\-#', '', $value );
 
249
  $user = get_user_by( $key, $value );
250
- if ( ! $user )
251
  return false;
 
252
  $user->type = 'wpuser';
253
  // However, if guest authors are enabled and there's a guest author linked to this
254
  // user account, we want to use that instead
255
  if ( $this->is_guest_authors_enabled() && isset( $this->guest_authors ) ) {
256
  $guest_author = $this->guest_authors->get_guest_author_by( 'linked_account', $user->user_login );
257
- if ( is_object( $guest_author ) )
258
  $user = $guest_author;
 
259
  }
260
  return $user;
261
  break;
@@ -275,8 +288,9 @@ class coauthors_plus {
275
  */
276
  public function is_post_type_enabled( $post_type = null ) {
277
 
278
- if ( ! $post_type )
279
  $post_type = get_post_type();
 
280
 
281
  return (bool) in_array( $post_type, $this->supported_post_types );
282
  }
@@ -287,8 +301,9 @@ class coauthors_plus {
287
  */
288
  public function remove_authors_box() {
289
 
290
- if ( $this->is_post_type_enabled() )
291
  remove_meta_box( $this->coreauthors_meta_box_name, get_post_type(), 'normal' );
 
292
  }
293
 
294
  /**
@@ -296,8 +311,9 @@ class coauthors_plus {
296
  */
297
  public function add_coauthors_box() {
298
 
299
- if( $this->is_post_type_enabled() && $this->current_user_can_set_authors() )
300
- add_meta_box( $this->coauthors_meta_box_name, __('Authors', 'co-authors-plus'), array( $this, 'coauthors_meta_box' ), get_post_type(), apply_filters( 'coauthors_meta_box_context', 'normal'), apply_filters( 'coauthors_meta_box_priority', 'high'));
 
301
  }
302
 
303
  /**
@@ -313,7 +329,7 @@ class coauthors_plus {
313
  // @daniel, $post_id and $post->post_author are always set when a new post is created due to auto draft,
314
  // and the else case below was always able to properly assign users based on wp_posts.post_author,
315
  // but that's not possible with force_guest_authors = true.
316
- if( !$post_id || $post_id == 0 || ( !$post->post_author && !$coauthors_plus->force_guest_authors ) || ( $current_screen->base == 'post' && $current_screen->action == 'add' ) ) {
317
  $coauthors = array();
318
  // If guest authors is enabled, try to find a guest author attached to this user ID
319
  if ( $this->is_guest_authors_enabled() ) {
@@ -325,8 +341,8 @@ class coauthors_plus {
325
  // If the above block was skipped, or if it failed to find a guest author, use the current
326
  // logged in user, so long as force_guest_authors is false. If force_guest_authors = true, we are
327
  // OK with having an empty authoring box.
328
- if ( !$coauthors_plus->force_guest_authors && empty( $coauthors ) ) {
329
- if( is_array( $default_user ) ) {
330
  $coauthors = $default_user;
331
  } else {
332
  $coauthors[] = $default_user;
@@ -337,17 +353,17 @@ class coauthors_plus {
337
  }
338
 
339
  $count = 0;
340
- if( !empty( $coauthors ) ) :
341
  ?>
342
  <div id="coauthors-readonly" class="hide-if-js">
343
  <ul>
344
  <?php
345
- foreach( $coauthors as $coauthor ) :
346
  $count++;
347
  ?>
348
  <li>
349
  <?php echo get_avatar( $coauthor->user_email, $this->gravatar_size ); ?>
350
- <span id="coauthor-readonly-<?php echo $count; ?>" class="coauthor-tag">
351
  <input type="text" name="coauthorsinput[]" readonly="readonly" value="<?php echo esc_attr( $coauthor->display_name ); ?>" />
352
  <input type="text" name="coauthors[]" value="<?php echo esc_attr( $coauthor->user_login ); ?>" />
353
  <input type="text" name="coauthorsemails[]" value="<?php echo esc_attr( $coauthor->user_email ); ?>" />
@@ -359,14 +375,14 @@ class coauthors_plus {
359
  ?>
360
  </ul>
361
  <div class="clear"></div>
362
- <p><?php _e( '<strong>Note:</strong> To edit post authors, please enable javascript or use a javascript-capable browser', 'co-authors-plus' ); ?></p>
363
  </div>
364
  <?php
365
  endif;
366
  ?>
367
 
368
  <div id="coauthors-edit" class="hide-if-no-js">
369
- <p><?php _e( 'Click on an author to change them. Drag to change their order. Click on <strong>Remove</strong> to remove them.', 'co-authors-plus' ); ?></p>
370
  </div>
371
 
372
  <?php wp_nonce_field( 'coauthors-edit', 'coauthors-nonce' ); ?>
@@ -380,8 +396,9 @@ class coauthors_plus {
380
  function remove_quick_edit_authors_box() {
381
  global $pagenow;
382
 
383
- if ( 'edit.php' == $pagenow && $this->is_post_type_enabled() )
384
  remove_post_type_support( get_post_type(), 'author' );
 
385
  }
386
 
387
  /**
@@ -392,16 +409,19 @@ class coauthors_plus {
392
  function _filter_manage_posts_columns( $posts_columns ) {
393
 
394
  $new_columns = array();
395
- if ( ! $this->is_post_type_enabled() )
396
  return $posts_columns;
 
397
 
398
- foreach ($posts_columns as $key => $value) {
399
- $new_columns[$key] = $value;
400
- if( $key == 'title' )
401
  $new_columns['coauthors'] = __( 'Authors', 'co-authors-plus' );
 
402
 
403
- if ( $key == 'author' )
404
- unset($new_columns[$key]);
 
405
  }
406
  return $new_columns;
407
  }
@@ -412,24 +432,25 @@ class coauthors_plus {
412
  * @param string $column_name
413
  */
414
  function _filter_manage_posts_custom_column( $column_name ) {
415
- if ($column_name == 'coauthors') {
416
  global $post;
417
  $authors = get_coauthors( $post->ID );
418
 
419
  $count = 1;
420
- foreach( $authors as $author ) :
421
  $args = array(
422
  'author_name' => $author->user_nicename,
423
  );
424
- if ( 'post' != $post->post_type )
425
  $args['post_type'] = $post->post_type;
426
- $author_filter_url = add_query_arg( $args, admin_url( 'edit.php' ) );
 
427
  ?>
428
  <a href="<?php echo esc_url( $author_filter_url ); ?>"
429
  data-user_nicename="<?php echo esc_attr( $author->user_nicename ) ?>"
430
- data-user_email="<?php echo esc_attr( $author->user_email) ?>"
431
- data-display_name="<?php echo esc_attr( $author->display_name) ?>"
432
- data-user_login="<?php echo esc_attr( $author->user_login) ?>"
433
  ><?php echo esc_html( $author->display_name ); ?></a><?php echo ( $count < count( $authors ) ) ? ',' : ''; ?>
434
  <?php
435
  $count++;
@@ -444,11 +465,12 @@ class coauthors_plus {
444
 
445
  $new_columns = array();
446
  // Unset and add our column while retaining the order of the columns
447
- foreach( $columns as $column_name => $column_title ) {
448
- if ( 'posts' == $column_name )
449
  $new_columns['coauthors_post_count'] = __( 'Posts', 'co-authors-plus' );
450
- else
451
- $new_columns[$column_name] = $column_title;
 
452
  }
453
  return $new_columns;
454
  }
@@ -457,8 +479,9 @@ class coauthors_plus {
457
  * Provide an accurate count when looking up the number of published posts for a user
458
  */
459
  function _filter_manage_users_custom_column( $value, $column_name, $user_id ) {
460
- if ( 'coauthors_post_count' != $column_name )
461
  return $value;
 
462
  // We filter count_user_posts() so it provides an accurate number
463
  $numposts = count_user_posts( $user_id );
464
  $user = get_user_by( 'id', $user_id );
@@ -476,17 +499,14 @@ class coauthors_plus {
476
  * Quick Edit co-authors box.
477
  */
478
  function _action_quick_edit_custom_box( $column_name, $post_type ) {
479
- if (
480
- 'coauthors' != $column_name ||
481
- ! $this->is_post_type_enabled( $post_type ) ||
482
- ! $this->current_user_can_set_authors()
483
- )
484
  return;
 
485
  ?>
486
  <label class="inline-edit-group inline-edit-coauthors">
487
- <span class="title"><?php _e( 'Authors', 'co-authors-plus' ) ?></span>
488
  <div id="coauthors-edit" class="hide-if-no-js">
489
- <p><?php _e( 'Click on an author to change them. Drag to change their order. Click on <strong>Remove</strong> to remove them.', 'co-authors-plus' ); ?></p>
490
  </div>
491
  <?php wp_nonce_field( 'coauthors-edit', 'coauthors-nonce' ); ?>
492
  </label>
@@ -502,7 +522,7 @@ class coauthors_plus {
502
  $tt_ids = implode( ', ', array_map( 'intval', $tt_ids ) );
503
  $term_ids = $wpdb->get_results( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)" );
504
 
505
- foreach( (array)$term_ids as $term_id_result ) {
506
  $term = get_term_by( 'id', $term_id_result->term_id, $this->coauthor_taxonomy );
507
  $this->update_author_term_post_count( $term );
508
  }
@@ -520,15 +540,17 @@ class coauthors_plus {
520
  public function action_edited_term_taxonomy_flush_cache( $tt_id, $taxonomy ) {
521
  global $wpdb;
522
 
523
- if ( $this->coauthor_taxonomy != $taxonomy )
524
  return;
 
525
 
526
  $term_id = $wpdb->get_results( $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d ", $tt_id ) );
527
 
528
  $term = get_term_by( 'id', $term_id[0]->term_id, $taxonomy );
529
  $coauthor = $this->get_coauthor_by( 'user_nicename', $term->slug );
530
- if ( ! $coauthor )
531
  return new WP_Error( 'missing-coauthor', __( 'No co-author exists for that term', 'co-authors-plus' ) );
 
532
 
533
  wp_cache_delete( 'author-term-' . $coauthor->user_nicename, 'co-authors-plus' );
534
  }
@@ -544,8 +566,9 @@ class coauthors_plus {
544
  global $wpdb;
545
 
546
  $coauthor = $this->get_coauthor_by( 'user_nicename', $term->slug );
547
- if ( ! $coauthor )
548
  return new WP_Error( 'missing-coauthor', __( 'No co-author exists for that term', 'co-authors-plus' ) );
 
549
 
550
  $query = "SELECT COUNT({$wpdb->posts}.ID) FROM {$wpdb->posts}";
551
 
@@ -553,8 +576,9 @@ class coauthors_plus {
553
  $query .= " LEFT JOIN {$wpdb->term_taxonomy} ON ( {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id )";
554
 
555
  $having_terms_and_authors = $having_terms = $wpdb->prepare( "{$wpdb->term_taxonomy}.term_id = %d", $term->term_id );
556
- if ( 'wpuser' == $coauthor->type )
557
  $having_terms_and_authors .= $wpdb->prepare( " OR {$wpdb->posts}.post_author = %d", $coauthor->ID );
 
558
 
559
  $post_types = apply_filters( 'coauthors_count_published_post_types', array( 'post' ) );
560
  $post_types = array_map( 'sanitize_key', $post_types );
@@ -562,7 +586,7 @@ class coauthors_plus {
562
 
563
  $query .= " WHERE ({$having_terms_and_authors}) AND {$wpdb->posts}.post_type IN ({$post_types}) AND {$wpdb->posts}.post_status = 'publish'";
564
 
565
- $query .= $wpdb->prepare( " GROUP BY {$wpdb->posts}.ID HAVING MAX( IF( {$wpdb->term_taxonomy}.taxonomy = '%s', IF( {$having_terms},2,1 ),0 ) ) <> 1 ", $this->coauthor_taxonomy );
566
 
567
  $count = $wpdb->query( $query );
568
  $wpdb->update( $wpdb->term_taxonomy, array( 'count' => $count ), array( 'term_taxonomy_id' => $term->term_taxonomy_id ) );
@@ -573,26 +597,28 @@ class coauthors_plus {
573
  /**
574
  * Modify the author query posts SQL to include posts co-authored
575
  */
576
- function posts_join_filter( $join, $query ){
577
  global $wpdb;
578
 
579
- if( $query->is_author() ) {
580
 
581
- if ( !empty( $query->query_vars['post_type'] ) && !is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) )
582
  return $join;
 
583
 
584
- if ( empty( $this->having_terms ) )
585
  return $join;
 
586
 
587
  // Check to see that JOIN hasn't already been added. Props michaelingp and nbaxley
588
  $term_relationship_join = " INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
589
  $term_taxonomy_join = " INNER JOIN {$wpdb->term_taxonomy} ON ( {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id )";
590
 
591
- if( strpos( $join, trim( $term_relationship_join ) ) === false ) {
592
- $join .= str_replace( "INNER JOIN", "LEFT JOIN", $term_relationship_join );
593
  }
594
- if( strpos( $join, trim( $term_taxonomy_join ) ) === false ) {
595
- $join .= str_replace( "INNER JOIN", "LEFT JOIN", $term_taxonomy_join );
596
  }
597
  }
598
 
@@ -602,56 +628,60 @@ class coauthors_plus {
602
  /**
603
  * Modify the author query posts SQL to include posts co-authored
604
  */
605
- function posts_where_filter( $where, $query ){
606
  global $wpdb;
607
 
608
  if ( $query->is_author() ) {
609
 
610
- if ( !empty( $query->query_vars['post_type'] ) && !is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) )
611
  return $where;
 
612
 
613
- if ( $query->get( 'author_name' ) )
614
  $author_name = sanitize_title( $query->get( 'author_name' ) );
615
- else {
616
  $author_data = get_userdata( $query->get( 'author' ) );
617
- if ( is_object( $author_data ) )
618
  $author_name = $author_data->user_nicename;
619
- else
620
  return $where;
 
621
  }
622
 
623
  $terms = array();
624
  $coauthor = $this->get_coauthor_by( 'user_nicename', $author_name );
625
- if ( $author_term = $this->get_author_term( $coauthor ) )
626
  $terms[] = $author_term;
 
627
  // If this coauthor has a linked account, we also need to get posts with those terms
628
  if ( ! empty( $coauthor->linked_account ) ) {
629
  $linked_account = get_user_by( 'login', $coauthor->linked_account );
630
- if ( $guest_author_term = $this->get_author_term( $linked_account ) )
631
  $terms[] = $guest_author_term;
 
632
  }
633
 
634
  // Whether or not to include the original 'post_author' value in the query
635
  // Don't include it if we're forcing guest authors, or it's obvious our query is for a guest author's posts
636
- if ( $this->force_guest_authors || stripos( $where, '.post_author = 0)' ) )
637
  $maybe_both = false;
638
- else
639
  $maybe_both = apply_filters( 'coauthors_plus_should_query_post_author', true );
 
640
 
641
  $maybe_both_query = $maybe_both ? '$1 OR' : '';
642
 
643
- if ( !empty( $terms ) ) {
644
  $terms_implode = '';
645
  $this->having_terms = '';
646
- foreach( $terms as $term ) {
647
  $terms_implode .= '(' . $wpdb->term_taxonomy . '.taxonomy = \''. $this->coauthor_taxonomy.'\' AND '. $wpdb->term_taxonomy .'.term_id = \''. $term->term_id .'\') OR ';
648
  $this->having_terms .= ' ' . $wpdb->term_taxonomy .'.term_id = \''. $term->term_id .'\' OR ';
649
  }
650
  $terms_implode = rtrim( $terms_implode, ' OR' );
651
  $this->having_terms = rtrim( $this->having_terms, ' OR' );
652
- $where = preg_replace( '/(\b(?:' . $wpdb->posts . '\.)?post_author\s*=\s*(\d+))/', '(' . $maybe_both_query . ' ' . $terms_implode . ')', $where, 1 ); #' . $wpdb->postmeta . '.meta_id IS NOT NULL AND
653
  }
654
-
655
  }
656
  return $where;
657
  }
@@ -662,13 +692,14 @@ class coauthors_plus {
662
  function posts_groupby_filter( $groupby, $query ) {
663
  global $wpdb;
664
 
665
- if( $query->is_author() ) {
666
 
667
- if ( !empty( $query->query_vars['post_type'] ) && !is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) )
668
  return $groupby;
 
669
 
670
  if ( $this->having_terms ) {
671
- $having = 'MAX( IF( ' . $wpdb->term_taxonomy . '.taxonomy = \''. $this->coauthor_taxonomy.'\', IF( ' . $this->having_terms . ',2,1 ),0 ) ) <> 1 ';
672
  $groupby = $wpdb->posts . '.ID HAVING ' . $having;
673
  }
674
  }
@@ -681,15 +712,17 @@ class coauthors_plus {
681
  function coauthors_set_post_author_field( $data, $postarr ) {
682
 
683
  // Bail on autosave
684
- if ( defined( 'DOING_AUTOSAVE' ) && !DOING_AUTOSAVE )
685
  return $data;
 
686
 
687
  // Bail on revisions
688
- if ( ! $this->is_post_type_enabled( $data['post_type'] ) )
689
  return $data;
 
690
 
691
  // This action happens when a post is saved while editing a post
692
- if( isset( $_REQUEST['coauthors-nonce'] ) && isset( $_POST['coauthors'] ) && is_array( $_POST['coauthors'] ) ) {
693
  $author = sanitize_text_field( $_POST['coauthors'][0] );
694
  if ( $author ) {
695
  $author_data = $this->get_coauthor_by( 'user_nicename', $author );
@@ -697,13 +730,14 @@ class coauthors_plus {
697
  // because it'll be the valid user ID
698
  if ( 'guest-author' == $author_data->type && ! empty( $author_data->linked_account ) ) {
699
  $data['post_author'] = get_user_by( 'login', $author_data->linked_account )->ID;
700
- } else if ( $author_data->type == 'wpuser' )
701
  $data['post_author'] = $author_data->ID;
 
702
  }
703
  }
704
 
705
  // If for some reason we don't have the coauthors fields set
706
- if( ! isset( $data['post_author'] ) ) {
707
  $user = wp_get_current_user();
708
  $data['post_author'] = $user->ID;
709
  }
@@ -721,15 +755,17 @@ class coauthors_plus {
721
  */
722
  function coauthors_update_post( $post_id, $post ) {
723
 
724
- if ( defined( 'DOING_AUTOSAVE' ) && !DOING_AUTOSAVE )
725
  return;
 
726
 
727
- if ( ! $this->is_post_type_enabled( $post->post_type ) )
728
  return;
 
729
 
730
  if ( $this->current_user_can_set_authors( $post ) ) {
731
  // if current_user_can_set_authors and nonce valid
732
- if( isset( $_POST['coauthors-nonce'] ) && isset( $_POST['coauthors'] ) ) {
733
  check_admin_referer( 'coauthors-edit', 'coauthors-nonce' );
734
 
735
  $coauthors = (array) $_POST['coauthors'];
@@ -740,8 +776,9 @@ class coauthors_plus {
740
  // If the user can't set authors and a co-author isn't currently set, we need to explicity set one
741
  if ( ! $this->has_author_terms( $post_id ) ) {
742
  $user = get_userdata( $post->post_author );
743
- if ( $user )
744
  $this->add_coauthors( $post_id, array( $user->user_login ) );
 
745
  }
746
  }
747
  }
@@ -753,7 +790,7 @@ class coauthors_plus {
753
 
754
  /**
755
  * Add one or more co-authors as bylines for a post
756
- *
757
  * @param int
758
  * @param array
759
  * @param bool
@@ -779,10 +816,10 @@ class coauthors_plus {
779
  // Set the coauthors
780
  $coauthors = array_unique( array_merge( $existing_coauthors, $coauthors ) );
781
  $coauthor_objects = array();
782
- foreach( $coauthors as &$author_name ){
783
 
784
  $author = $this->get_coauthor_by( 'user_nicename', $author_name );
785
- $coauthor_objects[] = $author;
786
  $term = $this->update_author_term( $author );
787
  $author_name = $term->slug;
788
  }
@@ -793,7 +830,7 @@ class coauthors_plus {
793
  $post_author_user = get_user_by( 'id', get_post( $post_id )->post_author );
794
  if ( empty( $post_author_user )
795
  || ! in_array( $post_author_user->user_login, $coauthors ) ) {
796
- foreach( $coauthor_objects as $coauthor_object ) {
797
  if ( 'wpuser' == $coauthor_object->type ) {
798
  $new_author = $coauthor_object;
799
  break;
@@ -817,7 +854,7 @@ class coauthors_plus {
817
  * - Option to specify alternate user in place for each post
818
  * @param delete_id
819
  */
820
- function delete_user_action($delete_id){
821
  global $wpdb;
822
 
823
  $reassign_id = isset( $_POST['reassign_user'] ) ? absint( $_POST['reassign_user'] ) : false;
@@ -827,7 +864,7 @@ class coauthors_plus {
827
  // Get posts belonging to deleted author
828
  $reassign_user = get_user_by( 'id', $reassign_id );
829
  // Set to new author
830
- if( is_object( $reassign_user ) ) {
831
  $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $delete_id ) );
832
 
833
  if ( $post_ids ) {
@@ -853,18 +890,34 @@ class coauthors_plus {
853
  */
854
  function filter_wp_get_object_terms( $terms, $object_ids, $taxonomies, $args ) {
855
 
856
- if ( !isset( $_REQUEST['bulk_edit'] ) || $taxonomies != "'author'" )
857
  return $terms;
 
858
 
859
  global $wpdb;
860
  $orderby = 'ORDER BY tr.term_order';
861
  $order = 'ASC';
862
- $object_ids = (int)$object_ids;
863
- $query = $wpdb->prepare( "SELECT t.slug, t.term_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (%s) AND tr.object_id IN (%s) $orderby $order", $taxonomies, $object_ids );
864
  $raw_coauthors = $wpdb->get_results( $query );
865
  $terms = array();
866
- foreach( $raw_coauthors as $author ) {
867
- $terms[] = $author->slug;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
  }
869
 
870
  return $terms;
@@ -881,7 +934,7 @@ class coauthors_plus {
881
 
882
  $term = $this->get_author_term( $user );
883
  // Only modify the count if the author already exists as a term
884
- if( $term && !is_wp_error( $term ) ) {
885
  $count = $term->count;
886
  }
887
 
@@ -896,22 +949,27 @@ class coauthors_plus {
896
 
897
  if ( ! $post ) {
898
  $post = get_post();
899
- if ( ! $post )
900
  return false;
 
901
  }
902
 
903
  $post_type = $post->post_type;
904
 
905
  // TODO: need to fix this; shouldn't just say no if don't have post_type
906
- if( ! $post_type ) return false;
 
 
907
 
908
  $post_type_object = get_post_type_object( $post_type );
909
  $current_user = wp_get_current_user();
910
- if ( ! $current_user )
911
  return false;
 
912
  // Super admins can do anything
913
- if ( function_exists( 'is_super_admin' ) && is_super_admin() )
914
  return true;
 
915
 
916
  $can_set_authors = isset( $current_user->allcaps['edit_others_posts'] ) ? $current_user->allcaps['edit_others_posts'] : false;
917
 
@@ -923,7 +981,7 @@ class coauthors_plus {
923
  *
924
  * If an author has no posts, we only want to force the queried object to be
925
  * the author if they're a member of the blog.
926
- *
927
  * If the author does have posts, it doesn't matter that they're not an author.
928
  *
929
  * Alternatively, on an author archive, if the first story has coauthors and
@@ -951,7 +1009,8 @@ class coauthors_plus {
951
  $authordata = $author;
952
  $term = $this->get_author_term( $authordata );
953
  }
954
- if ( ( is_object( $authordata ) && is_user_member_of_blog( $authordata->ID ) )
 
955
  || ( ! empty( $term ) && $term->count ) ) {
956
  $wp_query->queried_object = $authordata;
957
  $wp_query->queried_object_id = $authordata->ID;
@@ -962,24 +1021,52 @@ class coauthors_plus {
962
  }
963
  }
964
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
965
  /**
966
  * Main function that handles search-as-you-type for adding authors
967
  */
968
  public function ajax_suggest() {
969
 
970
- if( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'coauthors-search' ) )
971
  die();
 
972
 
973
- if( empty( $_REQUEST['q'] ) )
974
  die();
 
975
 
976
  $search = sanitize_text_field( strtolower( $_REQUEST['q'] ) );
977
  $ignore = array_map( 'sanitize_text_field', explode( ',', $_REQUEST['existing_authors'] ) );
978
 
979
  $authors = $this->search_authors( $search, $ignore );
980
 
981
- foreach( $authors as $author ) {
982
- echo $author->ID ." | ". $author->user_login ." | ". $author->display_name ." | ". $author->user_email ." | ". $author->user_nicename . "\n";
983
  }
984
 
985
  die();
@@ -1010,7 +1097,7 @@ class coauthors_plus {
1010
  $found_users = get_users( $args );
1011
  remove_action( 'pre_user_query', array( $this, 'action_pre_user_query' ) );
1012
 
1013
- foreach( $found_users as $found_user ) {
1014
  $term = $this->get_author_term( $found_user );
1015
  if ( empty( $term ) || empty( $term->description ) ) {
1016
  $this->update_author_term( $found_user );
@@ -1027,25 +1114,28 @@ class coauthors_plus {
1027
  $found_terms = get_terms( $this->coauthor_taxonomy, $args );
1028
  remove_filter( 'terms_clauses', array( $this, 'filter_terms_clauses' ) );
1029
 
1030
- if ( empty( $found_terms ) )
1031
  return array();
 
1032
 
1033
  // Get the co-author objects
1034
  $found_users = array();
1035
- foreach( $found_terms as $found_term ) {
1036
  $found_user = $this->get_coauthor_by( 'user_nicename', $found_term->slug );
1037
- if ( !empty( $found_user ) )
1038
- $found_users[$found_user->user_login] = $found_user;
 
1039
  }
1040
 
1041
  // Allow users to always filter out certain users if needed (e.g. administrators)
1042
  $ignored_authors = apply_filters( 'coauthors_edit_ignored_authors', $ignored_authors );
1043
- foreach( $found_users as $key => $found_user ) {
1044
  // Make sure the user is contributor and above (or a custom cap)
1045
- if ( in_array( $found_user->user_login, $ignored_authors ) )
1046
- unset( $found_users[$key] );
1047
- else if ( $found_user->type == 'wpuser' && false === $found_user->has_cap( apply_filters( 'coauthors_edit_author_cap', 'edit_posts' ) ) )
1048
- unset( $found_users[$key] );
 
1049
  }
1050
  return (array) $found_users;
1051
  }
@@ -1056,7 +1146,7 @@ class coauthors_plus {
1056
  function action_pre_user_query( &$user_query ) {
1057
 
1058
  if ( is_object( $user_query ) ) {
1059
- $user_query->query_where = str_replace( "user_nicename LIKE", "display_name LIKE", $user_query->query_where );
1060
  }
1061
 
1062
  }
@@ -1075,16 +1165,17 @@ class coauthors_plus {
1075
  /**
1076
  * Functions to add scripts and css
1077
  */
1078
- function enqueue_scripts($hook_suffix) {
1079
  global $pagenow, $post;
1080
 
1081
- if ( !$this->is_valid_page() || ! $this->is_post_type_enabled() || !$this->current_user_can_set_authors() )
1082
  return;
 
1083
 
1084
  wp_enqueue_script( 'jquery' );
1085
  wp_enqueue_script( 'jquery-ui-sortable' );
1086
  wp_enqueue_style( 'co-authors-plus-css', plugins_url( 'css/co-authors-plus.css', __FILE__ ), false, COAUTHORS_PLUS_VERSION, 'all' );
1087
- wp_enqueue_script( 'co-authors-plus-js', plugins_url( 'js/co-authors-plus.js', __FILE__ ), array('jquery', 'suggest'), COAUTHORS_PLUS_VERSION, true);
1088
 
1089
  $js_strings = array(
1090
  'edit_label' => __( 'Edit', 'co-authors-plus' ),
@@ -1104,8 +1195,9 @@ class coauthors_plus {
1104
  function load_edit() {
1105
 
1106
  $screen = get_current_screen();
1107
- if ( in_array( $screen->post_type, $this->supported_post_types ) )
1108
  add_filter( 'views_' . $screen->id, array( $this, 'filter_views' ) );
 
1109
  }
1110
 
1111
  /**
@@ -1115,21 +1207,24 @@ class coauthors_plus {
1115
  */
1116
  function filter_views( $views ) {
1117
 
1118
- if ( array_key_exists( 'mine', $views ) )
1119
  return $views;
 
1120
 
1121
  $views = array_reverse( $views );
1122
  $all_view = array_pop( $views );
1123
  $mine_args = array(
1124
  'author_name' => wp_get_current_user()->user_nicename,
1125
  );
1126
- if ( 'post' != get_post_type() )
1127
  $mine_args['post_type'] = get_post_type();
1128
- if ( ! empty( $_REQUEST['author_name'] ) && wp_get_current_user()->user_nicename == $_REQUEST['author_name'] )
 
1129
  $class = ' class="current"';
1130
- else
1131
  $class = '';
1132
- $views['mine'] = $view_mine = '<a' . $class . ' href="' . add_query_arg( $mine_args, admin_url( 'edit.php' ) ) . '">' . __( 'Mine', 'co-authors-plus' ) . '</a>';
 
1133
 
1134
  $views['all'] = str_replace( $class, '', $all_view );
1135
  $views = array_reverse( $views );
@@ -1142,31 +1237,35 @@ class coauthors_plus {
1142
  */
1143
  public function js_vars() {
1144
 
1145
- if ( ! $this->is_valid_page() || ! $this->is_post_type_enabled() || ! $this-> current_user_can_set_authors() )
1146
  return;
 
1147
  ?>
1148
  <script type="text/javascript">
1149
  // AJAX link used for the autosuggest
1150
- var coAuthorsPlus_ajax_suggest_link = '<?php echo add_query_arg(
1151
- array(
1152
- 'action' => 'coauthors_ajax_suggest',
1153
- 'post_type' => get_post_type(),
1154
- ),
1155
- wp_nonce_url( 'admin-ajax.php', 'coauthors-search' )
1156
- ); ?>';
 
 
 
1157
  </script>
1158
  <?php
1159
  }
1160
 
1161
  /**
1162
  * Helper to only add javascript to necessary pages. Avoids bloat in admin.
1163
- *
1164
  * @return bool
1165
  */
1166
  public function is_valid_page() {
1167
  global $pagenow;
1168
 
1169
- return (bool)in_array( $pagenow, $this->_pages_whitelist );
1170
  }
1171
 
1172
  /**
@@ -1179,30 +1278,34 @@ class coauthors_plus {
1179
  $post_id = isset( $args[2] ) ? $args[2] : 0;
1180
 
1181
  $obj = get_post_type_object( get_post_type( $post_id ) );
1182
- if ( ! $obj )
1183
  return $allcaps;
 
1184
 
1185
  $caps_to_modify = array(
1186
  $obj->cap->edit_post,
1187
  'edit_post', // Need to filter this too, unfortunately: http://core.trac.wordpress.org/ticket/22415
1188
  $obj->cap->edit_others_posts, // This as well: http://core.trac.wordpress.org/ticket/22417
1189
  );
1190
- if ( ! in_array( $cap, $caps_to_modify ) )
1191
  return $allcaps;
 
1192
 
1193
  // We won't be doing any modification if they aren't already a co-author on the post
1194
- if( ! is_user_logged_in() || ! is_coauthor_for_post( $user_id, $post_id ) )
1195
  return $allcaps;
 
1196
 
1197
  $current_user = wp_get_current_user();
1198
- if ( 'publish' == get_post_status( $post_id ) &&
1199
- ( isset( $obj->cap->edit_published_posts ) && ! empty( $current_user->allcaps[$obj->cap->edit_published_posts] ) ) )
1200
- $allcaps[$obj->cap->edit_published_posts] = true;
1201
- elseif ( 'private' == get_post_status( $post_id ) &&
1202
- ( isset( $obj->cap->edit_private_posts ) && ! empty( $current_user->allcaps[$obj->cap->edit_private_posts] ) ) )
1203
- $allcaps[$obj->cap->edit_private_posts] = true;
 
1204
 
1205
- $allcaps[$obj->cap->edit_others_posts] = true;
1206
 
1207
  return $allcaps;
1208
  }
@@ -1217,12 +1320,14 @@ class coauthors_plus {
1217
  */
1218
  public function get_author_term( $coauthor ) {
1219
 
1220
- if ( ! is_object( $coauthor ) )
1221
  return;
 
1222
 
1223
  $cache_key = 'author-term-' . $coauthor->user_nicename;
1224
- if ( false !== ( $term = wp_cache_get( $cache_key, 'co-authors-plus' ) ) )
1225
  return $term;
 
1226
 
1227
  // See if the prefixed term is available, otherwise default to just the nicename
1228
  $term = get_term_by( 'slug', 'cap-' . $coauthor->user_nicename, $this->coauthor_taxonomy );
@@ -1243,12 +1348,13 @@ class coauthors_plus {
1243
  */
1244
  public function update_author_term( $coauthor ) {
1245
 
1246
- if ( ! is_object( $coauthor ) )
1247
  return false;
 
1248
 
1249
  // Update the taxonomy term to include details about the user for searching
1250
  $search_values = array();
1251
- foreach( $this->ajax_search_fields as $search_field ) {
1252
  $search_values[] = $coauthor->$search_field;
1253
  }
1254
  $term_description = implode( ' ', $search_values );
@@ -1274,7 +1380,7 @@ class coauthors_plus {
1274
  * Filter Edit Flow's 'ef_calendar_item_information_fields' to add co-authors
1275
  *
1276
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/2
1277
- *
1278
  * @param array $information_fields
1279
  * @param int $post_id
1280
  * @return array
@@ -1282,14 +1388,16 @@ class coauthors_plus {
1282
  function filter_ef_calendar_item_information_fields( $information_fields, $post_id ) {
1283
 
1284
  // Don't add the author row again if another plugin has removed
1285
- if ( !array_key_exists( 'author', $information_fields ) )
1286
  return $information_fields;
 
1287
 
1288
  $co_authors = get_coauthors( $post_id );
1289
- if ( count( $co_authors ) > 1 )
1290
  $information_fields['author']['label'] = __( 'Authors', 'co-authors-plus' );
 
1291
  $co_authors_names = '';
1292
- foreach( $co_authors as $co_author ) {
1293
  $co_authors_names .= $co_author->display_name . ', ';
1294
  }
1295
  $information_fields['author']['value'] = rtrim( $co_authors_names, ', ' );
@@ -1300,7 +1408,7 @@ class coauthors_plus {
1300
  * Filter Edit Flow's 'ef_story_budget_term_column_value' to add co-authors to the story budget
1301
  *
1302
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/2
1303
- *
1304
  * @param string $column_name
1305
  * @param object $post
1306
  * @param object $parent_term
@@ -1309,12 +1417,13 @@ class coauthors_plus {
1309
  function filter_ef_story_budget_term_column_value( $column_name, $post, $parent_term ) {
1310
 
1311
  // We only want to modify the 'author' column
1312
- if ( 'author' != $column_name )
1313
  return $column_name;
 
1314
 
1315
  $co_authors = get_coauthors( $post->ID );
1316
  $co_authors_names = '';
1317
- foreach( $co_authors as $co_author ) {
1318
  $co_authors_names .= $co_author->display_name . ', ';
1319
  }
1320
  return rtrim( $co_authors_names, ', ' );
@@ -1352,203 +1461,147 @@ class coauthors_plus {
1352
  }
1353
 
1354
  // Send back the updated Open Graph Tags
1355
- return $og_tags;
1356
  }
1357
-
1358
  }
1359
 
1360
  global $coauthors_plus;
1361
- $coauthors_plus = new coauthors_plus();
1362
 
1363
- if ( ! function_exists('wp_notify_postauthor') ) :
1364
- /**
1365
- * Notify a co-author of a comment/trackback/pingback to one of their posts.
1366
- * This is a modified version of the core function in wp-includes/pluggable.php that
1367
- * supports notifs to multiple co-authors. Unfortunately, this is the best way to do it :(
1368
- *
1369
- * @since 2.6.2
1370
- *
1371
- * @param int $comment_id Comment ID
1372
- * @param string $comment_type Optional. The comment type either 'comment' (default), 'trackback', or 'pingback'
1373
- * @return bool False if user email does not exist. True on completion.
1374
- */
1375
- function wp_notify_postauthor( $comment_id, $comment_type = '' ) {
1376
- $comment = get_comment( $comment_id );
1377
- $post = get_post( $comment->comment_post_ID );
1378
- $coauthors = get_coauthors( $post->ID );
1379
- foreach( $coauthors as $author ) {
 
 
 
 
 
1380
 
1381
- // The comment was left by the co-author
1382
- if ( $comment->user_id == $author->ID )
1383
- return false;
 
1384
 
1385
- // The co-author moderated a comment on his own post
1386
- if ( $author->ID == get_current_user_id() )
1387
- return false;
 
1388
 
1389
- // If there's no email to send the comment to
1390
- if ( '' == $author->user_email )
1391
- return false;
1392
 
1393
- $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1394
-
1395
- // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1396
- // we want to reverse this for the plain text arena of emails.
1397
- $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1398
-
1399
- if ( empty( $comment_type ) ) $comment_type = 'comment';
1400
-
1401
- if ('comment' == $comment_type) {
1402
- $notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
1403
- /* translators: 1: comment author, 2: author IP, 3: author domain */
1404
- $notify_message .= sprintf( __('Author : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1405
- $notify_message .= sprintf( __('E-mail : %s'), $comment->comment_author_email ) . "\r\n";
1406
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1407
- $notify_message .= sprintf( __('Whois : http://whois.arin.net/rest/ip/%s'), $comment->comment_author_IP ) . "\r\n";
1408
- $notify_message .= __('Comment: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1409
- $notify_message .= __('You can see all comments on this post here: ') . "\r\n";
1410
- /* translators: 1: blog name, 2: post title */
1411
- $subject = sprintf( __('[%1$s] Comment: "%2$s"'), $blogname, $post->post_title );
1412
- } elseif ('trackback' == $comment_type) {
1413
- $notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
1414
- /* translators: 1: website name, 2: author IP, 3: author domain */
1415
- $notify_message .= sprintf( __('Website: %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1416
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1417
- $notify_message .= __('Excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1418
- $notify_message .= __('You can see all trackbacks on this post here: ') . "\r\n";
1419
- /* translators: 1: blog name, 2: post title */
1420
- $subject = sprintf( __('[%1$s] Trackback: "%2$s"'), $blogname, $post->post_title );
1421
- } elseif ('pingback' == $comment_type) {
1422
- $notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
1423
- /* translators: 1: comment author, 2: author IP, 3: author domain */
1424
- $notify_message .= sprintf( __('Website: %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1425
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1426
- $notify_message .= __('Excerpt: ') . "\r\n" . sprintf('[...] %s [...]', $comment->comment_content ) . "\r\n\r\n";
1427
- $notify_message .= __('You can see all pingbacks on this post here: ') . "\r\n";
1428
- /* translators: 1: blog name, 2: post title */
1429
- $subject = sprintf( __('[%1$s] Pingback: "%2$s"'), $blogname, $post->post_title );
1430
- }
1431
- $notify_message .= get_permalink($comment->comment_post_ID) . "#comments\r\n\r\n";
1432
- $notify_message .= sprintf( __('Permalink: %s'), get_permalink( $comment->comment_post_ID ) . '#comment-' . $comment_id ) . "\r\n";
1433
- if ( EMPTY_TRASH_DAYS )
1434
- $notify_message .= sprintf( __('Trash it: %s'), admin_url("comment.php?action=trash&c=$comment_id") ) . "\r\n";
1435
- else
1436
- $notify_message .= sprintf( __('Delete it: %s'), admin_url("comment.php?action=delete&c=$comment_id") ) . "\r\n";
1437
- $notify_message .= sprintf( __('Spam it: %s'), admin_url("comment.php?action=spam&c=$comment_id") ) . "\r\n";
1438
-
1439
- $wp_email = 'wordpress@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME']));
1440
-
1441
- if ( '' == $comment->comment_author ) {
1442
- $from = "From: \"$blogname\" <$wp_email>";
1443
- if ( '' != $comment->comment_author_email )
1444
- $reply_to = "Reply-To: $comment->comment_author_email";
1445
- } else {
1446
- $from = "From: \"$comment->comment_author\" <$wp_email>";
1447
- if ( '' != $comment->comment_author_email )
1448
- $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
1449
- }
1450
 
1451
- $message_headers = "$from\n"
1452
- . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
 
1453
 
1454
- if ( isset($reply_to) )
1455
- $message_headers .= $reply_to . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1456
 
1457
- $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment_id );
1458
- $subject = apply_filters( 'comment_notification_subject', $subject, $comment_id );
1459
- $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment_id );
1460
 
1461
- @wp_mail( $author->user_email, $subject, $notify_message, $message_headers );
1462
- }
 
 
 
 
 
 
 
 
 
1463
 
1464
- return true;
1465
- }
1466
- endif;
1467
 
1468
- if ( !function_exists('wp_notify_moderator') ) :
1469
- /**
1470
- * Notifies the moderator of the blog about a new comment that is awaiting approval.
1471
- * This is a modified version of the core function in wp-includes/pluggable.php that
1472
- * supports notifs to multiple co-authors. Unfortunately, this is the best way to do it :(
1473
- *
1474
- * @since 2.6.2
1475
- *
1476
- * @param int $comment_id Comment ID
1477
- * @return bool Always returns true
1478
- */
1479
- function wp_notify_moderator( $comment_id ) {
1480
- global $wpdb;
1481
 
1482
- if ( 0 == get_option( 'moderation_notify' ) )
1483
- return true;
 
1484
 
1485
- $comment = get_comment($comment_id);
1486
- $post = get_post($comment->comment_post_ID);
1487
- $coauthors = get_coauthors( $post->ID );
1488
- // Send to the administration and to the co-authors if the co-author can modify the comment.
1489
- $email_to = array( get_option('admin_email') );
1490
- foreach( $coauthors as $user ) {
1491
- if ( user_can($user->ID, 'edit_comment', $comment_id) && !empty($user->user_email) && ( get_option('admin_email') != $user->user_email) )
1492
- $email_to[] = $user->user_email;
1493
- }
1494
 
1495
- $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1496
- $comments_waiting = $wpdb->get_var("SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'");
1497
-
1498
- // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1499
- // we want to reverse this for the plain text arena of emails.
1500
- $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1501
-
1502
- switch ($comment->comment_type)
1503
- {
1504
- case 'trackback':
1505
- $notify_message = sprintf( __('A new trackback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1506
- $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1507
- $notify_message .= sprintf( __('Website : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1508
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1509
- $notify_message .= __('Trackback excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1510
- break;
1511
- case 'pingback':
1512
- $notify_message = sprintf( __('A new pingback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1513
- $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1514
- $notify_message .= sprintf( __('Website : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1515
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1516
- $notify_message .= __('Pingback excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1517
- break;
1518
- default: //Comments
1519
- $notify_message = sprintf( __('A new comment on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1520
- $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1521
- $notify_message .= sprintf( __('Author : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1522
- $notify_message .= sprintf( __('E-mail : %s'), $comment->comment_author_email ) . "\r\n";
1523
- $notify_message .= sprintf( __('URL : %s'), $comment->comment_author_url ) . "\r\n";
1524
- $notify_message .= sprintf( __('Whois : http://whois.arin.net/rest/ip/%s'), $comment->comment_author_IP ) . "\r\n";
1525
- $notify_message .= __('Comment: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1526
- break;
1527
  }
 
1528
 
1529
- $notify_message .= sprintf( __('Approve it: %s'), admin_url("comment.php?action=approve&c=$comment_id") ) . "\r\n";
1530
- if ( EMPTY_TRASH_DAYS )
1531
- $notify_message .= sprintf( __('Trash it: %s'), admin_url("comment.php?action=trash&c=$comment_id") ) . "\r\n";
1532
- else
1533
- $notify_message .= sprintf( __('Delete it: %s'), admin_url("comment.php?action=delete&c=$comment_id") ) . "\r\n";
1534
- $notify_message .= sprintf( __('Spam it: %s'), admin_url("comment.php?action=spam&c=$comment_id") ) . "\r\n";
1535
-
1536
- $notify_message .= sprintf( _n('Currently %s comment is waiting for approval. Please visit the moderation panel:',
1537
- 'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting), number_format_i18n($comments_waiting) ) . "\r\n";
1538
- $notify_message .= admin_url("edit-comments.php?comment_status=moderated") . "\r\n";
1539
-
1540
- $subject = sprintf( __('[%1$s] Please moderate: "%2$s"'), $blogname, $post->post_title );
1541
- $message_headers = '';
1542
-
1543
- $notify_message = apply_filters('comment_moderation_text', $notify_message, $comment_id);
1544
- $subject = apply_filters('comment_moderation_subject', $subject, $comment_id);
1545
- $message_headers = apply_filters('comment_moderation_headers', $message_headers);
1546
 
1547
- foreach ( $email_to as $email )
1548
- @wp_mail($email, $subject, $notify_message, $message_headers);
 
 
 
 
 
1549
 
1550
- return true;
 
 
1551
  }
1552
- endif;
1553
-
1554
-
3
  Plugin Name: Co-Authors Plus
4
  Plugin URI: http://wordpress.org/extend/plugins/co-authors-plus/
5
  Description: Allows multiple authors to be assigned to a post. This plugin is an extended version of the Co-Authors plugin developed by Weston Ruter.
6
+ Version: 3.2
7
  Author: Mohammad Jangda, Daniel Bachhuber, Automattic
8
+ Copyright: 2008-2015 Shared and distributed between Mohammad Jangda, Daniel Bachhuber, Weston Ruter
9
 
10
  GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
11
  This program is free software; you can redistribute it and/or modify
24
 
25
  */
26
 
27
+ define( 'COAUTHORS_PLUS_VERSION', '3.1.2' );
28
 
29
  require_once( dirname( __FILE__ ) . '/template-tags.php' );
30
  require_once( dirname( __FILE__ ) . '/deprecated.php' );
31
 
32
  require_once( dirname( __FILE__ ) . '/php/class-coauthors-template-filters.php' );
33
+ require_once( dirname( __FILE__ ) . '/php/integrations/amp.php' );
34
 
35
+ if ( defined( 'WP_CLI' ) && WP_CLI ) {
36
  require_once( dirname( __FILE__ ) . '/php/class-wp-cli.php' );
37
+ }
38
 
39
+ class CoAuthors_Plus {
40
 
41
  // Name for the taxonomy we're using to store relationships
42
  // and the post type we're using to store co-authors
66
  add_action( 'init', array( $this, 'action_init_late' ), 100 );
67
 
68
  // Load admin_init function
69
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
70
 
71
  // Modify SQL queries to include coauthors
72
  add_filter( 'posts_where', array( $this, 'posts_where_filter' ), 10, 2 );
110
  // Support Jetpack Open Graph Tags
111
  add_filter( 'jetpack_open_graph_tags', array( $this, 'filter_jetpack_open_graph_tags' ), 10, 2 );
112
 
113
+ // Filter to send comment moderation notification e-mail to multiple authors
114
+ add_filter( 'comment_moderation_recipients', 'cap_filter_comment_moderation_email_recipients', 10, 2 );
115
+
116
+ // Support infinite scroll for Guest Authors on author pages
117
+ add_filter( 'infinite_scroll_js_settings', array( $this, 'filter_infinite_scroll_js_settings' ), 10, 2 );
118
 
 
 
119
  }
120
 
121
  /**
138
 
139
  // Maybe automatically apply our template tags
140
  if ( apply_filters( 'coauthors_auto_apply_template_tags', false ) ) {
141
+ global $coauthors_plus_template_filters;
142
+ $coauthors_plus_template_filters = new CoAuthors_Template_Filters;
143
  }
144
 
145
  }
158
  'public' => false,
159
  'sort' => true,
160
  'args' => array( 'orderby' => 'term_order' ),
161
+ 'show_ui' => false,
162
  );
163
 
164
  // If we use the nasty SQL query, we need our custom callback. Otherwise, we still need to flush cache.
165
+ if ( apply_filters( 'coauthors_plus_should_query_post_author', true ) ) {
166
  $args['update_count_callback'] = array( $this, '_update_users_posts_count' );
167
+ } else {
168
  add_action( 'edited_term_taxonomy', array( $this, 'action_edited_term_taxonomy_flush_cache' ), 10, 2 );
169
+ }
170
 
171
  $post_types_with_authors = array_values( get_post_types() );
172
+ foreach ( $post_types_with_authors as $key => $name ) {
173
+ if ( ! post_type_supports( $name, 'author' ) || in_array( $name, array( 'revision', 'attachment' ) ) ) {
174
+ unset( $post_types_with_authors[ $key ] );
175
+ }
176
  }
177
  $this->supported_post_types = apply_filters( 'coauthors_supported_post_types', $post_types_with_authors );
178
  register_taxonomy( $this->coauthor_taxonomy, $this->supported_post_types, $args );
213
  * add_filter( 'coauthors_guest_authors_enabled', '__return_false' )
214
  *
215
  * @since 3.0
216
+ *
217
  * @return bool
218
  */
219
  public function is_guest_authors_enabled() {
237
  }
238
  }
239
 
240
+ switch ( $key ) {
241
  case 'id':
242
  case 'login':
243
  case 'user_login':
244
  case 'email':
245
  case 'user_nicename':
246
  case 'user_email':
247
+ if ( 'user_login' == $key ) {
248
  $key = 'login';
249
+ }
250
+ if ( 'user_email' == $key ) {
251
  $key = 'email';
252
+ }
253
+ if ( 'user_nicename' == $key ) {
254
  $key = 'slug';
255
+ }
256
  // Ensure we aren't doing the lookup by the prefixed value
257
+ if ( 'login' == $key || 'slug' == $key ) {
258
  $value = preg_replace( '#^cap\-#', '', $value );
259
+ }
260
  $user = get_user_by( $key, $value );
261
+ if ( ! $user ) {
262
  return false;
263
+ }
264
  $user->type = 'wpuser';
265
  // However, if guest authors are enabled and there's a guest author linked to this
266
  // user account, we want to use that instead
267
  if ( $this->is_guest_authors_enabled() && isset( $this->guest_authors ) ) {
268
  $guest_author = $this->guest_authors->get_guest_author_by( 'linked_account', $user->user_login );
269
+ if ( is_object( $guest_author ) ) {
270
  $user = $guest_author;
271
+ }
272
  }
273
  return $user;
274
  break;
288
  */
289
  public function is_post_type_enabled( $post_type = null ) {
290
 
291
+ if ( ! $post_type ) {
292
  $post_type = get_post_type();
293
+ }
294
 
295
  return (bool) in_array( $post_type, $this->supported_post_types );
296
  }
301
  */
302
  public function remove_authors_box() {
303
 
304
+ if ( $this->is_post_type_enabled() ) {
305
  remove_meta_box( $this->coreauthors_meta_box_name, get_post_type(), 'normal' );
306
+ }
307
  }
308
 
309
  /**
311
  */
312
  public function add_coauthors_box() {
313
 
314
+ if ( $this->is_post_type_enabled() && $this->current_user_can_set_authors() ) {
315
+ add_meta_box( $this->coauthors_meta_box_name, apply_filters( 'coauthors_meta_box_title', __( 'Authors', 'co-authors-plus' ) ), array( $this, 'coauthors_meta_box' ), get_post_type(), apply_filters( 'coauthors_meta_box_context', 'normal' ), apply_filters( 'coauthors_meta_box_priority', 'high' ) );
316
+ }
317
  }
318
 
319
  /**
329
  // @daniel, $post_id and $post->post_author are always set when a new post is created due to auto draft,
330
  // and the else case below was always able to properly assign users based on wp_posts.post_author,
331
  // but that's not possible with force_guest_authors = true.
332
+ if ( ! $post_id || 0 === $post_id || ( ! $post->post_author && ! $coauthors_plus->force_guest_authors ) || ( 'post' === $current_screen->base && 'add' === $current_screen->action ) ) {
333
  $coauthors = array();
334
  // If guest authors is enabled, try to find a guest author attached to this user ID
335
  if ( $this->is_guest_authors_enabled() ) {
341
  // If the above block was skipped, or if it failed to find a guest author, use the current
342
  // logged in user, so long as force_guest_authors is false. If force_guest_authors = true, we are
343
  // OK with having an empty authoring box.
344
+ if ( ! $coauthors_plus->force_guest_authors && empty( $coauthors ) ) {
345
+ if ( is_array( $default_user ) ) {
346
  $coauthors = $default_user;
347
  } else {
348
  $coauthors[] = $default_user;
353
  }
354
 
355
  $count = 0;
356
+ if ( ! empty( $coauthors ) ) :
357
  ?>
358
  <div id="coauthors-readonly" class="hide-if-js">
359
  <ul>
360
  <?php
361
+ foreach ( $coauthors as $coauthor ) :
362
  $count++;
363
  ?>
364
  <li>
365
  <?php echo get_avatar( $coauthor->user_email, $this->gravatar_size ); ?>
366
+ <span id="<?php echo esc_attr( 'coauthor-readonly-' . $count ); ?>" class="coauthor-tag">
367
  <input type="text" name="coauthorsinput[]" readonly="readonly" value="<?php echo esc_attr( $coauthor->display_name ); ?>" />
368
  <input type="text" name="coauthors[]" value="<?php echo esc_attr( $coauthor->user_login ); ?>" />
369
  <input type="text" name="coauthorsemails[]" value="<?php echo esc_attr( $coauthor->user_email ); ?>" />
375
  ?>
376
  </ul>
377
  <div class="clear"></div>
378
+ <p><?php wp_kses( __( '<strong>Note:</strong> To edit post authors, please enable javascript or use a javascript-capable browser', 'co-authors-plus' ), array( 'strong' => array() ) ); ?></p>
379
  </div>
380
  <?php
381
  endif;
382
  ?>
383
 
384
  <div id="coauthors-edit" class="hide-if-no-js">
385
+ <p><?php wp_kses( __( 'Click on an author to change them. Drag to change their order. Click on <strong>Remove</strong> to remove them.', 'co-authors-plus' ), array( 'strong' => array() ) ); ?></p>
386
  </div>
387
 
388
  <?php wp_nonce_field( 'coauthors-edit', 'coauthors-nonce' ); ?>
396
  function remove_quick_edit_authors_box() {
397
  global $pagenow;
398
 
399
+ if ( 'edit.php' == $pagenow && $this->is_post_type_enabled() ) {
400
  remove_post_type_support( get_post_type(), 'author' );
401
+ }
402
  }
403
 
404
  /**
409
  function _filter_manage_posts_columns( $posts_columns ) {
410
 
411
  $new_columns = array();
412
+ if ( ! $this->is_post_type_enabled() ) {
413
  return $posts_columns;
414
+ }
415
 
416
+ foreach ( $posts_columns as $key => $value ) {
417
+ $new_columns[ $key ] = $value;
418
+ if ( 'title' === $key ) {
419
  $new_columns['coauthors'] = __( 'Authors', 'co-authors-plus' );
420
+ }
421
 
422
+ if ( 'author' === $key ) {
423
+ unset( $new_columns[ $key ] );
424
+ }
425
  }
426
  return $new_columns;
427
  }
432
  * @param string $column_name
433
  */
434
  function _filter_manage_posts_custom_column( $column_name ) {
435
+ if ( 'coauthors' === $column_name ) {
436
  global $post;
437
  $authors = get_coauthors( $post->ID );
438
 
439
  $count = 1;
440
+ foreach ( $authors as $author ) :
441
  $args = array(
442
  'author_name' => $author->user_nicename,
443
  );
444
+ if ( 'post' != $post->post_type ) {
445
  $args['post_type'] = $post->post_type;
446
+ }
447
+ $author_filter_url = add_query_arg( array_map( 'rawurlencode', $args ), admin_url( 'edit.php' ) );
448
  ?>
449
  <a href="<?php echo esc_url( $author_filter_url ); ?>"
450
  data-user_nicename="<?php echo esc_attr( $author->user_nicename ) ?>"
451
+ data-user_email="<?php echo esc_attr( $author->user_email ) ?>"
452
+ data-display_name="<?php echo esc_attr( $author->display_name ) ?>"
453
+ data-user_login="<?php echo esc_attr( $author->user_login ) ?>"
454
  ><?php echo esc_html( $author->display_name ); ?></a><?php echo ( $count < count( $authors ) ) ? ',' : ''; ?>
455
  <?php
456
  $count++;
465
 
466
  $new_columns = array();
467
  // Unset and add our column while retaining the order of the columns
468
+ foreach ( $columns as $column_name => $column_title ) {
469
+ if ( 'posts' == $column_name ) {
470
  $new_columns['coauthors_post_count'] = __( 'Posts', 'co-authors-plus' );
471
+ } else {
472
+ $new_columns[ $column_name ] = $column_title;
473
+ }
474
  }
475
  return $new_columns;
476
  }
479
  * Provide an accurate count when looking up the number of published posts for a user
480
  */
481
  function _filter_manage_users_custom_column( $value, $column_name, $user_id ) {
482
+ if ( 'coauthors_post_count' != $column_name ) {
483
  return $value;
484
+ }
485
  // We filter count_user_posts() so it provides an accurate number
486
  $numposts = count_user_posts( $user_id );
487
  $user = get_user_by( 'id', $user_id );
499
  * Quick Edit co-authors box.
500
  */
501
  function _action_quick_edit_custom_box( $column_name, $post_type ) {
502
+ if ( 'coauthors' != $column_name || ! $this->is_post_type_enabled( $post_type ) || ! $this->current_user_can_set_authors() ) {
 
 
 
 
503
  return;
504
+ }
505
  ?>
506
  <label class="inline-edit-group inline-edit-coauthors">
507
+ <span class="title"><?php esc_html_e( 'Authors', 'co-authors-plus' ) ?></span>
508
  <div id="coauthors-edit" class="hide-if-no-js">
509
+ <p><?php wp_kses( __( 'Click on an author to change them. Drag to change their order. Click on <strong>Remove</strong> to remove them.', 'co-authors-plus' ), array( 'strong' => array() ) ); ?></p>
510
  </div>
511
  <?php wp_nonce_field( 'coauthors-edit', 'coauthors-nonce' ); ?>
512
  </label>
522
  $tt_ids = implode( ', ', array_map( 'intval', $tt_ids ) );
523
  $term_ids = $wpdb->get_results( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)" );
524
 
525
+ foreach ( (array) $term_ids as $term_id_result ) {
526
  $term = get_term_by( 'id', $term_id_result->term_id, $this->coauthor_taxonomy );
527
  $this->update_author_term_post_count( $term );
528
  }
540
  public function action_edited_term_taxonomy_flush_cache( $tt_id, $taxonomy ) {
541
  global $wpdb;
542
 
543
+ if ( $this->coauthor_taxonomy != $taxonomy ) {
544
  return;
545
+ }
546
 
547
  $term_id = $wpdb->get_results( $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d ", $tt_id ) );
548
 
549
  $term = get_term_by( 'id', $term_id[0]->term_id, $taxonomy );
550
  $coauthor = $this->get_coauthor_by( 'user_nicename', $term->slug );
551
+ if ( ! $coauthor ) {
552
  return new WP_Error( 'missing-coauthor', __( 'No co-author exists for that term', 'co-authors-plus' ) );
553
+ }
554
 
555
  wp_cache_delete( 'author-term-' . $coauthor->user_nicename, 'co-authors-plus' );
556
  }
566
  global $wpdb;
567
 
568
  $coauthor = $this->get_coauthor_by( 'user_nicename', $term->slug );
569
+ if ( ! $coauthor ) {
570
  return new WP_Error( 'missing-coauthor', __( 'No co-author exists for that term', 'co-authors-plus' ) );
571
+ }
572
 
573
  $query = "SELECT COUNT({$wpdb->posts}.ID) FROM {$wpdb->posts}";
574
 
576
  $query .= " LEFT JOIN {$wpdb->term_taxonomy} ON ( {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id )";
577
 
578
  $having_terms_and_authors = $having_terms = $wpdb->prepare( "{$wpdb->term_taxonomy}.term_id = %d", $term->term_id );
579
+ if ( 'wpuser' == $coauthor->type ) {
580
  $having_terms_and_authors .= $wpdb->prepare( " OR {$wpdb->posts}.post_author = %d", $coauthor->ID );
581
+ }
582
 
583
  $post_types = apply_filters( 'coauthors_count_published_post_types', array( 'post' ) );
584
  $post_types = array_map( 'sanitize_key', $post_types );
586
 
587
  $query .= " WHERE ({$having_terms_and_authors}) AND {$wpdb->posts}.post_type IN ({$post_types}) AND {$wpdb->posts}.post_status = 'publish'";
588
 
589
+ $query .= $wpdb->prepare( " GROUP BY {$wpdb->posts}.ID HAVING MAX( IF ( {$wpdb->term_taxonomy}.taxonomy = '%s', IF ( {$having_terms},2,1 ),0 ) ) <> 1 ", $this->coauthor_taxonomy );
590
 
591
  $count = $wpdb->query( $query );
592
  $wpdb->update( $wpdb->term_taxonomy, array( 'count' => $count ), array( 'term_taxonomy_id' => $term->term_taxonomy_id ) );
597
  /**
598
  * Modify the author query posts SQL to include posts co-authored
599
  */
600
+ function posts_join_filter( $join, $query ) {
601
  global $wpdb;
602
 
603
+ if ( $query->is_author() ) {
604
 
605
+ if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) ) {
606
  return $join;
607
+ }
608
 
609
+ if ( empty( $this->having_terms ) ) {
610
  return $join;
611
+ }
612
 
613
  // Check to see that JOIN hasn't already been added. Props michaelingp and nbaxley
614
  $term_relationship_join = " INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
615
  $term_taxonomy_join = " INNER JOIN {$wpdb->term_taxonomy} ON ( {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id )";
616
 
617
+ if ( false === strpos( $join, trim( $term_relationship_join ) ) ) {
618
+ $join .= str_replace( 'INNER JOIN', 'LEFT JOIN', $term_relationship_join );
619
  }
620
+ if ( false === strpos( $join, trim( $term_taxonomy_join ) ) ) {
621
+ $join .= str_replace( 'INNER JOIN', 'LEFT JOIN', $term_taxonomy_join );
622
  }
623
  }
624
 
628
  /**
629
  * Modify the author query posts SQL to include posts co-authored
630
  */
631
+ function posts_where_filter( $where, $query ) {
632
  global $wpdb;
633
 
634
  if ( $query->is_author() ) {
635
 
636
+ if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) ) {
637
  return $where;
638
+ }
639
 
640
+ if ( $query->get( 'author_name' ) ) {
641
  $author_name = sanitize_title( $query->get( 'author_name' ) );
642
+ } else {
643
  $author_data = get_userdata( $query->get( 'author' ) );
644
+ if ( is_object( $author_data ) ) {
645
  $author_name = $author_data->user_nicename;
646
+ } else {
647
  return $where;
648
+ }
649
  }
650
 
651
  $terms = array();
652
  $coauthor = $this->get_coauthor_by( 'user_nicename', $author_name );
653
+ if ( $author_term = $this->get_author_term( $coauthor ) ) {
654
  $terms[] = $author_term;
655
+ }
656
  // If this coauthor has a linked account, we also need to get posts with those terms
657
  if ( ! empty( $coauthor->linked_account ) ) {
658
  $linked_account = get_user_by( 'login', $coauthor->linked_account );
659
+ if ( $guest_author_term = $this->get_author_term( $linked_account ) ) {
660
  $terms[] = $guest_author_term;
661
+ }
662
  }
663
 
664
  // Whether or not to include the original 'post_author' value in the query
665
  // Don't include it if we're forcing guest authors, or it's obvious our query is for a guest author's posts
666
+ if ( $this->force_guest_authors || stripos( $where, '.post_author = 0)' ) ) {
667
  $maybe_both = false;
668
+ } else {
669
  $maybe_both = apply_filters( 'coauthors_plus_should_query_post_author', true );
670
+ }
671
 
672
  $maybe_both_query = $maybe_both ? '$1 OR' : '';
673
 
674
+ if ( ! empty( $terms ) ) {
675
  $terms_implode = '';
676
  $this->having_terms = '';
677
+ foreach ( $terms as $term ) {
678
  $terms_implode .= '(' . $wpdb->term_taxonomy . '.taxonomy = \''. $this->coauthor_taxonomy.'\' AND '. $wpdb->term_taxonomy .'.term_id = \''. $term->term_id .'\') OR ';
679
  $this->having_terms .= ' ' . $wpdb->term_taxonomy .'.term_id = \''. $term->term_id .'\' OR ';
680
  }
681
  $terms_implode = rtrim( $terms_implode, ' OR' );
682
  $this->having_terms = rtrim( $this->having_terms, ' OR' );
683
+ $where = preg_replace( '/(\b(?:' . $wpdb->posts . '\.)?post_author\s*=\s*(\d+))/', '(' . $maybe_both_query . ' ' . $terms_implode . ')', $where, -1 ); #' . $wpdb->postmeta . '.meta_id IS NOT NULL AND
684
  }
 
685
  }
686
  return $where;
687
  }
692
  function posts_groupby_filter( $groupby, $query ) {
693
  global $wpdb;
694
 
695
+ if ( $query->is_author() ) {
696
 
697
+ if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], $this->coauthor_taxonomy ) ) {
698
  return $groupby;
699
+ }
700
 
701
  if ( $this->having_terms ) {
702
+ $having = 'MAX( IF ( ' . $wpdb->term_taxonomy . '.taxonomy = \''. $this->coauthor_taxonomy.'\', IF ( ' . $this->having_terms . ',2,1 ),0 ) ) <> 1 ';
703
  $groupby = $wpdb->posts . '.ID HAVING ' . $having;
704
  }
705
  }
712
  function coauthors_set_post_author_field( $data, $postarr ) {
713
 
714
  // Bail on autosave
715
+ if ( defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) {
716
  return $data;
717
+ }
718
 
719
  // Bail on revisions
720
+ if ( ! $this->is_post_type_enabled( $data['post_type'] ) ) {
721
  return $data;
722
+ }
723
 
724
  // This action happens when a post is saved while editing a post
725
+ if ( isset( $_REQUEST['coauthors-nonce'] ) && isset( $_POST['coauthors'] ) && is_array( $_POST['coauthors'] ) ) {
726
  $author = sanitize_text_field( $_POST['coauthors'][0] );
727
  if ( $author ) {
728
  $author_data = $this->get_coauthor_by( 'user_nicename', $author );
730
  // because it'll be the valid user ID
731
  if ( 'guest-author' == $author_data->type && ! empty( $author_data->linked_account ) ) {
732
  $data['post_author'] = get_user_by( 'login', $author_data->linked_account )->ID;
733
+ } else if ( 'wpuser' === $author_data->type ) {
734
  $data['post_author'] = $author_data->ID;
735
+ }
736
  }
737
  }
738
 
739
  // If for some reason we don't have the coauthors fields set
740
+ if ( ! isset( $data['post_author'] ) ) {
741
  $user = wp_get_current_user();
742
  $data['post_author'] = $user->ID;
743
  }
755
  */
756
  function coauthors_update_post( $post_id, $post ) {
757
 
758
+ if ( defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) {
759
  return;
760
+ }
761
 
762
+ if ( ! $this->is_post_type_enabled( $post->post_type ) ) {
763
  return;
764
+ }
765
 
766
  if ( $this->current_user_can_set_authors( $post ) ) {
767
  // if current_user_can_set_authors and nonce valid
768
+ if ( isset( $_POST['coauthors-nonce'] ) && isset( $_POST['coauthors'] ) ) {
769
  check_admin_referer( 'coauthors-edit', 'coauthors-nonce' );
770
 
771
  $coauthors = (array) $_POST['coauthors'];
776
  // If the user can't set authors and a co-author isn't currently set, we need to explicity set one
777
  if ( ! $this->has_author_terms( $post_id ) ) {
778
  $user = get_userdata( $post->post_author );
779
+ if ( $user ) {
780
  $this->add_coauthors( $post_id, array( $user->user_login ) );
781
+ }
782
  }
783
  }
784
  }
790
 
791
  /**
792
  * Add one or more co-authors as bylines for a post
793
+ *
794
  * @param int
795
  * @param array
796
  * @param bool
816
  // Set the coauthors
817
  $coauthors = array_unique( array_merge( $existing_coauthors, $coauthors ) );
818
  $coauthor_objects = array();
819
+ foreach ( $coauthors as &$author_name ) {
820
 
821
  $author = $this->get_coauthor_by( 'user_nicename', $author_name );
822
+ $coauthor_objects[] = $author;
823
  $term = $this->update_author_term( $author );
824
  $author_name = $term->slug;
825
  }
830
  $post_author_user = get_user_by( 'id', get_post( $post_id )->post_author );
831
  if ( empty( $post_author_user )
832
  || ! in_array( $post_author_user->user_login, $coauthors ) ) {
833
+ foreach ( $coauthor_objects as $coauthor_object ) {
834
  if ( 'wpuser' == $coauthor_object->type ) {
835
  $new_author = $coauthor_object;
836
  break;
854
  * - Option to specify alternate user in place for each post
855
  * @param delete_id
856
  */
857
+ function delete_user_action( $delete_id ) {
858
  global $wpdb;
859
 
860
  $reassign_id = isset( $_POST['reassign_user'] ) ? absint( $_POST['reassign_user'] ) : false;
864
  // Get posts belonging to deleted author
865
  $reassign_user = get_user_by( 'id', $reassign_id );
866
  // Set to new author
867
+ if ( is_object( $reassign_user ) ) {
868
  $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $delete_id ) );
869
 
870
  if ( $post_ids ) {
890
  */
891
  function filter_wp_get_object_terms( $terms, $object_ids, $taxonomies, $args ) {
892
 
893
+ if ( ! isset( $_REQUEST['bulk_edit'] ) || "'author'" !== $taxonomies ) {
894
  return $terms;
895
+ }
896
 
897
  global $wpdb;
898
  $orderby = 'ORDER BY tr.term_order';
899
  $order = 'ASC';
900
+ $object_ids = (int) $object_ids;
901
+ $query = $wpdb->prepare( "SELECT t.name, t.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (%s) AND tr.object_id IN (%s) $orderby $order", $this->coauthor_taxonomy, $object_ids );
902
  $raw_coauthors = $wpdb->get_results( $query );
903
  $terms = array();
904
+ foreach ( $raw_coauthors as $author ) {
905
+ if ( true === is_array( $args ) && true === isset( $args['fields'] ) ) {
906
+ switch ( $args['fields'] ) {
907
+ case 'names' :
908
+ $terms[] = $author->name;
909
+ break;
910
+ case 'tt_ids' :
911
+ $terms[] = $author->term_taxonomy_id;
912
+ break;
913
+ case 'all' :
914
+ default :
915
+ $terms[] = get_term( $author->term_id, $this->coauthor_taxonomy );
916
+ break;
917
+ }
918
+ } else {
919
+ $terms[] = get_term( $author->term_id, $this->coauthor_taxonomy );
920
+ }
921
  }
922
 
923
  return $terms;
934
 
935
  $term = $this->get_author_term( $user );
936
  // Only modify the count if the author already exists as a term
937
+ if ( $term && ! is_wp_error( $term ) ) {
938
  $count = $term->count;
939
  }
940
 
949
 
950
  if ( ! $post ) {
951
  $post = get_post();
952
+ if ( ! $post ) {
953
  return false;
954
+ }
955
  }
956
 
957
  $post_type = $post->post_type;
958
 
959
  // TODO: need to fix this; shouldn't just say no if don't have post_type
960
+ if ( ! $post_type ) {
961
+ return false;
962
+ }
963
 
964
  $post_type_object = get_post_type_object( $post_type );
965
  $current_user = wp_get_current_user();
966
+ if ( ! $current_user ) {
967
  return false;
968
+ }
969
  // Super admins can do anything
970
+ if ( function_exists( 'is_super_admin' ) && is_super_admin() ) {
971
  return true;
972
+ }
973
 
974
  $can_set_authors = isset( $current_user->allcaps['edit_others_posts'] ) ? $current_user->allcaps['edit_others_posts'] : false;
975
 
981
  *
982
  * If an author has no posts, we only want to force the queried object to be
983
  * the author if they're a member of the blog.
984
+ *
985
  * If the author does have posts, it doesn't matter that they're not an author.
986
  *
987
  * Alternatively, on an author archive, if the first story has coauthors and
1009
  $authordata = $author;
1010
  $term = $this->get_author_term( $authordata );
1011
  }
1012
+
1013
+ if ( ( is_object( $authordata ) )
1014
  || ( ! empty( $term ) && $term->count ) ) {
1015
  $wp_query->queried_object = $authordata;
1016
  $wp_query->queried_object_id = $authordata->ID;
1021
  }
1022
  }
1023
 
1024
+ /**
1025
+ * Filters the Infinite Scroll settings to remove `author` from the query_args
1026
+ * when we are dealing with a Guest Author
1027
+ *
1028
+ * If this isn't removed, the author id can be sent in place of author_name, and the
1029
+ * normal query interception doesn't work, resulting in incorrect results
1030
+ *
1031
+ * @param array $settings The existing IS settings to filter
1032
+ * @return array The filtered IS settings
1033
+ */
1034
+ public function filter_infinite_scroll_js_settings( $settings ) {
1035
+ if ( ! is_author() ) {
1036
+ return $settings;
1037
+ }
1038
+
1039
+ $author = get_queried_object();
1040
+
1041
+ if ( $author && 'guest-author' == $author->type ) {
1042
+ unset( $settings['query_args']['author'] );
1043
+
1044
+ $settings['query_args']['author_name'] = $author->user_nicename;
1045
+ }
1046
+
1047
+ return $settings;
1048
+ }
1049
+
1050
  /**
1051
  * Main function that handles search-as-you-type for adding authors
1052
  */
1053
  public function ajax_suggest() {
1054
 
1055
+ if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'coauthors-search' ) ) {
1056
  die();
1057
+ }
1058
 
1059
+ if ( empty( $_REQUEST['q'] ) ) {
1060
  die();
1061
+ }
1062
 
1063
  $search = sanitize_text_field( strtolower( $_REQUEST['q'] ) );
1064
  $ignore = array_map( 'sanitize_text_field', explode( ',', $_REQUEST['existing_authors'] ) );
1065
 
1066
  $authors = $this->search_authors( $search, $ignore );
1067
 
1068
+ foreach ( $authors as $author ) {
1069
+ echo esc_html( $author->ID . ' | ' . $author->user_login . ' | ' . $author->display_name . ' | ' . $author->user_email . ' | ' . $author->user_nicename ) . "\n";
1070
  }
1071
 
1072
  die();
1097
  $found_users = get_users( $args );
1098
  remove_action( 'pre_user_query', array( $this, 'action_pre_user_query' ) );
1099
 
1100
+ foreach ( $found_users as $found_user ) {
1101
  $term = $this->get_author_term( $found_user );
1102
  if ( empty( $term ) || empty( $term->description ) ) {
1103
  $this->update_author_term( $found_user );
1114
  $found_terms = get_terms( $this->coauthor_taxonomy, $args );
1115
  remove_filter( 'terms_clauses', array( $this, 'filter_terms_clauses' ) );
1116
 
1117
+ if ( empty( $found_terms ) ) {
1118
  return array();
1119
+ }
1120
 
1121
  // Get the co-author objects
1122
  $found_users = array();
1123
+ foreach ( $found_terms as $found_term ) {
1124
  $found_user = $this->get_coauthor_by( 'user_nicename', $found_term->slug );
1125
+ if ( ! empty( $found_user ) ) {
1126
+ $found_users[ $found_user->user_login ] = $found_user;
1127
+ }
1128
  }
1129
 
1130
  // Allow users to always filter out certain users if needed (e.g. administrators)
1131
  $ignored_authors = apply_filters( 'coauthors_edit_ignored_authors', $ignored_authors );
1132
+ foreach ( $found_users as $key => $found_user ) {
1133
  // Make sure the user is contributor and above (or a custom cap)
1134
+ if ( in_array( $found_user->user_login, $ignored_authors ) ) {
1135
+ unset( $found_users[ $key ] );
1136
+ } else if ( 'wpuser' === $found_user->type && false === $found_user->has_cap( apply_filters( 'coauthors_edit_author_cap', 'edit_posts' ) ) ) {
1137
+ unset( $found_users[ $key ] );
1138
+ }
1139
  }
1140
  return (array) $found_users;
1141
  }
1146
  function action_pre_user_query( &$user_query ) {
1147
 
1148
  if ( is_object( $user_query ) ) {
1149
+ $user_query->query_where = str_replace( 'user_nicename LIKE', 'display_name LIKE', $user_query->query_where );
1150
  }
1151
 
1152
  }
1165
  /**
1166
  * Functions to add scripts and css
1167
  */
1168
+ function enqueue_scripts( $hook_suffix ) {
1169
  global $pagenow, $post;
1170
 
1171
+ if ( ! $this->is_valid_page() || ! $this->is_post_type_enabled() || ! $this->current_user_can_set_authors() ) {
1172
  return;
1173
+ }
1174
 
1175
  wp_enqueue_script( 'jquery' );
1176
  wp_enqueue_script( 'jquery-ui-sortable' );
1177
  wp_enqueue_style( 'co-authors-plus-css', plugins_url( 'css/co-authors-plus.css', __FILE__ ), false, COAUTHORS_PLUS_VERSION, 'all' );
1178
+ wp_enqueue_script( 'co-authors-plus-js', plugins_url( 'js/co-authors-plus.js', __FILE__ ), array( 'jquery', 'suggest' ), COAUTHORS_PLUS_VERSION, true );
1179
 
1180
  $js_strings = array(
1181
  'edit_label' => __( 'Edit', 'co-authors-plus' ),
1195
  function load_edit() {
1196
 
1197
  $screen = get_current_screen();
1198
+ if ( in_array( $screen->post_type, $this->supported_post_types ) ) {
1199
  add_filter( 'views_' . $screen->id, array( $this, 'filter_views' ) );
1200
+ }
1201
  }
1202
 
1203
  /**
1207
  */
1208
  function filter_views( $views ) {
1209
 
1210
+ if ( array_key_exists( 'mine', $views ) ) {
1211
  return $views;
1212
+ }
1213
 
1214
  $views = array_reverse( $views );
1215
  $all_view = array_pop( $views );
1216
  $mine_args = array(
1217
  'author_name' => wp_get_current_user()->user_nicename,
1218
  );
1219
+ if ( 'post' != get_post_type() ) {
1220
  $mine_args['post_type'] = get_post_type();
1221
+ }
1222
+ if ( ! empty( $_REQUEST['author_name'] ) && wp_get_current_user()->user_nicename == $_REQUEST['author_name'] ) {
1223
  $class = ' class="current"';
1224
+ } else {
1225
  $class = '';
1226
+ }
1227
+ $views['mine'] = $view_mine = '<a' . $class . ' href="' . esc_url( add_query_arg( array_map( 'rawurlencode', $mine_args ), admin_url( 'edit.php' ) ) ) . '">' . __( 'Mine', 'co-authors-plus' ) . '</a>';
1228
 
1229
  $views['all'] = str_replace( $class, '', $all_view );
1230
  $views = array_reverse( $views );
1237
  */
1238
  public function js_vars() {
1239
 
1240
+ if ( ! $this->is_valid_page() || ! $this->is_post_type_enabled() || ! $this-> current_user_can_set_authors() ) {
1241
  return;
1242
+ }
1243
  ?>
1244
  <script type="text/javascript">
1245
  // AJAX link used for the autosuggest
1246
+ var coAuthorsPlus_ajax_suggest_link = <?php
1247
+ echo wp_json_encode(
1248
+ add_query_arg(
1249
+ array(
1250
+ 'action' => 'coauthors_ajax_suggest',
1251
+ 'post_type' => rawurlencode( get_post_type() ),
1252
+ ),
1253
+ wp_nonce_url( 'admin-ajax.php', 'coauthors-search' )
1254
+ )
1255
+ ); ?>;
1256
  </script>
1257
  <?php
1258
  }
1259
 
1260
  /**
1261
  * Helper to only add javascript to necessary pages. Avoids bloat in admin.
1262
+ *
1263
  * @return bool
1264
  */
1265
  public function is_valid_page() {
1266
  global $pagenow;
1267
 
1268
+ return (bool) in_array( $pagenow, $this->_pages_whitelist );
1269
  }
1270
 
1271
  /**
1278
  $post_id = isset( $args[2] ) ? $args[2] : 0;
1279
 
1280
  $obj = get_post_type_object( get_post_type( $post_id ) );
1281
+ if ( ! $obj || 'revision' == $obj->name ) {
1282
  return $allcaps;
1283
+ }
1284
 
1285
  $caps_to_modify = array(
1286
  $obj->cap->edit_post,
1287
  'edit_post', // Need to filter this too, unfortunately: http://core.trac.wordpress.org/ticket/22415
1288
  $obj->cap->edit_others_posts, // This as well: http://core.trac.wordpress.org/ticket/22417
1289
  );
1290
+ if ( ! in_array( $cap, $caps_to_modify ) ) {
1291
  return $allcaps;
1292
+ }
1293
 
1294
  // We won't be doing any modification if they aren't already a co-author on the post
1295
+ if ( ! is_user_logged_in() || ! is_coauthor_for_post( $user_id, $post_id ) ) {
1296
  return $allcaps;
1297
+ }
1298
 
1299
  $current_user = wp_get_current_user();
1300
+ if ( 'publish' == get_post_status( $post_id ) &&
1301
+ ( isset( $obj->cap->edit_published_posts ) && ! empty( $current_user->allcaps[ $obj->cap->edit_published_posts ] ) ) ) {
1302
+ $allcaps[ $obj->cap->edit_published_posts ] = true;
1303
+ } elseif ( 'private' == get_post_status( $post_id ) &&
1304
+ ( isset( $obj->cap->edit_private_posts ) && ! empty( $current_user->allcaps[ $obj->cap->edit_private_posts ] ) ) ) {
1305
+ $allcaps[ $obj->cap->edit_private_posts ] = true;
1306
+ }
1307
 
1308
+ $allcaps[ $obj->cap->edit_others_posts ] = true;
1309
 
1310
  return $allcaps;
1311
  }
1320
  */
1321
  public function get_author_term( $coauthor ) {
1322
 
1323
+ if ( ! is_object( $coauthor ) ) {
1324
  return;
1325
+ }
1326
 
1327
  $cache_key = 'author-term-' . $coauthor->user_nicename;
1328
+ if ( false !== ( $term = wp_cache_get( $cache_key, 'co-authors-plus' ) ) ) {
1329
  return $term;
1330
+ }
1331
 
1332
  // See if the prefixed term is available, otherwise default to just the nicename
1333
  $term = get_term_by( 'slug', 'cap-' . $coauthor->user_nicename, $this->coauthor_taxonomy );
1348
  */
1349
  public function update_author_term( $coauthor ) {
1350
 
1351
+ if ( ! is_object( $coauthor ) ) {
1352
  return false;
1353
+ }
1354
 
1355
  // Update the taxonomy term to include details about the user for searching
1356
  $search_values = array();
1357
+ foreach ( $this->ajax_search_fields as $search_field ) {
1358
  $search_values[] = $coauthor->$search_field;
1359
  }
1360
  $term_description = implode( ' ', $search_values );
1380
  * Filter Edit Flow's 'ef_calendar_item_information_fields' to add co-authors
1381
  *
1382
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/2
1383
+ *
1384
  * @param array $information_fields
1385
  * @param int $post_id
1386
  * @return array
1388
  function filter_ef_calendar_item_information_fields( $information_fields, $post_id ) {
1389
 
1390
  // Don't add the author row again if another plugin has removed
1391
+ if ( ! array_key_exists( 'author', $information_fields ) ) {
1392
  return $information_fields;
1393
+ }
1394
 
1395
  $co_authors = get_coauthors( $post_id );
1396
+ if ( count( $co_authors ) > 1 ) {
1397
  $information_fields['author']['label'] = __( 'Authors', 'co-authors-plus' );
1398
+ }
1399
  $co_authors_names = '';
1400
+ foreach ( $co_authors as $co_author ) {
1401
  $co_authors_names .= $co_author->display_name . ', ';
1402
  }
1403
  $information_fields['author']['value'] = rtrim( $co_authors_names, ', ' );
1408
  * Filter Edit Flow's 'ef_story_budget_term_column_value' to add co-authors to the story budget
1409
  *
1410
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/2
1411
+ *
1412
  * @param string $column_name
1413
  * @param object $post
1414
  * @param object $parent_term
1417
  function filter_ef_story_budget_term_column_value( $column_name, $post, $parent_term ) {
1418
 
1419
  // We only want to modify the 'author' column
1420
+ if ( 'author' != $column_name ) {
1421
  return $column_name;
1422
+ }
1423
 
1424
  $co_authors = get_coauthors( $post->ID );
1425
  $co_authors_names = '';
1426
+ foreach ( $co_authors as $co_author ) {
1427
  $co_authors_names .= $co_author->display_name . ', ';
1428
  }
1429
  return rtrim( $co_authors_names, ', ' );
1461
  }
1462
 
1463
  // Send back the updated Open Graph Tags
1464
+ return apply_filters( 'coauthors_open_graph_tags', $og_tags );
1465
  }
 
1466
  }
1467
 
1468
  global $coauthors_plus;
1469
+ $coauthors_plus = new CoAuthors_Plus();
1470
 
1471
+ if ( ! function_exists( 'wp_notify_postauthor' ) ) :
1472
+ /**
1473
+ * Notify a co-author of a comment/trackback/pingback to one of their posts.
1474
+ * This is a modified version of the core function in wp-includes/pluggable.php that
1475
+ * supports notifs to multiple co-authors. Unfortunately, this is the best way to do it :(
1476
+ *
1477
+ * @since 2.6.2
1478
+ *
1479
+ * @param int $comment_id Comment ID
1480
+ * @param string $comment_type Optional. The comment type either 'comment' (default), 'trackback', or 'pingback'
1481
+ * @return bool False if user email does not exist. True on completion.
1482
+ */
1483
+ function wp_notify_postauthor( $comment_id, $comment_type = '' ) {
1484
+ $comment = get_comment( $comment_id );
1485
+ $post = get_post( $comment->comment_post_ID );
1486
+ $coauthors = get_coauthors( $post->ID );
1487
+ foreach ( $coauthors as $author ) {
1488
+
1489
+ // The comment was left by the co-author
1490
+ if ( $comment->user_id == $author->ID ) {
1491
+ return false;
1492
+ }
1493
 
1494
+ // The co-author moderated a comment on his own post
1495
+ if ( $author->ID == get_current_user_id() ) {
1496
+ return false;
1497
+ }
1498
 
1499
+ // If there's no email to send the comment to
1500
+ if ( '' == $author->user_email ) {
1501
+ return false;
1502
+ }
1503
 
1504
+ $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
 
 
1505
 
1506
+ // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1507
+ // we want to reverse this for the plain text arena of emails.
1508
+ $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1509
 
1510
+ if ( empty( $comment_type ) ) {
1511
+ $comment_type = 'comment';
1512
+ }
1513
 
1514
+ if ( 'comment' == $comment_type ) {
1515
+ $notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
1516
+ /* translators: 1: comment author, 2: author IP, 3: author domain */
1517
+ $notify_message .= sprintf( __( 'Author : %1$s (IP: %2$s , %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1518
+ $notify_message .= sprintf( __( 'E-mail : %s' ), $comment->comment_author_email ) . "\r\n";
1519
+ $notify_message .= sprintf( __( 'URL : %s' ), $comment->comment_author_url ) . "\r\n";
1520
+ $notify_message .= sprintf( __( 'Whois : http://whois.arin.net/rest/ip/%s' ), $comment->comment_author_IP ) . "\r\n";
1521
+ $notify_message .= __( 'Comment: ' ) . "\r\n" . $comment->comment_content . "\r\n\r\n";
1522
+ $notify_message .= __( 'You can see all comments on this post here: ' ) . "\r\n";
1523
+ /* translators: 1: blog name, 2: post title */
1524
+ $subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
1525
+ } elseif ( 'trackback' == $comment_type ) {
1526
+ $notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
1527
+ /* translators: 1: website name, 2: author IP, 3: author domain */
1528
+ $notify_message .= sprintf( __( 'Website: %1$s (IP: %2$s , %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1529
+ $notify_message .= sprintf( __( 'URL : %s' ), $comment->comment_author_url ) . "\r\n";
1530
+ $notify_message .= __( 'Excerpt: ' ) . "\r\n" . $comment->comment_content . "\r\n\r\n";
1531
+ $notify_message .= __( 'You can see all trackbacks on this post here: ' ) . "\r\n";
1532
+ /* translators: 1: blog name, 2: post title */
1533
+ $subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
1534
+ } elseif ( 'pingback' == $comment_type ) {
1535
+ $notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
1536
+ /* translators: 1: comment author, 2: author IP, 3: author domain */
1537
+ $notify_message .= sprintf( __( 'Website: %1$s (IP: %2$s , %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1538
+ $notify_message .= sprintf( __( 'URL : %s' ), $comment->comment_author_url ) . "\r\n";
1539
+ $notify_message .= __( 'Excerpt: ' ) . "\r\n" . sprintf( '[...] %s [...]', $comment->comment_content ) . "\r\n\r\n";
1540
+ $notify_message .= __( 'You can see all pingbacks on this post here: ' ) . "\r\n";
1541
+ /* translators: 1: blog name, 2: post title */
1542
+ $subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
1543
+ }
1544
+ $notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
1545
+ $notify_message .= sprintf( __( 'Permalink: %s' ), get_permalink( $comment->comment_post_ID ) . '#comment-' . $comment_id ) . "\r\n";
1546
+ if ( EMPTY_TRASH_DAYS ) {
1547
+ $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c=$comment_id" ) ) . "\r\n";
1548
+ } else {
1549
+ $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c=$comment_id" ) ) . "\r\n";
1550
+ }
1551
+ $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c=$comment_id" ) ) . "\r\n";
1552
 
1553
+ $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
 
 
1554
 
1555
+ if ( '' == $comment->comment_author ) {
1556
+ $from = "From: \"$blogname\" <$wp_email>";
1557
+ if ( '' != $comment->comment_author_email ) {
1558
+ $reply_to = "Reply-To: $comment->comment_author_email";
1559
+ }
1560
+ } else {
1561
+ $from = "From: \"$comment->comment_author\" <$wp_email>";
1562
+ if ( '' != $comment->comment_author_email ) {
1563
+ $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
1564
+ }
1565
+ }
1566
 
1567
+ $message_headers = "$from\n"
1568
+ . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
 
1569
 
1570
+ if ( isset( $reply_to ) ) {
1571
+ $message_headers .= $reply_to . "\n";
1572
+ }
 
 
 
 
 
 
 
 
 
 
1573
 
1574
+ $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment_id );
1575
+ $subject = apply_filters( 'comment_notification_subject', $subject, $comment_id );
1576
+ $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment_id );
1577
 
1578
+ @wp_mail( $author->user_email, $subject, $notify_message, $message_headers );
1579
+ }
 
 
 
 
 
 
 
1580
 
1581
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1582
  }
1583
+ endif;
1584
 
1585
+ /**
1586
+ * Filter array of moderation notification email addresses
1587
+ *
1588
+ * @param array $recipients
1589
+ * @param int $comment_id
1590
+ * @return array
1591
+ */
1592
+ function cap_filter_comment_moderation_email_recipients( $recipients, $comment_id ) {
1593
+ $comment = get_comment( $comment_id );
1594
+ $post_id = $comment->comment_post_ID;
 
 
 
 
 
 
 
1595
 
1596
+ if ( isset( $post_id ) ) {
1597
+ $coauthors = get_coauthors( $post_id );
1598
+ foreach ( $coauthors as $user ) {
1599
+ if ( ! empty( $user->user_email ) ) {
1600
+ $extra_recipients[] = $user->user_email;
1601
+ }
1602
+ }
1603
 
1604
+ return array_unique( array_merge( $recipients, $extra_recipients ) );
1605
+ }
1606
+ return $recipients;
1607
  }
 
 
 
css/co-authors-plus.css CHANGED
@@ -73,14 +73,14 @@
73
  text-decoration: underline;
74
  color: #FF0000;
75
  font-size: 11px;
76
-
77
  border: 1px solid transparent;
78
  }
79
  #coauthors-list .delete-coauthor:hover {
80
  cursor: pointer;
81
  background: #FF0000;
82
  color: #fff;
83
-
84
  border: 1px solid #FF0000;
85
  border-radius: 3px;
86
  -moz-border-radius: 3px;
@@ -89,7 +89,7 @@
89
  #coauthors-loading {
90
  margin: 10px 0px 5px 10px;
91
  }
92
-
93
  #coauthors-readonly {
94
  }
95
  #coauthors-readonly ul {
73
  text-decoration: underline;
74
  color: #FF0000;
75
  font-size: 11px;
76
+
77
  border: 1px solid transparent;
78
  }
79
  #coauthors-list .delete-coauthor:hover {
80
  cursor: pointer;
81
  background: #FF0000;
82
  color: #fff;
83
+
84
  border: 1px solid #FF0000;
85
  border-radius: 3px;
86
  -moz-border-radius: 3px;
89
  #coauthors-loading {
90
  margin: 10px 0px 5px 10px;
91
  }
92
+
93
  #coauthors-readonly {
94
  }
95
  #coauthors-readonly ul {
deprecated.php CHANGED
@@ -4,4 +4,4 @@
4
  * Constants
5
  */
6
  define( 'COAUTHORS_PLUS_PATH', dirname( __FILE__ ) );
7
- define( 'COAUTHORS_PLUS_URL', plugin_dir_url( __FILE__ ) );
4
  * Constants
5
  */
6
  define( 'COAUTHORS_PLUS_PATH', dirname( __FILE__ ) );
7
+ define( 'COAUTHORS_PLUS_URL', plugin_dir_url( __FILE__ ) );
js/co-authors-plus.js CHANGED
@@ -1,533 +1,448 @@
1
- jQuery(document).ready(function () {
2
-
3
- /*
4
- * Click handler for the delete button
5
- * @param event
6
- */
7
- var coauthors_delete_onclick = function(e){
8
- if(confirm(coAuthorsPlusStrings.confirm_delete)) {
9
- return coauthors_delete(this);
10
- }
11
- return false;
12
- };
13
-
14
- function coauthors_delete( elem ) {
15
-
16
- var $coauthor_row = jQuery(elem).closest('.coauthor-row');
17
- $coauthor_row.remove();
18
-
19
- // Hide the delete button when there's only one Co-Author
20
- if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length <= 1 )
21
- jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).addClass('hidden');
22
-
23
- return true;
24
- }
25
-
26
- var coauthors_edit_onclick = function(event) {
27
- var $tag = jQuery(this);
28
-
29
- var $co = $tag.prev();
30
-
31
- $tag.hide();
32
- $co.show()
33
- .focus()
34
- ;
35
-
36
- $co.previousAuthor = $tag.text();
37
- }
38
-
39
- /*
40
- * Save coauthor
41
- * @param int Author ID
42
- * @param string Author Name
43
- * @param object The autosuggest input box
44
- */
45
- function coauthors_save_coauthor(author, co) {
46
-
47
- // get sibling <span> and update
48
- co.siblings('.coauthor-tag')
49
- .html(author.name)
50
- .append(coauthors_create_author_gravatar(author))
51
- .show()
52
- ;
53
-
54
- // Update the value of the hidden input
55
- co.siblings('input[name="coauthors[]"]').val(author.nicename);
56
- }
57
-
58
-
59
- /*
60
- * Add coauthor
61
- * @param string Author Name
62
- * @param object The autosuggest input box
63
- * @param boolean Initial set up or not?
64
- */
65
- // function coauthors_add_coauthor(authorID, authorName, co, init, count){
66
- function coauthors_add_coauthor(author, co, init, count){
67
-
68
- // Check if editing
69
- if( co && co.siblings('.coauthor-tag').length ) {
70
- coauthors_save_coauthor(author, co);
71
- } else {
72
- // Not editing, so we create a new author entry
73
- if(count == 0) {
74
- var coName = (count == 0) ? 'coauthors-main' : '';
75
- // Add new author to <select>
76
- //coauthors_select_author( author );
77
- }
78
- var options = { addDelete: true, addEdit: false };
79
-
80
- // Create autosuggest box and text tag
81
- if(!co) var co = coauthors_create_autosuggest(author, coName)
82
- var tag = coauthors_create_author_tag(author);
83
- var input = coauthors_create_author_hidden_input(author);
84
- var $gravatar = coauthors_create_author_gravatar(author, 25);
85
-
86
- tag.append($gravatar);
87
-
88
- coauthors_add_to_table(co, tag, input, options);
89
-
90
- if(!init) {
91
- // Create new author-suggest and append it to a new row
92
- var newCO = coauthors_create_autosuggest('', false);
93
- coauthors_add_to_table(newCO);
94
- move_loading(newCO);
95
- }
96
- }
97
-
98
- co.bind('blur', coauthors_stop_editing);
99
-
100
- // Set the value for the auto-suggest box to the Author's name and hide it
101
- co.val(unescape(author.name))
102
- .hide()
103
- .unbind('focus')
104
- ;
105
-
106
- return true;
107
- }
108
-
109
-
110
- /*
111
- * Add the autosuggest box and text tag to the Co-Authors table
112
- * @param object Autosuggest input box
113
- * @param object Text tag
114
- * @param
115
- */
116
- function coauthors_add_to_table( co, tag, input, options ) {
117
- if(co) {
118
- var $div = jQuery('<div/>')
119
- .addClass('suggest')
120
- .addClass('coauthor-row')
121
- .append(co)
122
- .append(tag)
123
- .append(input)
124
- ;
125
-
126
- //Add buttons to row
127
- if(tag) coauthors_insert_author_edit_cells($div, options);
128
-
129
- jQuery('#coauthors-list').append($div);
130
- }
131
- }
132
-
133
- /*
134
- * Adds a delete and edit button next to an author
135
- * @param object The row to which the new author should be added
136
- */
137
- function coauthors_insert_author_edit_cells($div, options){
138
-
139
- var $options = jQuery('<div/>')
140
- .addClass('coauthors-author-options')
141
- ;
142
-
143
- /*
144
- if(options.addEdit) {
145
- var editBtn = jQuery('<span></span>')
146
- .addClass('edit-coauthor')
147
- .text(coAuthorsPlusStrings.edit_label)
148
- .bind('click', coauthors_edit_onclick)
149
- ;
150
- td.append(editBtn);
151
- }
152
- */
153
- if(options.addDelete) {
154
- var deleteBtn = jQuery('<span/>')
155
- .addClass('delete-coauthor')
156
- .text(coAuthorsPlusStrings.delete_label)
157
- .bind('click', coauthors_delete_onclick)
158
- ;
159
- $options.append(deleteBtn);
160
- }
161
-
162
- $div.append($options);
163
- return $div;
164
- }
165
-
166
- /*
167
- * Creates autosuggest input box
168
- * @param string [optional] Name of the author
169
- * @param string [optional] Name to be applied to the input box
170
- */
171
- function coauthors_create_autosuggest(authorName, inputName) {
172
-
173
- if(!inputName) inputName = 'coauthorsinput[]';
174
-
175
- var $co = jQuery('<input/>');
176
-
177
- $co.attr({
178
- 'class': 'coauthor-suggest'
179
- , 'name': inputName
180
- })
181
- .appendTo($coauthors_div)
182
- /*
183
- .autocomplete(coauthors_all, {
184
- matchContains: true
185
- , scroll: false
186
- , formatItem: function(row) { return row[2] + ' ' + row[0] + ' | ' + row[1] }
187
- , formatResult: function(row) { return row[1]; }
188
- })
189
- */
190
- .suggest(coAuthorsPlus_ajax_suggest_link, {
191
- onSelect: coauthors_autosuggest_select
192
- })
193
- .keydown(coauthors_autosuggest_keydown)
194
- ;
195
-
196
- if(authorName)
197
- $co.attr( 'value', unescape( authorName ) );
198
- else
199
- $co.attr( 'value', coAuthorsPlusStrings.search_box_text )
200
- .focus( function(){ $co.val( '' ) } )
201
- .blur( function(){ $co.val( coAuthorsPlusStrings.search_box_text ) } )
202
- ;
203
-
204
- return $co;
205
-
206
- }
207
-
208
- // Callback for when a user selects an author
209
- function coauthors_autosuggest_select() {
210
- $this = jQuery(this);
211
- var vals = this.value.split("|");
212
-
213
- var author = {}
214
- author.id = jQuery.trim(vals[0]);
215
- author.login = jQuery.trim(vals[1]);
216
- author.name = jQuery.trim(vals[2]);
217
- author.email = jQuery.trim(vals[3]);
218
- author.nicename = jQuery.trim(vals[4]);
219
-
220
- if(author.id=="New") {
221
- //alert('Eventually, this will allow you to add a new author right from here. But it\'s not ready yet. *sigh*');
222
- coauthors_new_author_display(name);
223
- } else {
224
- //coauthors_add_coauthor(login, name, co);
225
- coauthors_add_coauthor(author, $this);
226
- // Show the delete button if we now have more than one co-author
227
- if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length > 1 )
228
- jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).removeClass('hidden');
229
- }
230
- }
231
-
232
- // Prevent the enter key from triggering a submit
233
- function coauthors_autosuggest_keydown(e) {
234
- if(e.keyCode == 13) {return false;}
235
- }
236
-
237
- /*
238
- * Blur handler for autosuggest input box
239
- * @param event
240
- */
241
- function coauthors_stop_editing(event) {
242
-
243
- var co = jQuery(this);
244
- var tag = jQuery(co.next());
245
-
246
- co.attr('value',tag.text());
247
-
248
- co.hide();
249
- tag.show();
250
-
251
- // editing = false;
252
- }
253
-
254
- /*
255
- * Creates the text tag for an author
256
- * @param string Name of the author
257
- */
258
- function coauthors_create_author_tag(author) {
259
-
260
- var $tag = jQuery('<span></span>')
261
- .html(unescape(author.name))
262
- .attr('title', coAuthorsPlusStrings.input_box_title)
263
- .addClass('coauthor-tag')
264
- // Add Click event to edit
265
- .click(coauthors_edit_onclick);
266
- return $tag;
267
- }
268
-
269
- function coauthors_create_author_gravatar(author, size) {
270
-
271
- var gravatar_link = get_gravatar_link(author.email, size);
272
-
273
- var $gravatar = jQuery('<img/>')
274
- .attr('alt', author.name)
275
- .attr('src', gravatar_link)
276
- .addClass('coauthor-gravatar')
277
- ;
278
- return $gravatar;
279
- }
280
-
281
- // MD5 (Message-Digest Algorithm) by WebToolkit -- needed for gravatars
282
- // http://www.webtoolkit.info/javascript-md5.html
283
- function MD5(s){function L(k,d){return(k<<d)|(k>>>(32-d))}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{return(x^1073741824^F^H)}}else{return(x^F^H)}}function r(d,F,k){return(d&F)|((~d)&k)}function q(d,F,k){return(d&k)|(F&(~k))}function p(d,F,k){return(d^F^k)}function n(d,F,k){return(F^(d|(~k)))}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F)}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F)}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F)}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F)}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H<F){Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++}Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-1]=F>>>29;return aa}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2)}return k}function J(k){k=k.replace(/\r\n/g,"\n");var d="";for(var F=0;F<k.length;F++){var x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x)}else{if((x>127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128)}}}return d}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g)}var i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase()};
284
-
285
- // Adapted from http://www.deluxeblogtips.com/2010/04/get-gravatar-using-only-javascript.html
286
- function get_gravatar_link(email, size) {
287
- var size = size || 80;
288
-
289
- // need to check if page is secure or not
290
- var gravatar_url = 'http://www.gravatar.com/avatar/';
291
- if ("https:" == document.location.protocol) {
292
- // secure
293
- gravatar_url = 'https://secure.gravatar.com/avatar/';
294
- }
295
- return gravatar_url + MD5(email) + '.jpg?s=' + size;
296
- }
297
-
298
- /*
299
- * Creates the text tag for an author
300
- * @param string Name of the author
301
- */
302
- function coauthors_create_author_hidden_input (author) {
303
- var input = jQuery('<input />')
304
- .attr({
305
- 'type': 'hidden',
306
- 'id': 'coauthors_hidden_input',
307
- 'name': 'coauthors[]',
308
- 'value': unescape(author.nicename)
309
- })
310
- ;
311
-
312
- return input;
313
- }
314
-
315
- /*
316
- * Creates display for adding new author
317
- * @param string Name of the author
318
- */
319
- /*
320
- function coauthors_new_author_create_display ( ) {
321
-
322
- var author_window = jQuery('<div></div>')
323
- .appendTo(jQuery('body'))
324
- .attr('id','new-author-window')
325
- .addClass('wrap')
326
- .append(
327
- jQuery('<div></div>')
328
- .addClass('icon32')
329
- .attr('id','icon-users')
330
- )
331
- .append(
332
- jQuery('<h2></h2>')
333
- .text('Add new author')
334
- .attr('id', 'add-new-user')
335
-
336
- )
337
- .append(
338
- jQuery('<div/>')
339
- .attr('id', 'createauthor-ajax-response')
340
- )
341
- ;
342
-
343
- var author_form = jQuery('<form />')
344
- .appendTo(author_window)
345
- .attr({
346
- id: 'createauthor',
347
- name: 'createauthor',
348
- method: 'post',
349
- action: ''
350
- })
351
- ;
352
-
353
-
354
-
355
- var create_text_field = function( name, id, label) {
356
-
357
- var field = jQuery('<input />')
358
- .attr({
359
- type:'text',
360
- name: name,
361
- id: id,
362
- })
363
- var label = jQuery('<label></label>')
364
- .attr('for',name)
365
- .text(label)
366
-
367
- //return {field, label};
368
-
369
- };
370
-
371
- create_field('user_login', 'user_login', 'User Name');
372
- create_field('first_name', 'first_name', 'First Name');
373
-
374
- //last_name
375
- //email
376
- //pass1
377
- //email password checkbox
378
- //role
379
- }
380
- */
381
-
382
- var $coauthors_div = null;
383
-
384
- /**
385
- * Initialize the Coauthors UI.
386
- *
387
- * @param array List of coauthors objects.
388
- * Each coauthor object should have the (string) properties:
389
- * login
390
- * email
391
- * name
392
- * nicename
393
- */
394
- function coauthors_initialize(post_coauthors) {
395
- // Add the controls to add co-authors
396
-
397
- $coauthors_div = jQuery('#coauthors-edit');
398
-
399
- if( $coauthors_div.length ) {
400
- // Create the co-authors table
401
- var table = jQuery('<div/>')
402
- .attr('id', 'coauthors-list')
403
- ;
404
- $coauthors_div.append(table);
405
- }
406
-
407
- // Select authors already added to the post
408
- var addedAlready = [];
409
- //jQuery('#the-list tr').each(function(){
410
- var count = 0;
411
- jQuery.each(post_coauthors, function() {
412
- coauthors_add_coauthor(this, undefined, true, count );
413
- count++;
414
- });
415
-
416
- // Hide the delete button if there's only one co-author
417
- if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length < 2 )
418
- jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).addClass('hidden');
419
-
420
-
421
- // Create new author-suggest and append it to a new row
422
- var newCO = coauthors_create_autosuggest('', false);
423
- coauthors_add_to_table(newCO);
424
-
425
- $coauthors_loading = jQuery('#ajax-loading').clone().attr('id', 'coauthors-loading');
426
- move_loading(newCO);
427
-
428
-
429
- // Make co-authors sortable so an editor can control the order of the authors
430
- jQuery('#coauthors-edit').ready(function($) {
431
- $( "#coauthors-list" ).sortable({
432
- axis: 'y',
433
- handle: '.coauthor-tag',
434
- placeholder: 'ui-state-highlight',
435
- items: 'div.coauthor-row:not(div.coauthor-row:last)',
436
- containment: 'parent',
437
- });
438
- });
439
-
440
- }
441
-
442
-
443
- function show_loading() {
444
- $coauthors_loading.css('visibility', 'visible');
445
- }
446
- function hide_loading() {
447
- $coauthors_loading.css('visibility', 'hidden');
448
- }
449
- function move_loading($input) {
450
- $coauthors_loading.insertAfter($input);
451
- }
452
- // Show laoding cursor for autocomplete ajax requests
453
- jQuery(document).ajaxSend(function(e, xhr, settings) {
454
- if( settings.url.indexOf(coAuthorsPlus_ajax_suggest_link) != -1 ) {
455
- // Including existing authors on the AJAX suggest link
456
- // allows us to filter them out of the search request
457
- var existing_authors = jQuery('input[name="coauthors[]"]').map(function(){return jQuery(this).val();}).get();
458
- settings.url = settings.url.split('&existing_authors')[0];
459
- settings.url += '&existing_authors=' + existing_authors.join(',');
460
- show_loading();
461
- }
462
- });
463
- // Hide laoding cursor when autocomplete ajax requests are finished
464
- jQuery(document).ajaxComplete(function(e, xhr, settings) {
465
- if( settings.url.indexOf(coAuthorsPlus_ajax_suggest_link) != -1 )
466
- hide_loading();
467
- });
468
-
469
- if ( 'post-php' == adminpage || 'post-new-php' == adminpage ) {
470
- var $post_coauthor_logins = jQuery('input[name="coauthors[]"]');
471
- var $post_coauthor_names = jQuery('input[name="coauthorsinput[]"]');
472
- var $post_coauthor_emails = jQuery('input[name="coauthorsemails[]"]');
473
- var $post_coauthor_nicenames = jQuery('input[name="coauthorsnicenames[]"]');
474
-
475
- var post_coauthors = [];
476
-
477
- for(var i = 0; i < $post_coauthor_logins.length; i++) {
478
- post_coauthors.push({
479
- login: $post_coauthor_logins[i].value,
480
- name: $post_coauthor_names[i].value,
481
- email: $post_coauthor_emails[i].value,
482
- nicename: $post_coauthor_nicenames[i].value
483
- });
484
- }
485
-
486
- // Remove the read-only coauthors so we don't get craziness
487
- jQuery('#coauthors-readonly').remove();
488
- coauthors_initialize(post_coauthors);
489
- }
490
- else if ( 'edit-php' == adminpage ) {
491
-
492
- var wpInlineEdit = inlineEditPost.edit;
493
-
494
- inlineEditPost.edit = function( id ) {
495
-
496
- wpInlineEdit.apply( this, arguments )
497
-
498
- // get the post ID
499
- var postId = 0
500
- if ( typeof( id ) == 'object' )
501
- postId = parseInt( this.getId( id ) )
502
-
503
- if ( postId > 0 ) {
504
-
505
- var $postRow = jQuery( '#post-' + postId )
506
-
507
- // Move the element to the appropriate position in the view
508
- // JS hack for core bug: https://core.trac.wordpress.org/ticket/26982
509
- jQuery('.quick-edit-row .inline-edit-col-left .inline-edit-col').find('.inline-edit-coauthors').remove() // remove any previously added elements
510
- var el = jQuery('.inline-edit-group.inline-edit-coauthors', '#edit-' + postId );
511
- el.detach().appendTo('.quick-edit-row .inline-edit-col-left .inline-edit-col').show();
512
-
513
- // initialize coauthors
514
- var post_coauthors = jQuery.map(jQuery('.column-coauthors a', $postRow), function(el) {
515
- return {
516
- login: jQuery(el).data('user_login'),
517
- name: jQuery(el).data('display_name'),
518
- email: jQuery(el).data('user_email'),
519
- nicename: jQuery(el).data('user_nicename')
520
- }
521
- })
522
- coauthors_initialize(post_coauthors);
523
-
524
- }
525
- }
526
- }
527
-
528
- });
529
-
530
- if( typeof(console) === 'undefined' ) {
531
- var console = {}
532
- console.log = console.error = function() {};
533
- }
1
+ jQuery( document ).ready(function () {
2
+
3
+ /*
4
+ * Click handler for the delete button
5
+ * @param event
6
+ */
7
+ var coauthors_delete_onclick = function( e ) {
8
+ if ( confirm( coAuthorsPlusStrings.confirm_delete ) ) {
9
+ return coauthors_delete( this );
10
+ }
11
+ return false;
12
+ };
13
+
14
+ var $coauthors_loading;
15
+
16
+ function coauthors_delete( elem ) {
17
+
18
+ var $coauthor_row = jQuery( elem ).closest( '.coauthor-row' );
19
+ $coauthor_row.remove();
20
+
21
+ // Hide the delete button when there's only one Co-Author
22
+ if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length <= 1 )
23
+ jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).addClass( 'hidden' );
24
+
25
+ return true;
26
+ }
27
+
28
+ var coauthors_edit_onclick = function( event ) {
29
+ var $tag = jQuery( this );
30
+
31
+ var $co = $tag.prev();
32
+
33
+ $tag.hide();
34
+ $co.show()
35
+ .focus()
36
+ ;
37
+
38
+ $co.previousAuthor = $tag.text();
39
+ }
40
+
41
+ /*
42
+ * Save coauthor
43
+ * @param int Author ID
44
+ * @param string Author Name
45
+ * @param object The autosuggest input box
46
+ */
47
+ function coauthors_save_coauthor( author, co ) {
48
+
49
+ // get sibling <span> and update
50
+ co.siblings( '.coauthor-tag' )
51
+ .html( author.name )
52
+ .append( coauthors_create_author_gravatar( author ) )
53
+ .show()
54
+ ;
55
+
56
+ // Update the value of the hidden input
57
+ co.siblings( 'input[name="coauthors[]"]' ).val( author.nicename );
58
+ }
59
+
60
+
61
+ /*
62
+ * Add coauthor
63
+ * @param string Author Name
64
+ * @param object The autosuggest input box
65
+ * @param boolean Initial set up or not?
66
+ */
67
+ function coauthors_add_coauthor( author, co, init, count ){
68
+
69
+ // Check if editing
70
+ if ( co && co.siblings( '.coauthor-tag' ).length ) {
71
+ coauthors_save_coauthor( author, co );
72
+ } else {
73
+ // Not editing, so we create a new author entry
74
+ if ( count == 0 ) {
75
+ var coName = ( count == 0 ) ? 'coauthors-main' : '';
76
+ // Add new author to <select>
77
+ //coauthors_select_author( author );
78
+ }
79
+ var options = { addDelete: true, addEdit: false };
80
+
81
+ // Create autosuggest box and text tag
82
+ if ( ! co ) var co = coauthors_create_autosuggest( author.name, coName )
83
+ var tag = coauthors_create_author_tag( author );
84
+ var input = coauthors_create_author_hidden_input( author );
85
+ var $gravatar = coauthors_create_author_gravatar( author, 25 );
86
+
87
+ tag.append( $gravatar );
88
+
89
+ coauthors_add_to_table( co, tag, input, options );
90
+
91
+ if ( ! init ) {
92
+ // Create new author-suggest and append it to a new row
93
+ var newCO = coauthors_create_autosuggest( '', false );
94
+ coauthors_add_to_table( newCO );
95
+ move_loading( newCO );
96
+ }
97
+ }
98
+
99
+ co.bind( 'blur', coauthors_stop_editing );
100
+
101
+ // Set the value for the auto-suggest box to the Author's name and hide it
102
+ co.val( unescape( author.name ) )
103
+ .hide()
104
+ .unbind( 'focus' )
105
+ ;
106
+
107
+ return true;
108
+ }
109
+
110
+
111
+ /*
112
+ * Add the autosuggest box and text tag to the Co-Authors table
113
+ * @param object Autosuggest input box
114
+ * @param object Text tag
115
+ * @param
116
+ */
117
+ function coauthors_add_to_table( co, tag, input, options ) {
118
+ if ( co ) {
119
+ var $div = jQuery( '<div/>' )
120
+ .addClass( 'suggest' )
121
+ .addClass( 'coauthor-row' )
122
+ .append( co )
123
+ .append( tag )
124
+ .append( input )
125
+ ;
126
+
127
+ //Add buttons to row
128
+ if ( tag ) coauthors_insert_author_edit_cells( $div, options );
129
+
130
+ jQuery( '#coauthors-list' ).append( $div );
131
+ }
132
+ }
133
+
134
+ /*
135
+ * Adds a delete and edit button next to an author
136
+ * @param object The row to which the new author should be added
137
+ */
138
+ function coauthors_insert_author_edit_cells( $div, options ){
139
+
140
+ var $options = jQuery( '<div/>' )
141
+ .addClass( 'coauthors-author-options' )
142
+ ;
143
+
144
+ if ( options.addDelete ) {
145
+ var deleteBtn = jQuery( '<span/>' )
146
+ .addClass( 'delete-coauthor' )
147
+ .text( coAuthorsPlusStrings.delete_label )
148
+ .bind( 'click', coauthors_delete_onclick )
149
+ ;
150
+ $options.append( deleteBtn );
151
+ }
152
+
153
+ $div.append( $options );
154
+ return $div;
155
+ }
156
+
157
+ /*
158
+ * Creates autosuggest input box
159
+ * @param string [optional] Name of the author
160
+ * @param string [optional] Name to be applied to the input box
161
+ */
162
+ function coauthors_create_autosuggest( authorName, inputName ) {
163
+
164
+ if ( ! inputName ) inputName = 'coauthorsinput[]';
165
+
166
+ var $co = jQuery( '<input/>' );
167
+
168
+ $co.attr({
169
+ 'class': 'coauthor-suggest'
170
+ , 'name': inputName
171
+ })
172
+ .appendTo( $coauthors_div )
173
+ .suggest( coAuthorsPlus_ajax_suggest_link, {
174
+ onSelect: coauthors_autosuggest_select,
175
+ delay: 1000
176
+ })
177
+ .keydown( coauthors_autosuggest_keydown )
178
+ ;
179
+
180
+ if ( authorName )
181
+ $co.attr( 'value', unescape( authorName ) );
182
+ else
183
+ $co.attr( 'value', coAuthorsPlusStrings.search_box_text )
184
+ .focus( function(){ $co.val( '' ) } )
185
+ .blur( function(){ $co.val( coAuthorsPlusStrings.search_box_text ) } )
186
+ ;
187
+
188
+ return $co;
189
+
190
+ }
191
+
192
+ // Callback for when a user selects an author
193
+ function coauthors_autosuggest_select() {
194
+ $this = jQuery( this );
195
+ var vals = this.value.split( '|' );
196
+
197
+ var author = {}
198
+ author.id = jQuery.trim( vals[0] );
199
+ author.login = jQuery.trim( vals[1] );
200
+ author.name = jQuery.trim( vals[2] );
201
+ author.email = jQuery.trim( vals[3] );
202
+ author.nicename = jQuery.trim( vals[4] );
203
+
204
+ if ( author.id=='New' ) {
205
+ coauthors_new_author_display( name );
206
+ } else {
207
+ coauthors_add_coauthor( author, $this );
208
+ // Show the delete button if we now have more than one co-author
209
+ if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length > 1 )
210
+ jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).removeClass( 'hidden' );
211
+ }
212
+ }
213
+
214
+ // Prevent the enter key from triggering a submit
215
+ function coauthors_autosuggest_keydown( e ) {
216
+ if ( e.keyCode == 13 ) {return false;}
217
+ }
218
+
219
+ /*
220
+ * Blur handler for autosuggest input box
221
+ * @param event
222
+ */
223
+ function coauthors_stop_editing( event ) {
224
+
225
+ var co = jQuery( this );
226
+ var tag = jQuery( co.next() );
227
+
228
+ co.attr( 'value',tag.text() );
229
+
230
+ co.hide();
231
+ tag.show();
232
+
233
+ // editing = false;
234
+ }
235
+
236
+ /*
237
+ * Creates the text tag for an author
238
+ * @param string Name of the author
239
+ */
240
+ function coauthors_create_author_tag( author ) {
241
+
242
+ var $tag = jQuery( '<span></span>' )
243
+ .html( unescape( author.name ) )
244
+ .attr( 'title', coAuthorsPlusStrings.input_box_title )
245
+ .addClass( 'coauthor-tag' )
246
+ // Add Click event to edit
247
+ .click( coauthors_edit_onclick );
248
+ return $tag;
249
+ }
250
+
251
+ function coauthors_create_author_gravatar( author, size ) {
252
+
253
+ var gravatar_link = get_gravatar_link( author.email, size );
254
+
255
+ var $gravatar = jQuery( '<img/>' )
256
+ .attr( 'alt', author.name )
257
+ .attr( 'src', gravatar_link )
258
+ .addClass( 'coauthor-gravatar' )
259
+ ;
260
+ return $gravatar;
261
+ }
262
+
263
+ // MD5 (Message-Digest Algorithm) by WebToolkit -- needed for gravatars
264
+ // http://www.webtoolkit.info/javascript-md5.html
265
+ function MD5(s){function L(k,d){return(k<<d)|(k>>>(32-d))}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{return(x^1073741824^F^H)}}else{return(x^F^H)}}function r(d,F,k){return(d&F)|((~d)&k)}function q(d,F,k){return(d&k)|(F&(~k))}function p(d,F,k){return(d^F^k)}function n(d,F,k){return(F^(d|(~k)))}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F)}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F)}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F)}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F)}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H<F){Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++}Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-1]=F>>>29;return aa}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2)}return k}function J(k){k=k.replace(/\r\n/g,"\n");var d="";for(var F=0;F<k.length;F++){var x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x)}else{if((x>127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128)}}}return d}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g)}var i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase()};
266
+
267
+ // Adapted from http://www.deluxeblogtips.com/2010/04/get-gravatar-using-only-javascript.html
268
+ function get_gravatar_link( email, size ) {
269
+ var size = size || 80;
270
+
271
+ // need to check if page is secure or not
272
+ var gravatar_url = 'http://www.gravatar.com/avatar/';
273
+ if ( 'https:' == document.location.protocol ) {
274
+ // secure
275
+ gravatar_url = 'https://secure.gravatar.com/avatar/';
276
+ }
277
+ return gravatar_url + MD5( email ) + '.jpg?s=' + size;
278
+ }
279
+
280
+ /*
281
+ * Creates the text tag for an author
282
+ * @param string Name of the author
283
+ */
284
+ function coauthors_create_author_hidden_input ( author ) {
285
+ var input = jQuery( '<input />' )
286
+ .attr({
287
+ 'type': 'hidden',
288
+ 'id': 'coauthors_hidden_input',
289
+ 'name': 'coauthors[]',
290
+ 'value': unescape( author.nicename )
291
+ })
292
+ ;
293
+
294
+ return input;
295
+ }
296
+
297
+ var $coauthors_div = null;
298
+
299
+ /**
300
+ * Initialize the Coauthors UI.
301
+ *
302
+ * @param array List of coauthors objects.
303
+ * Each coauthor object should have the (string) properties:
304
+ * login
305
+ * email
306
+ * name
307
+ * nicename
308
+ */
309
+ function coauthors_initialize( post_coauthors ) {
310
+ // Add the controls to add co-authors
311
+
312
+ $coauthors_div = jQuery( '#coauthors-edit' );
313
+
314
+ if ( $coauthors_div.length ) {
315
+ // Create the co-authors table
316
+ var table = jQuery( '<div/>' )
317
+ .attr( 'id', 'coauthors-list' )
318
+ ;
319
+ $coauthors_div.append( table );
320
+ }
321
+
322
+ // Select authors already added to the post
323
+ var addedAlready = [];
324
+ //jQuery('#the-list tr').each(function(){
325
+ var count = 0;
326
+ jQuery.each( post_coauthors, function() {
327
+ coauthors_add_coauthor( this, undefined, true, count );
328
+ count++;
329
+ });
330
+
331
+ // Hide the delete button if there's only one co-author
332
+ if ( jQuery( '#coauthors-list .coauthor-row .coauthor-tag' ).length < 2 )
333
+ jQuery( '#coauthors-list .coauthor-row .coauthors-author-options' ).addClass( 'hidden' );
334
+
335
+
336
+ // Create new author-suggest and append it to a new row
337
+ var newCO = coauthors_create_autosuggest( '', false );
338
+ coauthors_add_to_table( newCO );
339
+
340
+ $coauthors_loading = jQuery( '#ajax-loading' ).clone().attr( 'id', 'coauthors-loading' );
341
+ move_loading( newCO );
342
+
343
+
344
+ // Make co-authors sortable so an editor can control the order of the authors
345
+ jQuery( '#coauthors-edit' ).ready(function( $ ) {
346
+ $( '#coauthors-list' ).sortable({
347
+ axis: 'y',
348
+ handle: '.coauthor-tag',
349
+ placeholder: 'ui-state-highlight',
350
+ items: 'div.coauthor-row:not(div.coauthor-row:last)',
351
+ containment: 'parent',
352
+ });
353
+ });
354
+
355
+ }
356
+
357
+
358
+ function show_loading() {
359
+ $coauthors_loading.css( 'visibility', 'visible' );
360
+ }
361
+ function hide_loading() {
362
+ $coauthors_loading.css( 'visibility', 'hidden' );
363
+ }
364
+ function move_loading( $input ) {
365
+ $coauthors_loading.insertAfter( $input );
366
+ }
367
+ // Show laoding cursor for autocomplete ajax requests
368
+ jQuery( document ).ajaxSend(function( e, xhr, settings ) {
369
+ if ( settings.url.indexOf( coAuthorsPlus_ajax_suggest_link ) != -1 ) {
370
+ // Including existing authors on the AJAX suggest link
371
+ // allows us to filter them out of the search request
372
+ var existing_authors = jQuery( 'input[name="coauthors[]"]' ).map(function(){return jQuery( this ).val();}).get();
373
+ settings.url = settings.url.split( '&existing_authors' )[0];
374
+ settings.url += '&existing_authors=' + existing_authors.join( ',' );
375
+ show_loading();
376
+ }
377
+ });
378
+ // Hide laoding cursor when autocomplete ajax requests are finished
379
+ jQuery( document ).ajaxComplete(function( e, xhr, settings ) {
380
+ if ( settings.url.indexOf( coAuthorsPlus_ajax_suggest_link ) != -1 )
381
+ hide_loading();
382
+ });
383
+
384
+ if ( 'post-php' == adminpage || 'post-new-php' == adminpage ) {
385
+ var $post_coauthor_logins = jQuery( 'input[name="coauthors[]"]' );
386
+ var $post_coauthor_names = jQuery( 'input[name="coauthorsinput[]"]' );
387
+ var $post_coauthor_emails = jQuery( 'input[name="coauthorsemails[]"]' );
388
+ var $post_coauthor_nicenames = jQuery( 'input[name="coauthorsnicenames[]"]' );
389
+
390
+ var post_coauthors = [];
391
+
392
+ for ( var i = 0; i < $post_coauthor_logins.length; i++ ) {
393
+ post_coauthors.push({
394
+ login: $post_coauthor_logins[i].value,
395
+ name: $post_coauthor_names[i].value,
396
+ email: $post_coauthor_emails[i].value,
397
+ nicename: $post_coauthor_nicenames[i].value
398
+ });
399
+ }
400
+
401
+ // Remove the read-only coauthors so we don't get craziness
402
+ jQuery( '#coauthors-readonly' ).remove();
403
+ coauthors_initialize( post_coauthors );
404
+ }
405
+ else if ( 'edit-php' == adminpage ) {
406
+
407
+ var wpInlineEdit = inlineEditPost.edit;
408
+
409
+ inlineEditPost.edit = function( id ) {
410
+
411
+ wpInlineEdit.apply( this, arguments )
412
+
413
+ // get the post ID
414
+ var postId = 0
415
+ if ( typeof( id ) == 'object' )
416
+ postId = parseInt( this.getId( id ) )
417
+
418
+ if ( postId > 0 ) {
419
+
420
+ var $postRow = jQuery( '#post-' + postId )
421
+
422
+ // Move the element to the appropriate position in the view
423
+ // JS hack for core bug: https://core.trac.wordpress.org/ticket/26982
424
+ jQuery( '.quick-edit-row .inline-edit-col-left .inline-edit-col' ).find( '.inline-edit-coauthors' ).remove() // remove any previously added elements
425
+ var el = jQuery( '.inline-edit-group.inline-edit-coauthors', '#edit-' + postId );
426
+ el.detach().appendTo( '.quick-edit-row .inline-edit-col-left .inline-edit-col' ).show();
427
+
428
+ // initialize coauthors
429
+ var post_coauthors = jQuery.map( jQuery( '.column-coauthors a', $postRow ), function( el ) {
430
+ return {
431
+ login: jQuery( el ).data( 'user_login' ),
432
+ name: jQuery( el ).data( 'display_name' ),
433
+ email: jQuery( el ).data( 'user_email' ),
434
+ nicename: jQuery( el ).data( 'user_nicename' )
435
+ }
436
+ })
437
+ coauthors_initialize( post_coauthors );
438
+
439
+ }
440
+ }
441
+ }
442
+
443
+ });
444
+
445
+ if ( typeof( console ) === 'undefined' ) {
446
+ var console = {}
447
+ console.log = console.error = function() {};
448
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/guest-authors.js CHANGED
@@ -1,8 +1,8 @@
1
- jQuery(document).ready(function($){
2
- $('.reassign-option').on('click',function(){
3
- $('#wpbody-content input#submit').addClass('button-primary').removeAttr('disabled');
4
  });
5
- $('#leave-assigned-to').select2({
6
  minimumInputLength: 2,
7
  width: 'copy',
8
  multiple: false,
@@ -13,7 +13,7 @@ jQuery(document).ready(function($){
13
  return {
14
  q: term,
15
  action: 'search_coauthors_to_assign',
16
- guest_author: $('#id').val()
17
  };
18
  },
19
  results: function( data, page ) {
@@ -26,7 +26,7 @@ jQuery(document).ready(function($){
26
  formatSelection: function( object, container ) {
27
  return object.display_name;
28
  }
29
- }).on('change', function() {
30
- $('#reassign-another').trigger('click');
31
  });
32
  });
1
+ jQuery( document ).ready(function( $ ){
2
+ $( '.reassign-option' ).on( 'click',function(){
3
+ $( '#wpbody-content input#submit' ).addClass( 'button-primary' ).removeAttr( 'disabled' );
4
  });
5
+ $( '#leave-assigned-to' ).select2({
6
  minimumInputLength: 2,
7
  width: 'copy',
8
  multiple: false,
13
  return {
14
  q: term,
15
  action: 'search_coauthors_to_assign',
16
+ guest_author: $( '#id' ).val()
17
  };
18
  },
19
  results: function( data, page ) {
26
  formatSelection: function( object, container ) {
27
  return object.display_name;
28
  }
29
+ }).on( 'change', function() {
30
+ $( '#reassign-another' ).trigger( 'click' );
31
  });
32
  });
languages/co-authors-plus-de_DE.po CHANGED
@@ -473,7 +473,7 @@ msgstr "ID"
473
 
474
  #: template-tags.php:136
475
  msgid " and "
476
- msgstr "und"
477
 
478
  #: co-authors-plus.php:342
479
  msgid "<strong>Note:</strong> To edit post authors, please enable javascript or use a javascript-capable browser"
@@ -534,4 +534,4 @@ msgid "http://wordpress.org/extend/plugins/co-authors-plus/"
534
  msgstr "http://wordpress.org/extend/plugins/co-authors-plus/"
535
 
536
  msgid "Allows multiple authors to be assigned to a post. This plugin is an extended version of the Co-Authors plugin developed by Weston Ruter."
537
- msgstr "Erlaubt es mehrere Autoren einem Artikel zuzuweisen. Dieses Plugin ist eine erweiterte Version des Co-Authors Plugins, dass von Weston Ruter entwickelt wurde."
473
 
474
  #: template-tags.php:136
475
  msgid " and "
476
+ msgstr " und "
477
 
478
  #: co-authors-plus.php:342
479
  msgid "<strong>Note:</strong> To edit post authors, please enable javascript or use a javascript-capable browser"
534
  msgstr "http://wordpress.org/extend/plugins/co-authors-plus/"
535
 
536
  msgid "Allows multiple authors to be assigned to a post. This plugin is an extended version of the Co-Authors plugin developed by Weston Ruter."
537
+ msgstr "Erlaubt es mehrere Autoren einem Artikel zuzuweisen. Dieses Plugin ist eine erweiterte Version des Co-Authors Plugins, dass von Weston Ruter entwickelt wurde."
languages/co-authors-plus-ru_RU.mo ADDED
Binary file
languages/co-authors-plus-ru_RU.po ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2012 Co-Authors Plus
2
+ # This file is distributed under the same license as the Co-Authors Plus package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Co-Authors Plus\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/co-authors-plus\n"
7
+ "POT-Creation-Date: 2014-03-17 15:59:18+00:00\n"
8
+ "PO-Revision-Date: 2014-03-30 19:31+0200\n"
9
+ "Last-Translator: Jurko Chervony <info@skinik.name>\n"
10
+ "Language-Team: skinik <info@skinik.name>\n"
11
+ "Language: ru_RU\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Poedit 1.6.4\n"
16
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
17
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
18
+ "X-Poedit-SourceCharset: UTF-8\n"
19
+
20
+ #: co-authors-plus.php:300 co-authors-plus.php:401 co-authors-plus.php:487
21
+ #: co-authors-plus.php:1290
22
+ msgid "Authors"
23
+ msgstr "Авторы"
24
+
25
+ #: co-authors-plus.php:362
26
+ msgid ""
27
+ "<strong>Note:</strong> To edit post authors, please enable javascript or use "
28
+ "a javascript-capable browser"
29
+ msgstr ""
30
+
31
+ #: co-authors-plus.php:369 co-authors-plus.php:489 co-authors-plus.php:1095
32
+ msgid ""
33
+ "Click on an author to change them. Drag to change their order. Click on "
34
+ "<strong>Remove</strong> to remove them."
35
+ msgstr ""
36
+
37
+ #: co-authors-plus.php:449 php/class-coauthors-wp-list-table.php:148
38
+ msgid "Posts"
39
+ msgstr "Записи"
40
+
41
+ #: co-authors-plus.php:466
42
+ msgid "View posts by this author"
43
+ msgstr "Просмотреть все материалы автора"
44
+
45
+ #: co-authors-plus.php:531 co-authors-plus.php:548
46
+ msgid "No co-author exists for that term"
47
+ msgstr ""
48
+
49
+ #: co-authors-plus.php:1090 php/class-coauthors-wp-list-table.php:212
50
+ msgid "Edit"
51
+ msgstr "Редактировать"
52
+
53
+ #: co-authors-plus.php:1091
54
+ msgid "Remove"
55
+ msgstr "Удалить"
56
+
57
+ #: co-authors-plus.php:1092
58
+ msgid "Are you sure you want to remove this author?"
59
+ msgstr ""
60
+
61
+ #: co-authors-plus.php:1093
62
+ msgid "Click to change this author, or drag to change their position"
63
+ msgstr ""
64
+
65
+ #: co-authors-plus.php:1094
66
+ msgid "Search for an author"
67
+ msgstr "Искать автора"
68
+
69
+ #: co-authors-plus.php:1132
70
+ msgid "Mine"
71
+ msgstr ""
72
+
73
+ #: co-authors-plus.php:1402
74
+ msgid "New comment on your post \"%s\""
75
+ msgstr ""
76
+
77
+ #. translators: 1: comment author, 2: author IP, 3: author domain
78
+ #: co-authors-plus.php:1404 co-authors-plus.php:1521
79
+ msgid "Author : %1$s (IP: %2$s , %3$s)"
80
+ msgstr ""
81
+
82
+ #: co-authors-plus.php:1405 co-authors-plus.php:1522
83
+ msgid "E-mail : %s"
84
+ msgstr ""
85
+
86
+ #: co-authors-plus.php:1406 co-authors-plus.php:1416 co-authors-plus.php:1425
87
+ #: co-authors-plus.php:1508 co-authors-plus.php:1515 co-authors-plus.php:1523
88
+ msgid "URL : %s"
89
+ msgstr ""
90
+
91
+ #: co-authors-plus.php:1407 co-authors-plus.php:1524
92
+ msgid "Whois : http://whois.arin.net/rest/ip/%s"
93
+ msgstr ""
94
+
95
+ #: co-authors-plus.php:1408 co-authors-plus.php:1525
96
+ msgid "Comment: "
97
+ msgstr "Комментарий:"
98
+
99
+ #: co-authors-plus.php:1409
100
+ msgid "You can see all comments on this post here: "
101
+ msgstr ""
102
+
103
+ #. translators: 1: blog name, 2: post title
104
+ #: co-authors-plus.php:1411
105
+ msgid "[%1$s] Comment: \"%2$s\""
106
+ msgstr ""
107
+
108
+ #: co-authors-plus.php:1413
109
+ msgid "New trackback on your post \"%s\""
110
+ msgstr ""
111
+
112
+ #. translators: 1: website name, 2: author IP, 3: author domain
113
+ #. translators: 1: comment author, 2: author IP, 3: author domain
114
+ #: co-authors-plus.php:1415 co-authors-plus.php:1424
115
+ msgid "Website: %1$s (IP: %2$s , %3$s)"
116
+ msgstr ""
117
+
118
+ #: co-authors-plus.php:1417 co-authors-plus.php:1426
119
+ msgid "Excerpt: "
120
+ msgstr ""
121
+
122
+ #: co-authors-plus.php:1418
123
+ msgid "You can see all trackbacks on this post here: "
124
+ msgstr ""
125
+
126
+ #. translators: 1: blog name, 2: post title
127
+ #: co-authors-plus.php:1420
128
+ msgid "[%1$s] Trackback: \"%2$s\""
129
+ msgstr ""
130
+
131
+ #: co-authors-plus.php:1422
132
+ msgid "New pingback on your post \"%s\""
133
+ msgstr ""
134
+
135
+ #: co-authors-plus.php:1427
136
+ msgid "You can see all pingbacks on this post here: "
137
+ msgstr ""
138
+
139
+ #. translators: 1: blog name, 2: post title
140
+ #: co-authors-plus.php:1429
141
+ msgid "[%1$s] Pingback: \"%2$s\""
142
+ msgstr ""
143
+
144
+ #: co-authors-plus.php:1432
145
+ msgid "Permalink: %s"
146
+ msgstr ""
147
+
148
+ #: co-authors-plus.php:1434 co-authors-plus.php:1531
149
+ msgid "Trash it: %s"
150
+ msgstr ""
151
+
152
+ #: co-authors-plus.php:1436 co-authors-plus.php:1533
153
+ msgid "Delete it: %s"
154
+ msgstr ""
155
+
156
+ #: co-authors-plus.php:1437 co-authors-plus.php:1534
157
+ msgid "Spam it: %s"
158
+ msgstr ""
159
+
160
+ #: co-authors-plus.php:1505
161
+ msgid "A new trackback on the post \"%s\" is waiting for your approval"
162
+ msgstr ""
163
+
164
+ #: co-authors-plus.php:1507 co-authors-plus.php:1514
165
+ msgid "Website : %1$s (IP: %2$s , %3$s)"
166
+ msgstr ""
167
+
168
+ #: co-authors-plus.php:1509
169
+ msgid "Trackback excerpt: "
170
+ msgstr ""
171
+
172
+ #: co-authors-plus.php:1512
173
+ msgid "A new pingback on the post \"%s\" is waiting for your approval"
174
+ msgstr ""
175
+
176
+ #: co-authors-plus.php:1516
177
+ msgid "Pingback excerpt: "
178
+ msgstr ""
179
+
180
+ #: co-authors-plus.php:1519
181
+ msgid "A new comment on the post \"%s\" is waiting for your approval"
182
+ msgstr ""
183
+
184
+ #: co-authors-plus.php:1529
185
+ msgid "Approve it: %s"
186
+ msgstr ""
187
+
188
+ #: co-authors-plus.php:1536
189
+ msgid ""
190
+ "Currently %s comment is waiting for approval. Please visit the moderation "
191
+ "panel:"
192
+ msgid_plural ""
193
+ "Currently %s comments are waiting for approval. Please visit the moderation "
194
+ "panel:"
195
+ msgstr[0] ""
196
+ msgstr[1] ""
197
+
198
+ #: co-authors-plus.php:1540
199
+ msgid "[%1$s] Please moderate: \"%2$s\""
200
+ msgstr ""
201
+
202
+ #: php/class-coauthors-guest-authors.php:80
203
+ msgid "Guest Author"
204
+ msgstr ""
205
+
206
+ #: php/class-coauthors-guest-authors.php:81
207
+ msgid "Guest Authors"
208
+ msgstr ""
209
+
210
+ #: php/class-coauthors-guest-authors.php:82
211
+ msgid "All Guest Authors"
212
+ msgstr ""
213
+
214
+ #: php/class-coauthors-guest-authors.php:83
215
+ msgid "Add New Guest Author"
216
+ msgstr ""
217
+
218
+ #: php/class-coauthors-guest-authors.php:84
219
+ msgid "Edit Guest Author"
220
+ msgstr ""
221
+
222
+ #: php/class-coauthors-guest-authors.php:85
223
+ msgid "New Guest Author"
224
+ msgstr ""
225
+
226
+ #: php/class-coauthors-guest-authors.php:86
227
+ msgid "View Guest Author"
228
+ msgstr ""
229
+
230
+ #: php/class-coauthors-guest-authors.php:87
231
+ msgid "Search Guest Authors"
232
+ msgstr ""
233
+
234
+ #: php/class-coauthors-guest-authors.php:88
235
+ msgid "No guest authors found"
236
+ msgstr ""
237
+
238
+ #: php/class-coauthors-guest-authors.php:89
239
+ msgid "No guest authors found in Trash"
240
+ msgstr ""
241
+
242
+ #: php/class-coauthors-guest-authors.php:90
243
+ msgid "Update Guest Author"
244
+ msgstr ""
245
+
246
+ #: php/class-coauthors-guest-authors.php:91
247
+ msgid "About the guest author"
248
+ msgstr ""
249
+
250
+ #: php/class-coauthors-guest-authors.php:100
251
+ msgctxt "guest author"
252
+ msgid "Add New"
253
+ msgstr ""
254
+
255
+ #: php/class-coauthors-guest-authors.php:156
256
+ #: php/class-coauthors-guest-authors.php:162
257
+ msgid "Guest author updated. <a href=\"%s\">View profile</a>"
258
+ msgstr ""
259
+
260
+ #: php/class-coauthors-guest-authors.php:157
261
+ msgid "Custom field updated."
262
+ msgstr ""
263
+
264
+ #: php/class-coauthors-guest-authors.php:158
265
+ msgid "Custom field deleted."
266
+ msgstr ""
267
+
268
+ #: php/class-coauthors-guest-authors.php:159
269
+ msgid "Guest author updated."
270
+ msgstr ""
271
+
272
+ #. translators: %s: date and time of the revision
273
+ #: php/class-coauthors-guest-authors.php:161
274
+ msgid "Guest author restored to revision from %s"
275
+ msgstr ""
276
+
277
+ #: php/class-coauthors-guest-authors.php:163
278
+ msgid "Guest author saved."
279
+ msgstr ""
280
+
281
+ #: php/class-coauthors-guest-authors.php:164
282
+ msgid ""
283
+ "Guest author submitted. <a target=\"_blank\" href=\"%s\">Preview profile</a>"
284
+ msgstr ""
285
+
286
+ #: php/class-coauthors-guest-authors.php:165
287
+ msgid ""
288
+ "Guest author scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
289
+ "\"%2$s\">Preview profile</a>"
290
+ msgstr ""
291
+
292
+ #. translators: Publish box date format, see http:php.net/date
293
+ #: php/class-coauthors-guest-authors.php:167
294
+ msgid "M j, Y @ G:i"
295
+ msgstr ""
296
+
297
+ #: php/class-coauthors-guest-authors.php:168
298
+ msgid ""
299
+ "Guest author updated. <a target=\"_blank\" href=\"%s\">Preview profile</a>"
300
+ msgstr ""
301
+
302
+ #: php/class-coauthors-guest-authors.php:185
303
+ #: php/class-coauthors-guest-authors.php:218
304
+ #: php/class-coauthors-guest-authors.php:437
305
+ msgid "Doin' something fishy, huh?"
306
+ msgstr ""
307
+
308
+ #: php/class-coauthors-guest-authors.php:188
309
+ #: php/class-coauthors-guest-authors.php:222
310
+ msgid "You don't have permission to perform this action."
311
+ msgstr ""
312
+
313
+ #: php/class-coauthors-guest-authors.php:227
314
+ #: php/class-coauthors-guest-authors.php:442
315
+ msgid "Guest author can't be deleted because it doesn't exist."
316
+ msgstr ""
317
+
318
+ #: php/class-coauthors-guest-authors.php:241
319
+ msgid "Co-author does not exists. Try again?"
320
+ msgstr ""
321
+
322
+ #: php/class-coauthors-guest-authors.php:249
323
+ msgid "Please make sure to pick an option."
324
+ msgstr ""
325
+
326
+ #: php/class-coauthors-guest-authors.php:393
327
+ msgid "Guest author deleted."
328
+ msgstr ""
329
+
330
+ #: php/class-coauthors-guest-authors.php:417
331
+ msgid "Save"
332
+ msgstr "Сохранить"
333
+
334
+ #: php/class-coauthors-guest-authors.php:418
335
+ msgid "Unique Slug"
336
+ msgstr ""
337
+
338
+ #: php/class-coauthors-guest-authors.php:420
339
+ msgid "Name"
340
+ msgstr ""
341
+
342
+ #: php/class-coauthors-guest-authors.php:421
343
+ msgid "Contact Info"
344
+ msgstr ""
345
+
346
+ #: php/class-coauthors-guest-authors.php:446
347
+ msgid "Delete %s"
348
+ msgstr "Удалить %s"
349
+
350
+ #: php/class-coauthors-guest-authors.php:447
351
+ msgid "You have specified this guest author for deletion:"
352
+ msgstr ""
353
+
354
+ #: php/class-coauthors-guest-authors.php:449
355
+ msgid "What should be done with posts assigned to this guest author?"
356
+ msgstr ""
357
+
358
+ #: php/class-coauthors-guest-authors.php:450
359
+ msgid ""
360
+ "Note: If you'd like to delete the guest author and all of their posts, you "
361
+ "should delete their posts first and then come back to delete the guest "
362
+ "author."
363
+ msgstr ""
364
+
365
+ #: php/class-coauthors-guest-authors.php:459
366
+ msgid "Reassign to another co-author:"
367
+ msgstr ""
368
+
369
+ #: php/class-coauthors-guest-authors.php:465
370
+ msgid "Leave posts assigned to the mapped user, %s."
371
+ msgstr ""
372
+
373
+ #: php/class-coauthors-guest-authors.php:470
374
+ msgid "Remove byline from posts (but leave each post in its current status)."
375
+ msgstr ""
376
+
377
+ #: php/class-coauthors-guest-authors.php:473
378
+ msgid "Confirm Deletion"
379
+ msgstr ""
380
+
381
+ #: php/class-coauthors-guest-authors.php:482
382
+ msgid "Add New"
383
+ msgstr "Добавить нового"
384
+
385
+ #: php/class-coauthors-guest-authors.php:543
386
+ msgid "WordPress User Mapping"
387
+ msgstr ""
388
+
389
+ #: php/class-coauthors-guest-authors.php:545
390
+ msgid "-- Not mapped --"
391
+ msgstr ""
392
+
393
+ #: php/class-coauthors-guest-authors.php:679
394
+ #: php/class-coauthors-guest-authors.php:688
395
+ msgid "Guest authors cannot be created without display names."
396
+ msgstr ""
397
+
398
+ #: php/class-coauthors-guest-authors.php:697
399
+ msgid ""
400
+ "Guest authors cannot be created with the same user_login value as a user. "
401
+ "Try creating a profile from the user on the Manage Users listing instead."
402
+ msgstr ""
403
+
404
+ #: php/class-coauthors-guest-authors.php:702
405
+ msgid "Display name conflicts with another guest author display name."
406
+ msgstr ""
407
+
408
+ #: php/class-coauthors-guest-authors.php:896
409
+ msgid "ID"
410
+ msgstr ""
411
+
412
+ #: php/class-coauthors-guest-authors.php:903
413
+ #: php/class-coauthors-wp-list-table.php:143
414
+ msgid "Display Name"
415
+ msgstr ""
416
+
417
+ #: php/class-coauthors-guest-authors.php:909
418
+ #: php/class-coauthors-wp-list-table.php:144
419
+ msgid "First Name"
420
+ msgstr "Имя"
421
+
422
+ #: php/class-coauthors-guest-authors.php:914
423
+ #: php/class-coauthors-wp-list-table.php:145
424
+ msgid "Last Name"
425
+ msgstr "Фамилия"
426
+
427
+ #: php/class-coauthors-guest-authors.php:919
428
+ msgid "Slug"
429
+ msgstr ""
430
+
431
+ #: php/class-coauthors-guest-authors.php:926
432
+ #: php/class-coauthors-wp-list-table.php:146
433
+ msgid "E-mail"
434
+ msgstr ""
435
+
436
+ #: php/class-coauthors-guest-authors.php:932
437
+ #: php/class-coauthors-wp-list-table.php:147
438
+ msgid "Linked Account"
439
+ msgstr ""
440
+
441
+ #: php/class-coauthors-guest-authors.php:937
442
+ msgid "Website"
443
+ msgstr ""
444
+
445
+ #: php/class-coauthors-guest-authors.php:943
446
+ msgid "AIM"
447
+ msgstr ""
448
+
449
+ #: php/class-coauthors-guest-authors.php:948
450
+ msgid "Yahoo IM"
451
+ msgstr ""
452
+
453
+ #: php/class-coauthors-guest-authors.php:953
454
+ msgid "Jabber / Google Talk"
455
+ msgstr ""
456
+
457
+ #: php/class-coauthors-guest-authors.php:958
458
+ msgid "Biographical Info"
459
+ msgstr ""
460
+
461
+ #: php/class-coauthors-guest-authors.php:1122
462
+ msgid "%s is a required field"
463
+ msgstr ""
464
+
465
+ #: php/class-coauthors-guest-authors.php:1128
466
+ msgid "user_login cannot duplicate existing guest author or mapped user"
467
+ msgstr ""
468
+
469
+ #: php/class-coauthors-guest-authors.php:1173
470
+ msgid "Guest author does not exist"
471
+ msgstr ""
472
+
473
+ #: php/class-coauthors-guest-authors.php:1185
474
+ msgid "Reassignment co-author does not exist"
475
+ msgstr ""
476
+
477
+ #: php/class-coauthors-guest-authors.php:1217
478
+ msgid "No user exists with that ID"
479
+ msgstr ""
480
+
481
+ #: php/class-coauthors-guest-authors.php:1275
482
+ msgid "Edit Profile"
483
+ msgstr "Редактировать профиль"
484
+
485
+ #: php/class-coauthors-guest-authors.php:1284
486
+ msgid "Create Profile"
487
+ msgstr ""
488
+
489
+ #: php/class-coauthors-wp-list-table.php:19
490
+ msgid "Co-Authors"
491
+ msgstr ""
492
+
493
+ #: php/class-coauthors-wp-list-table.php:20
494
+ msgid "Co-Author"
495
+ msgstr ""
496
+
497
+ #: php/class-coauthors-wp-list-table.php:81
498
+ msgid "Show all"
499
+ msgstr ""
500
+
501
+ #: php/class-coauthors-wp-list-table.php:82
502
+ msgid "With linked account"
503
+ msgstr ""
504
+
505
+ #: php/class-coauthors-wp-list-table.php:83
506
+ msgid "Without linked account"
507
+ msgstr ""
508
+
509
+ #: php/class-coauthors-wp-list-table.php:135
510
+ msgid "No matching guest authors were found."
511
+ msgstr ""
512
+
513
+ #: php/class-coauthors-wp-list-table.php:215
514
+ msgid "Delete"
515
+ msgstr "Удалить"
516
+
517
+ #: php/class-coauthors-wp-list-table.php:217
518
+ msgid "View Posts"
519
+ msgstr ""
520
+
521
+ #: php/class-coauthors-wp-list-table.php:267
522
+ msgid "Filter"
523
+ msgstr ""
524
+
525
+ #: php/class-wp-cli.php:220
526
+ msgid "Please specify a valid user_login"
527
+ msgstr ""
528
+
529
+ #: php/class-wp-cli.php:223
530
+ msgid "Please specify a valid co-author login"
531
+ msgstr ""
532
+
533
+ #: php/class-wp-cli.php:230
534
+ msgid "Skipping - Post #%d already has co-authors assigned: %s"
535
+ msgstr ""
536
+
537
+ #: php/class-wp-cli.php:235
538
+ msgid "Updating - Adding %s's byline to post #%d"
539
+ msgstr ""
540
+
541
+ #: php/class-wp-cli.php:240
542
+ msgid "All done! %d posts were affected."
543
+ msgstr ""
544
+
545
+ #: template-tags.php:79
546
+ msgid ""
547
+ "No post ID provided for CoAuthorsIterator constructor. Are you not in a loop "
548
+ "or is $post not set?"
549
+ msgstr ""
550
+
551
+ #: template-tags.php:133
552
+ msgid " and "
553
+ msgstr " и "
554
+
555
+ #: template-tags.php:233 template-tags.php:468
556
+ msgid "Posts by %s"
557
+ msgstr "Материалы автора %s"
558
+
559
+ #: template-tags.php:350
560
+ msgid "Visit %s&#8217;s website"
561
+ msgstr ""
562
+
563
+ #. Plugin Name of the plugin/theme
564
+ msgid "Co-Authors Plus"
565
+ msgstr ""
566
+
567
+ #. Plugin URI of the plugin/theme
568
+ msgid "http://wordpress.org/extend/plugins/co-authors-plus/"
569
+ msgstr ""
570
+
571
+ #. Description of the plugin/theme
572
+ msgid ""
573
+ "Allows multiple authors to be assigned to a post. This plugin is an extended "
574
+ "version of the Co-Authors plugin developed by Weston Ruter."
575
+ msgstr ""
576
+
577
+ #. Author of the plugin/theme
578
+ msgid "Mohammad Jangda, Daniel Bachhuber, Automattic"
579
+ msgstr ""
languages/co-authors-plus-uk.mo ADDED
Binary file
languages/co-authors-plus-uk.po ADDED
@@ -0,0 +1,581 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2012 Co-Authors Plus
2
+ # This file is distributed under the same license as the Co-Authors Plus package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Co-Authors Plus\n"
6
+ "Report-Msgid-Bugs-To: http://wordpress.org/tag/co-authors-plus\n"
7
+ "POT-Creation-Date: 2014-03-17 15:59:18+00:00\n"
8
+ "PO-Revision-Date: 2014-03-30 19:29+0200\n"
9
+ "Last-Translator: Jurko Chervony <info@skinik.name>\n"
10
+ "Language-Team: skinik <info@skinik.name>\n"
11
+ "Language: uk\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Poedit 1.6.4\n"
16
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
17
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
18
+ "X-Poedit-SourceCharset: UTF-8\n"
19
+ "X-Poedit-Basepath: ..\n"
20
+ "X-Poedit-SearchPath-0: .\n"
21
+
22
+ #: co-authors-plus.php:300 co-authors-plus.php:401 co-authors-plus.php:487
23
+ #: co-authors-plus.php:1290
24
+ msgid "Authors"
25
+ msgstr "Автори"
26
+
27
+ #: co-authors-plus.php:362
28
+ msgid ""
29
+ "<strong>Note:</strong> To edit post authors, please enable javascript or use "
30
+ "a javascript-capable browser"
31
+ msgstr ""
32
+
33
+ #: co-authors-plus.php:369 co-authors-plus.php:489 co-authors-plus.php:1095
34
+ msgid ""
35
+ "Click on an author to change them. Drag to change their order. Click on "
36
+ "<strong>Remove</strong> to remove them."
37
+ msgstr ""
38
+
39
+ #: co-authors-plus.php:449 php/class-coauthors-wp-list-table.php:148
40
+ msgid "Posts"
41
+ msgstr "Публікації"
42
+
43
+ #: co-authors-plus.php:466
44
+ msgid "View posts by this author"
45
+ msgstr "Переглянути всі матеріали автора"
46
+
47
+ #: co-authors-plus.php:531 co-authors-plus.php:548
48
+ msgid "No co-author exists for that term"
49
+ msgstr ""
50
+
51
+ #: co-authors-plus.php:1090 php/class-coauthors-wp-list-table.php:212
52
+ msgid "Edit"
53
+ msgstr "Редагувати"
54
+
55
+ #: co-authors-plus.php:1091
56
+ msgid "Remove"
57
+ msgstr "Видалити"
58
+
59
+ #: co-authors-plus.php:1092
60
+ msgid "Are you sure you want to remove this author?"
61
+ msgstr ""
62
+
63
+ #: co-authors-plus.php:1093
64
+ msgid "Click to change this author, or drag to change their position"
65
+ msgstr ""
66
+
67
+ #: co-authors-plus.php:1094
68
+ msgid "Search for an author"
69
+ msgstr "Шукати автора"
70
+
71
+ #: co-authors-plus.php:1132
72
+ msgid "Mine"
73
+ msgstr "Моє"
74
+
75
+ #: co-authors-plus.php:1402
76
+ msgid "New comment on your post \"%s\""
77
+ msgstr ""
78
+
79
+ #. translators: 1: comment author, 2: author IP, 3: author domain
80
+ #: co-authors-plus.php:1404 co-authors-plus.php:1521
81
+ msgid "Author : %1$s (IP: %2$s , %3$s)"
82
+ msgstr ""
83
+
84
+ #: co-authors-plus.php:1405 co-authors-plus.php:1522
85
+ msgid "E-mail : %s"
86
+ msgstr ""
87
+
88
+ #: co-authors-plus.php:1406 co-authors-plus.php:1416 co-authors-plus.php:1425
89
+ #: co-authors-plus.php:1508 co-authors-plus.php:1515 co-authors-plus.php:1523
90
+ msgid "URL : %s"
91
+ msgstr ""
92
+
93
+ #: co-authors-plus.php:1407 co-authors-plus.php:1524
94
+ msgid "Whois : http://whois.arin.net/rest/ip/%s"
95
+ msgstr ""
96
+
97
+ #: co-authors-plus.php:1408 co-authors-plus.php:1525
98
+ msgid "Comment: "
99
+ msgstr "Коментар:"
100
+
101
+ #: co-authors-plus.php:1409
102
+ msgid "You can see all comments on this post here: "
103
+ msgstr ""
104
+
105
+ #. translators: 1: blog name, 2: post title
106
+ #: co-authors-plus.php:1411
107
+ msgid "[%1$s] Comment: \"%2$s\""
108
+ msgstr ""
109
+
110
+ #: co-authors-plus.php:1413
111
+ msgid "New trackback on your post \"%s\""
112
+ msgstr ""
113
+
114
+ #. translators: 1: website name, 2: author IP, 3: author domain
115
+ #. translators: 1: comment author, 2: author IP, 3: author domain
116
+ #: co-authors-plus.php:1415 co-authors-plus.php:1424
117
+ msgid "Website: %1$s (IP: %2$s , %3$s)"
118
+ msgstr ""
119
+
120
+ #: co-authors-plus.php:1417 co-authors-plus.php:1426
121
+ msgid "Excerpt: "
122
+ msgstr ""
123
+
124
+ #: co-authors-plus.php:1418
125
+ msgid "You can see all trackbacks on this post here: "
126
+ msgstr ""
127
+
128
+ #. translators: 1: blog name, 2: post title
129
+ #: co-authors-plus.php:1420
130
+ msgid "[%1$s] Trackback: \"%2$s\""
131
+ msgstr ""
132
+
133
+ #: co-authors-plus.php:1422
134
+ msgid "New pingback on your post \"%s\""
135
+ msgstr ""
136
+
137
+ #: co-authors-plus.php:1427
138
+ msgid "You can see all pingbacks on this post here: "
139
+ msgstr ""
140
+
141
+ #. translators: 1: blog name, 2: post title
142
+ #: co-authors-plus.php:1429
143
+ msgid "[%1$s] Pingback: \"%2$s\""
144
+ msgstr ""
145
+
146
+ #: co-authors-plus.php:1432
147
+ msgid "Permalink: %s"
148
+ msgstr ""
149
+
150
+ #: co-authors-plus.php:1434 co-authors-plus.php:1531
151
+ msgid "Trash it: %s"
152
+ msgstr ""
153
+
154
+ #: co-authors-plus.php:1436 co-authors-plus.php:1533
155
+ msgid "Delete it: %s"
156
+ msgstr ""
157
+
158
+ #: co-authors-plus.php:1437 co-authors-plus.php:1534
159
+ msgid "Spam it: %s"
160
+ msgstr ""
161
+
162
+ #: co-authors-plus.php:1505
163
+ msgid "A new trackback on the post \"%s\" is waiting for your approval"
164
+ msgstr ""
165
+
166
+ #: co-authors-plus.php:1507 co-authors-plus.php:1514
167
+ msgid "Website : %1$s (IP: %2$s , %3$s)"
168
+ msgstr ""
169
+
170
+ #: co-authors-plus.php:1509
171
+ msgid "Trackback excerpt: "
172
+ msgstr ""
173
+
174
+ #: co-authors-plus.php:1512
175
+ msgid "A new pingback on the post \"%s\" is waiting for your approval"
176
+ msgstr ""
177
+
178
+ #: co-authors-plus.php:1516
179
+ msgid "Pingback excerpt: "
180
+ msgstr ""
181
+
182
+ #: co-authors-plus.php:1519
183
+ msgid "A new comment on the post \"%s\" is waiting for your approval"
184
+ msgstr ""
185
+
186
+ #: co-authors-plus.php:1529
187
+ msgid "Approve it: %s"
188
+ msgstr ""
189
+
190
+ #: co-authors-plus.php:1536
191
+ msgid ""
192
+ "Currently %s comment is waiting for approval. Please visit the moderation "
193
+ "panel:"
194
+ msgid_plural ""
195
+ "Currently %s comments are waiting for approval. Please visit the moderation "
196
+ "panel:"
197
+ msgstr[0] ""
198
+ msgstr[1] ""
199
+
200
+ #: co-authors-plus.php:1540
201
+ msgid "[%1$s] Please moderate: \"%2$s\""
202
+ msgstr ""
203
+
204
+ #: php/class-coauthors-guest-authors.php:80
205
+ msgid "Guest Author"
206
+ msgstr "Гостьовий автор"
207
+
208
+ #: php/class-coauthors-guest-authors.php:81
209
+ msgid "Guest Authors"
210
+ msgstr "Гостьові автори"
211
+
212
+ #: php/class-coauthors-guest-authors.php:82
213
+ msgid "All Guest Authors"
214
+ msgstr "Всі гостьові автори"
215
+
216
+ #: php/class-coauthors-guest-authors.php:83
217
+ msgid "Add New Guest Author"
218
+ msgstr "Додати нового гостьового автора"
219
+
220
+ #: php/class-coauthors-guest-authors.php:84
221
+ msgid "Edit Guest Author"
222
+ msgstr "Редагувати гостьового автора"
223
+
224
+ #: php/class-coauthors-guest-authors.php:85
225
+ msgid "New Guest Author"
226
+ msgstr "Новий гостьовий автор"
227
+
228
+ #: php/class-coauthors-guest-authors.php:86
229
+ msgid "View Guest Author"
230
+ msgstr "Переглянути гостьового автора"
231
+
232
+ #: php/class-coauthors-guest-authors.php:87
233
+ msgid "Search Guest Authors"
234
+ msgstr "Шукати гостьових авторів"
235
+
236
+ #: php/class-coauthors-guest-authors.php:88
237
+ msgid "No guest authors found"
238
+ msgstr "Не знайдено гостьових авторів"
239
+
240
+ #: php/class-coauthors-guest-authors.php:89
241
+ msgid "No guest authors found in Trash"
242
+ msgstr "В кошику не знайдено гостьових авторів"
243
+
244
+ #: php/class-coauthors-guest-authors.php:90
245
+ msgid "Update Guest Author"
246
+ msgstr "Оновити гостьового автора"
247
+
248
+ #: php/class-coauthors-guest-authors.php:91
249
+ msgid "About the guest author"
250
+ msgstr "Про гостьового автора"
251
+
252
+ #: php/class-coauthors-guest-authors.php:100
253
+ msgctxt "guest author"
254
+ msgid "Add New"
255
+ msgstr "Додати нового"
256
+
257
+ #: php/class-coauthors-guest-authors.php:156
258
+ #: php/class-coauthors-guest-authors.php:162
259
+ msgid "Guest author updated. <a href=\"%s\">View profile</a>"
260
+ msgstr "Гостьового автора оновлено. <a href=\"%s\">Переглянути</a>"
261
+
262
+ #: php/class-coauthors-guest-authors.php:157
263
+ msgid "Custom field updated."
264
+ msgstr ""
265
+
266
+ #: php/class-coauthors-guest-authors.php:158
267
+ msgid "Custom field deleted."
268
+ msgstr ""
269
+
270
+ #: php/class-coauthors-guest-authors.php:159
271
+ msgid "Guest author updated."
272
+ msgstr ""
273
+
274
+ #. translators: %s: date and time of the revision
275
+ #: php/class-coauthors-guest-authors.php:161
276
+ msgid "Guest author restored to revision from %s"
277
+ msgstr ""
278
+
279
+ #: php/class-coauthors-guest-authors.php:163
280
+ msgid "Guest author saved."
281
+ msgstr ""
282
+
283
+ #: php/class-coauthors-guest-authors.php:164
284
+ msgid ""
285
+ "Guest author submitted. <a target=\"_blank\" href=\"%s\">Preview profile</a>"
286
+ msgstr ""
287
+
288
+ #: php/class-coauthors-guest-authors.php:165
289
+ msgid ""
290
+ "Guest author scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
291
+ "\"%2$s\">Preview profile</a>"
292
+ msgstr ""
293
+
294
+ #. translators: Publish box date format, see http:php.net/date
295
+ #: php/class-coauthors-guest-authors.php:167
296
+ msgid "M j, Y @ G:i"
297
+ msgstr ""
298
+
299
+ #: php/class-coauthors-guest-authors.php:168
300
+ msgid ""
301
+ "Guest author updated. <a target=\"_blank\" href=\"%s\">Preview profile</a>"
302
+ msgstr ""
303
+
304
+ #: php/class-coauthors-guest-authors.php:185
305
+ #: php/class-coauthors-guest-authors.php:218
306
+ #: php/class-coauthors-guest-authors.php:437
307
+ msgid "Doin' something fishy, huh?"
308
+ msgstr ""
309
+
310
+ #: php/class-coauthors-guest-authors.php:188
311
+ #: php/class-coauthors-guest-authors.php:222
312
+ msgid "You don't have permission to perform this action."
313
+ msgstr ""
314
+
315
+ #: php/class-coauthors-guest-authors.php:227
316
+ #: php/class-coauthors-guest-authors.php:442
317
+ msgid "Guest author can't be deleted because it doesn't exist."
318
+ msgstr ""
319
+
320
+ #: php/class-coauthors-guest-authors.php:241
321
+ msgid "Co-author does not exists. Try again?"
322
+ msgstr ""
323
+
324
+ #: php/class-coauthors-guest-authors.php:249
325
+ msgid "Please make sure to pick an option."
326
+ msgstr ""
327
+
328
+ #: php/class-coauthors-guest-authors.php:393
329
+ msgid "Guest author deleted."
330
+ msgstr "Гостьового автора видалено."
331
+
332
+ #: php/class-coauthors-guest-authors.php:417
333
+ msgid "Save"
334
+ msgstr "Зберегти"
335
+
336
+ #: php/class-coauthors-guest-authors.php:418
337
+ msgid "Unique Slug"
338
+ msgstr ""
339
+
340
+ #: php/class-coauthors-guest-authors.php:420
341
+ msgid "Name"
342
+ msgstr ""
343
+
344
+ #: php/class-coauthors-guest-authors.php:421
345
+ msgid "Contact Info"
346
+ msgstr "Контактна інформація"
347
+
348
+ #: php/class-coauthors-guest-authors.php:446
349
+ msgid "Delete %s"
350
+ msgstr "Видалити %s"
351
+
352
+ #: php/class-coauthors-guest-authors.php:447
353
+ msgid "You have specified this guest author for deletion:"
354
+ msgstr ""
355
+
356
+ #: php/class-coauthors-guest-authors.php:449
357
+ msgid "What should be done with posts assigned to this guest author?"
358
+ msgstr ""
359
+
360
+ #: php/class-coauthors-guest-authors.php:450
361
+ msgid ""
362
+ "Note: If you'd like to delete the guest author and all of their posts, you "
363
+ "should delete their posts first and then come back to delete the guest "
364
+ "author."
365
+ msgstr ""
366
+
367
+ #: php/class-coauthors-guest-authors.php:459
368
+ msgid "Reassign to another co-author:"
369
+ msgstr ""
370
+
371
+ #: php/class-coauthors-guest-authors.php:465
372
+ msgid "Leave posts assigned to the mapped user, %s."
373
+ msgstr ""
374
+
375
+ #: php/class-coauthors-guest-authors.php:470
376
+ msgid "Remove byline from posts (but leave each post in its current status)."
377
+ msgstr ""
378
+
379
+ #: php/class-coauthors-guest-authors.php:473
380
+ msgid "Confirm Deletion"
381
+ msgstr "Підтвердити видалення"
382
+
383
+ #: php/class-coauthors-guest-authors.php:482
384
+ msgid "Add New"
385
+ msgstr "Додати нового"
386
+
387
+ #: php/class-coauthors-guest-authors.php:543
388
+ msgid "WordPress User Mapping"
389
+ msgstr ""
390
+
391
+ #: php/class-coauthors-guest-authors.php:545
392
+ msgid "-- Not mapped --"
393
+ msgstr "-- Не визначено --"
394
+
395
+ #: php/class-coauthors-guest-authors.php:679
396
+ #: php/class-coauthors-guest-authors.php:688
397
+ msgid "Guest authors cannot be created without display names."
398
+ msgstr ""
399
+
400
+ #: php/class-coauthors-guest-authors.php:697
401
+ msgid ""
402
+ "Guest authors cannot be created with the same user_login value as a user. "
403
+ "Try creating a profile from the user on the Manage Users listing instead."
404
+ msgstr ""
405
+
406
+ #: php/class-coauthors-guest-authors.php:702
407
+ msgid "Display name conflicts with another guest author display name."
408
+ msgstr ""
409
+
410
+ #: php/class-coauthors-guest-authors.php:896
411
+ msgid "ID"
412
+ msgstr ""
413
+
414
+ #: php/class-coauthors-guest-authors.php:903
415
+ #: php/class-coauthors-wp-list-table.php:143
416
+ msgid "Display Name"
417
+ msgstr ""
418
+
419
+ #: php/class-coauthors-guest-authors.php:909
420
+ #: php/class-coauthors-wp-list-table.php:144
421
+ msgid "First Name"
422
+ msgstr "Ім’я"
423
+
424
+ #: php/class-coauthors-guest-authors.php:914
425
+ #: php/class-coauthors-wp-list-table.php:145
426
+ msgid "Last Name"
427
+ msgstr "Прізвище"
428
+
429
+ #: php/class-coauthors-guest-authors.php:919
430
+ msgid "Slug"
431
+ msgstr ""
432
+
433
+ #: php/class-coauthors-guest-authors.php:926
434
+ #: php/class-coauthors-wp-list-table.php:146
435
+ msgid "E-mail"
436
+ msgstr ""
437
+
438
+ #: php/class-coauthors-guest-authors.php:932
439
+ #: php/class-coauthors-wp-list-table.php:147
440
+ msgid "Linked Account"
441
+ msgstr ""
442
+
443
+ #: php/class-coauthors-guest-authors.php:937
444
+ msgid "Website"
445
+ msgstr "Сайт"
446
+
447
+ #: php/class-coauthors-guest-authors.php:943
448
+ msgid "AIM"
449
+ msgstr ""
450
+
451
+ #: php/class-coauthors-guest-authors.php:948
452
+ msgid "Yahoo IM"
453
+ msgstr ""
454
+
455
+ #: php/class-coauthors-guest-authors.php:953
456
+ msgid "Jabber / Google Talk"
457
+ msgstr ""
458
+
459
+ #: php/class-coauthors-guest-authors.php:958
460
+ msgid "Biographical Info"
461
+ msgstr "Опис"
462
+
463
+ #: php/class-coauthors-guest-authors.php:1122
464
+ msgid "%s is a required field"
465
+ msgstr "%s — обов’язкове поле"
466
+
467
+ #: php/class-coauthors-guest-authors.php:1128
468
+ msgid "user_login cannot duplicate existing guest author or mapped user"
469
+ msgstr ""
470
+
471
+ #: php/class-coauthors-guest-authors.php:1173
472
+ msgid "Guest author does not exist"
473
+ msgstr "Гостьовий автор не існує"
474
+
475
+ #: php/class-coauthors-guest-authors.php:1185
476
+ msgid "Reassignment co-author does not exist"
477
+ msgstr ""
478
+
479
+ #: php/class-coauthors-guest-authors.php:1217
480
+ msgid "No user exists with that ID"
481
+ msgstr ""
482
+
483
+ #: php/class-coauthors-guest-authors.php:1275
484
+ msgid "Edit Profile"
485
+ msgstr "Редагувати профіль"
486
+
487
+ #: php/class-coauthors-guest-authors.php:1284
488
+ msgid "Create Profile"
489
+ msgstr "Створити обліковий запис"
490
+
491
+ #: php/class-coauthors-wp-list-table.php:19
492
+ msgid "Co-Authors"
493
+ msgstr ""
494
+
495
+ #: php/class-coauthors-wp-list-table.php:20
496
+ msgid "Co-Author"
497
+ msgstr ""
498
+
499
+ #: php/class-coauthors-wp-list-table.php:81
500
+ msgid "Show all"
501
+ msgstr "Показати все"
502
+
503
+ #: php/class-coauthors-wp-list-table.php:82
504
+ msgid "With linked account"
505
+ msgstr ""
506
+
507
+ #: php/class-coauthors-wp-list-table.php:83
508
+ msgid "Without linked account"
509
+ msgstr ""
510
+
511
+ #: php/class-coauthors-wp-list-table.php:135
512
+ msgid "No matching guest authors were found."
513
+ msgstr ""
514
+
515
+ #: php/class-coauthors-wp-list-table.php:215
516
+ msgid "Delete"
517
+ msgstr "Видалити"
518
+
519
+ #: php/class-coauthors-wp-list-table.php:217
520
+ msgid "View Posts"
521
+ msgstr "Переглянути мареріали"
522
+
523
+ #: php/class-coauthors-wp-list-table.php:267
524
+ msgid "Filter"
525
+ msgstr "Фільтрувати"
526
+
527
+ #: php/class-wp-cli.php:220
528
+ msgid "Please specify a valid user_login"
529
+ msgstr ""
530
+
531
+ #: php/class-wp-cli.php:223
532
+ msgid "Please specify a valid co-author login"
533
+ msgstr ""
534
+
535
+ #: php/class-wp-cli.php:230
536
+ msgid "Skipping - Post #%d already has co-authors assigned: %s"
537
+ msgstr ""
538
+
539
+ #: php/class-wp-cli.php:235
540
+ msgid "Updating - Adding %s's byline to post #%d"
541
+ msgstr ""
542
+
543
+ #: php/class-wp-cli.php:240
544
+ msgid "All done! %d posts were affected."
545
+ msgstr ""
546
+
547
+ #: template-tags.php:79
548
+ msgid ""
549
+ "No post ID provided for CoAuthorsIterator constructor. Are you not in a loop "
550
+ "or is $post not set?"
551
+ msgstr ""
552
+
553
+ #: template-tags.php:133
554
+ msgid " and "
555
+ msgstr " та "
556
+
557
+ #: template-tags.php:233 template-tags.php:468
558
+ msgid "Posts by %s"
559
+ msgstr "Матеріали автора %s"
560
+
561
+ #: template-tags.php:350
562
+ msgid "Visit %s&#8217;s website"
563
+ msgstr "Відвідати %s&#8217;s сайт"
564
+
565
+ #. Plugin Name of the plugin/theme
566
+ msgid "Co-Authors Plus"
567
+ msgstr ""
568
+
569
+ #. Plugin URI of the plugin/theme
570
+ msgid "http://wordpress.org/extend/plugins/co-authors-plus/"
571
+ msgstr ""
572
+
573
+ #. Description of the plugin/theme
574
+ msgid ""
575
+ "Allows multiple authors to be assigned to a post. This plugin is an extended "
576
+ "version of the Co-Authors plugin developed by Weston Ruter."
577
+ msgstr ""
578
+
579
+ #. Author of the plugin/theme
580
+ msgid "Mohammad Jangda, Daniel Bachhuber, Automattic"
581
+ msgstr ""
lib/select2/select2.min.js CHANGED
@@ -1,6 +1,6 @@
1
  /*
2
  Copyright 2012 Igor Vaynberg
3
-
4
  Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012
5
 
6
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in
1
  /*
2
  Copyright 2012 Igor Vaynberg
3
+
4
  Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012
5
 
6
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in
php/class-coauthors-guest-authors.php CHANGED
@@ -125,12 +125,13 @@ class CoAuthors_Guest_Authors
125
  // Some of the common sizes used by get_avatar
126
  $this->avatar_sizes = array(
127
  32,
 
128
  64,
129
  96,
130
- 128
131
  );
132
  $this->avatar_sizes = apply_filters( 'coauthors_guest_author_avatar_sizes', $this->avatar_sizes );
133
- foreach( $this->avatar_sizes as $size ) {
134
  add_image_size( 'guest-author-' . $size, $size, $size, true );
135
  }
136
 
@@ -148,24 +149,28 @@ class CoAuthors_Guest_Authors
148
  function filter_post_updated_messages( $messages ) {
149
  global $post;
150
 
 
 
 
 
151
  $guest_author = $this->get_guest_author_by( 'ID', $post->ID );
152
  $guest_author_link = $this->filter_author_link( '', $guest_author->ID, $guest_author->user_nicename );
153
 
154
- $messages[$this->post_type] = array(
155
  0 => '', // Unused. Messages start at index 1.
156
  1 => sprintf( __( 'Guest author updated. <a href="%s">View profile</a>', 'co-authors-plus' ), esc_url( $guest_author_link ) ),
157
  2 => __( 'Custom field updated.', 'co-authors-plus' ),
158
  3 => __( 'Custom field deleted.', 'co-authors-plus' ),
159
  4 => __( 'Guest author updated.', 'co-authors-plus' ),
160
  /* translators: %s: date and time of the revision */
161
- 5 => isset($_GET['revision']) ? sprintf( __( 'Guest author restored to revision from %s', 'co-authors-plus' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
162
  6 => sprintf( __( 'Guest author updated. <a href="%s">View profile</a>', 'co-authors-plus' ), esc_url( $guest_author_link ) ),
163
  7 => __( 'Guest author saved.', 'co-authors-plus' ),
164
  8 => sprintf( __( 'Guest author submitted. <a target="_blank" href="%s">Preview profile</a>', 'co-authors-plus' ), esc_url( add_query_arg( 'preview', 'true', $guest_author_link ) ) ),
165
  9 => sprintf( __( 'Guest author scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview profile</a>', 'co-authors-plus' ),
166
- // translators: Publish box date format, see http://php.net/date
167
  date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( $guest_author_link ) ),
168
- 10 => sprintf( __('Guest author updated. <a target="_blank" href="%s">Preview profile</a>', 'co-authors-plus' ), esc_url( add_query_arg( 'preview', 'true', $guest_author_link ) ) ),
169
  );
170
  return $messages;
171
  }
@@ -178,26 +183,30 @@ class CoAuthors_Guest_Authors
178
  */
179
  function handle_create_guest_author_action() {
180
 
181
- if ( !isset( $_GET['action'], $_GET['nonce'], $_GET['user_id'] ) || $_GET['action'] != 'cap-create-guest-author' )
182
  return;
 
183
 
184
- if ( !wp_verify_nonce( $_GET['nonce'], 'create-guest-author' ) )
185
- wp_die( __( "Doin' something fishy, huh?", 'co-authors-plus' ) );
 
186
 
187
- if ( ! current_user_can( $this->list_guest_authors_cap ) )
188
- wp_die( __( "You don't have permission to perform this action.", 'co-authors-plus' ) );
 
189
 
190
  $user_id = intval( $_GET['user_id'] );
191
 
192
  // Create the guest author
193
  $post_id = $this->create_guest_author_from_user_id( $user_id );
194
- if ( is_wp_error( $post_id ) )
195
- wp_die( $post_id->get_error_message() );
 
196
 
197
  // Redirect to the edit Guest Author screen
198
  $edit_link = get_edit_post_link( $post_id, 'redirect' );
199
  $redirect_to = add_query_arg( 'message', 'guest-author-created', $edit_link );
200
- wp_safe_redirect( $redirect_to );
201
  exit;
202
 
203
  }
@@ -210,25 +219,29 @@ class CoAuthors_Guest_Authors
210
  function handle_delete_guest_author_action() {
211
  global $coauthors_plus;
212
 
213
- if ( !isset( $_POST['action'], $_POST['reassign'], $_POST['_wpnonce'], $_POST['id'] ) || 'delete-guest-author' != $_POST['action'] )
214
  return;
 
215
 
216
  // Verify the user is who they say they are
217
- if ( !wp_verify_nonce( $_POST['_wpnonce'], 'delete-guest-author' ) )
218
- wp_die( __( "Doin' something fishy, huh?", 'co-authors-plus' ) );
 
219
 
220
  // Make sure they can perform the action
221
- if ( ! current_user_can( $this->list_guest_authors_cap ) )
222
- wp_die( __( "You don't have permission to perform this action.", 'co-authors-plus' ) );
 
223
 
224
  // Make sure the guest author actually exists
225
- $guest_author = $this->get_guest_author_by( 'ID', (int)$_POST['id'] );
226
- if ( ! $guest_author )
227
- wp_die( __( "Guest author can't be deleted because it doesn't exist.", 'co-authors-plus' ) );
 
228
 
229
  // Perform the reassignment if needed
230
  $guest_author_term = $coauthors_plus->get_author_term( $guest_author );
231
- switch( $_POST['reassign'] ) {
232
  // Leave assigned to the current linked account
233
  case 'leave-assigned':
234
  $reassign_to = $guest_author->linked_account;
@@ -237,8 +250,9 @@ class CoAuthors_Guest_Authors
237
  case 'reassign-another':
238
  $user_nicename = sanitize_title( $_POST['leave-assigned-to'] );
239
  $reassign_to = $coauthors_plus->get_coauthor_by( 'user_nicename', $user_nicename );
240
- if ( ! $reassign_to )
241
- wp_die( __( 'Co-author does not exists. Try again?', 'co-authors-plus' ) );
 
242
  $reassign_to = $reassign_to->user_login;
243
  break;
244
  // Remove the byline, but don't delete the post
@@ -246,7 +260,7 @@ class CoAuthors_Guest_Authors
246
  $reassign_to = false;
247
  break;
248
  default:
249
- wp_die( __( "Please make sure to pick an option.", 'co-authors-plus' ) );
250
  break;
251
  }
252
 
@@ -255,14 +269,15 @@ class CoAuthors_Guest_Authors
255
  $args = array(
256
  'page' => 'view-guest-authors',
257
  );
258
- if ( is_wp_error( $retval ) )
259
  $args['message'] = 'delete-error';
260
- else
261
  $args['message'] = 'guest-author-deleted';
 
262
 
263
  // Redirect to safety
264
- $redirect_to = add_query_arg( $args, admin_url( $this->parent_page ) );
265
- wp_safe_redirect( $redirect_to );
266
  exit;
267
  }
268
 
@@ -274,26 +289,28 @@ class CoAuthors_Guest_Authors
274
  function handle_ajax_search_coauthors_to_assign() {
275
  global $coauthors_plus;
276
 
277
- if ( ! current_user_can( $this->list_guest_authors_cap ) )
278
  die();
 
279
 
280
  $search = sanitize_text_field( $_GET['q'] );
281
- if ( ! empty( $_GET['guest_author'] ) )
282
- $ignore = array( $this->get_guest_author_by( 'ID', (int)$_GET['guest_author'] )->user_login );
283
- else
284
  $ignore = array();
 
285
 
286
  $results = wp_list_pluck( $coauthors_plus->search_authors( $search, $ignore ), 'user_login' );
287
  $retval = array();
288
- foreach( $results as $user_login ) {
289
  $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $user_login );
290
- $retval[] = (object)array(
291
  'display_name' => $coauthor->display_name,
292
  'user_login' => $coauthor->user_login,
293
  'id' => $coauthor->user_nicename,
294
  );
295
  }
296
- echo json_encode( $retval );
297
  die();
298
  }
299
 
@@ -305,23 +322,25 @@ class CoAuthors_Guest_Authors
305
  */
306
  function action_parse_request( $query ) {
307
 
308
- if ( !isset( $query->query_vars['author_name'] ) )
309
  return $query;
 
310
 
311
  // No redirection needed on admin requests
312
- if ( is_admin() )
313
  return $query;
 
314
 
315
  $coauthor = $this->get_guest_author_by( 'linked_account', sanitize_title( $query->query_vars['author_name'] ) );
316
  if ( is_object( $coauthor ) && $query->query_vars['author_name'] != $coauthor->user_login ) {
317
  global $wp_rewrite;
318
  $link = $wp_rewrite->get_author_permastruct();
319
 
320
- if ( empty($link) ) {
321
  $file = home_url( '/' );
322
  $link = $file . '?author_name=' . $coauthor->user_login;
323
  } else {
324
- $link = str_replace('%author%', $coauthor->user_login, $link);
325
  $link = home_url( user_trailingslashit( $link ) );
326
  }
327
  wp_safe_redirect( $link );
@@ -350,13 +369,13 @@ class CoAuthors_Guest_Authors
350
  function action_admin_enqueue_scripts() {
351
  global $pagenow;
352
  // Enqueue our guest author CSS on the related pages
353
- if ( $this->parent_page == $pagenow && isset( $_GET['page'] ) && $_GET['page'] == 'view-guest-authors' ) {
354
  wp_enqueue_script( 'jquery-select2', plugins_url( 'lib/select2/select2.min.js', dirname( __FILE__ ) ), array( 'jquery' ), COAUTHORS_PLUS_VERSION );
355
  wp_enqueue_style( 'cap-jquery-select2-css', plugins_url( 'lib/select2/select2.css', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
356
 
357
  wp_enqueue_style( 'guest-authors-css', plugins_url( 'css/guest-authors.css', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
358
  wp_enqueue_script( 'guest-authors-js', plugins_url( 'js/guest-authors.js', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
359
- } else if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) && $this->post_type == get_post_type() ) {
360
  add_action( 'admin_head', array( $this, 'change_title_icon' ) );
361
  }
362
  }
@@ -385,10 +404,11 @@ class CoAuthors_Guest_Authors
385
  function action_admin_notices() {
386
  global $pagenow;
387
 
388
- if ( $this->parent_page != $pagenow || ! isset( $_REQUEST['message'] ) )
389
  return;
 
390
 
391
- switch( $_REQUEST['message'] ) {
392
  case 'guest-author-deleted':
393
  $message = __( 'Guest author deleted.', 'co-authors-plus' );
394
  break;
@@ -397,9 +417,9 @@ class CoAuthors_Guest_Authors
397
  break;
398
  }
399
 
400
- if ( $message )
401
  echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
402
-
403
  }
404
 
405
  /**
@@ -414,11 +434,11 @@ class CoAuthors_Guest_Authors
414
  // Remove the submitpost metabox because we have our own
415
  remove_meta_box( 'submitdiv', $this->post_type, 'side' );
416
  remove_meta_box( 'slugdiv', $this->post_type, 'normal' );
417
- add_meta_box( 'coauthors-manage-guest-author-save', __( 'Save', 'co-authors-plus'), array( $this, 'metabox_manage_guest_author_save' ), $this->post_type, 'side', 'default' );
418
- add_meta_box( 'coauthors-manage-guest-author-slug', __( 'Unique Slug', 'co-authors-plus'), array( $this, 'metabox_manage_guest_author_slug' ), $this->post_type, 'side', 'default' );
419
  // Our metaboxes with co-author details
420
- add_meta_box( 'coauthors-manage-guest-author-name', __( 'Name', 'co-authors-plus'), array( $this, 'metabox_manage_guest_author_name' ), $this->post_type, 'normal', 'default' );
421
- add_meta_box( 'coauthors-manage-guest-author-contact-info', __( 'Contact Info', 'co-authors-plus'), array( $this, 'metabox_manage_guest_author_contact_info' ), $this->post_type, 'normal', 'default' );
422
  add_meta_box( 'coauthors-manage-guest-author-bio', $this->labels['metabox_about'], array( $this, 'metabox_manage_guest_author_bio' ), $this->post_type, 'normal', 'default' );
423
  }
424
  }
@@ -433,41 +453,43 @@ class CoAuthors_Guest_Authors
433
  // Allow guest authors to be deleted
434
  if ( isset( $_GET['action'], $_GET['id'], $_GET['_wpnonce'] ) && 'delete' == $_GET['action'] ) {
435
  // Make sure the user is who they say they are
436
- if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'guest-author-delete' ) )
437
- wp_die( __( "Doin' something fishy, huh?", 'co-authors-plus' ) );
 
438
 
439
  // Make sure the guest author actually exists
440
- $guest_author = $this->get_guest_author_by( 'ID', (int)$_GET['id'] );
441
- if ( ! $guest_author )
442
- wp_die( __( "Guest author can't be deleted because it doesn't exist.", 'co-authors-plus' ) );
 
443
 
444
  echo '<div class="wrap">';
445
  echo '<div class="icon32" id="icon-users"><br/></div>';
446
- echo '<h2>' . sprintf( __( 'Delete %s', 'co-authors-plus ' ), $this->labels['plural'] ) . '</h2>';
447
- echo '<p>' . __( 'You have specified this guest author for deletion:', 'co-authors-plus' ) . '</p>';
448
- echo '<p>#' . $guest_author->ID . ': ' . esc_html( $guest_author->display_name ) . '</p>';
449
- echo '<p>' . __( "What should be done with posts assigned to this guest author?", 'co-authors-plus' ) . '</p>';
450
- echo '<p class="description">' . __( "Note: If you'd like to delete the guest author and all of their posts, you should delete their posts first and then come back to delete the guest author.", 'co-authors-plus' ) . '</p>';
451
  echo '<form method="POST" action="' . esc_url( add_query_arg( 'page', 'view-guest-authors', admin_url( $this->parent_page ) ) ) . '">';
452
  // Hidden stuffs
453
  echo '<input type="hidden" name="action" value="delete-guest-author" />';
454
  wp_nonce_field( 'delete-guest-author' );
455
- echo '<input type="hidden" id="id" name="id" value="' . esc_attr( (int)$_GET['id'] ) . '" />';
456
  echo '<fieldset><ul style="list-style-type:none;">';
457
  // Reassign to another user
458
  echo '<li class="hide-if-no-js"><label for="reassign-another">';
459
- echo '<input type="radio" id="reassign-another" name="reassign" class="reassign-option" value="reassign-another" />&nbsp;&nbsp;' . __( 'Reassign to another co-author:', 'co-authors-plus' ) . '&nbsp;&nbsp;</label>';
460
  echo '<input type="hidden" id="leave-assigned-to" name="leave-assigned-to" style="width:200px;" />';
461
  echo '</li>';
462
  // Leave mapped to a linked account
463
  if ( get_user_by( 'login', $guest_author->linked_account ) ) {
464
  echo '<li><label for="leave-assigned">';
465
- echo '<input type="radio" id="leave-assigned" class="reassign-option" name="reassign" value="leave-assigned" />&nbsp;&nbsp;' . sprintf( __( 'Leave posts assigned to the mapped user, %s.', 'co-authors-plus' ), $guest_author->linked_account );
466
  echo '</label></li>';
467
  }
468
  // Remove bylines from the posts
469
  echo '<li><label for="remove-byline">';
470
- echo '<input type="radio" id="remove-byline" class="reassign-option" name="reassign" value="remove-byline" />&nbsp;&nbsp;' . __( 'Remove byline from posts (but leave each post in its current status).', 'co-authors-plus' );
471
  echo '</label></li>';
472
  echo '</ul></fieldset>';
473
  submit_button( __( 'Confirm Deletion', 'co-authors-plus' ), 'secondary', 'submit', true, array( 'disabled' => 'disabled' ) );
@@ -476,10 +498,10 @@ class CoAuthors_Guest_Authors
476
  } else {
477
  echo '<div class="wrap">';
478
  echo '<div class="icon32" id="icon-users"><br/></div>';
479
- echo '<h2>' . $this->labels['plural'];
480
  // @todo caps check for creating a new user
481
  $add_new_link = admin_url( "post-new.php?post_type=$this->post_type" );
482
- echo '<a href="' . $add_new_link . '" class="add-new-h2">' . esc_html( __( 'Add New', 'co-authors-plus' ) ) . '</a>';
483
  echo '</h2>';
484
  $cap_list_table = new CoAuthors_WP_List_Table();
485
  $cap_list_table->prepare_items();
@@ -500,10 +522,11 @@ class CoAuthors_Guest_Authors
500
  function metabox_manage_guest_author_save() {
501
  global $post, $coauthors_plus;
502
 
503
- if ( in_array( $post->post_status, array( 'pending', 'publish', 'draft' ) ) )
504
  $button_text = $this->labels['update_item'];
505
- else
506
  $button_text = $this->labels['add_new_item'];
 
507
  submit_button( $button_text, 'primary', 'publish', false );
508
 
509
  // Secure all of our requests
@@ -527,21 +550,24 @@ class CoAuthors_Guest_Authors
527
  // Taken from grist_authors.
528
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
529
  $linked_account = get_post_meta( $post->ID, $linked_account_key, true );
530
- if ( $user = get_user_by( 'login', $linked_account ) )
531
  $linked_account_id = $user->ID;
532
- else
533
  $linked_account_id = -1;
 
534
 
535
  // If user_login is the same as linked account, don't let the association be removed
536
- if ( $linked_account == $existing_slug )
537
  add_filter( 'wp_dropdown_users', array( $this, 'filter_wp_dropdown_users_to_disable' ) );
 
538
 
539
  $linked_account_user_ids = wp_list_pluck( $this->get_all_linked_accounts(), 'ID' );
540
- if ( false !== ( $key = array_search( $linked_account_id, $linked_account_user_ids ) ) )
541
- unset( $linked_account_user_ids[$key] );
 
542
 
543
- echo '<p><label>' . __( 'WordPress User Mapping', 'co-authors-plus' ) . '</label> ';
544
- wp_dropdown_users( array(
545
  'show_option_none' => __( '-- Not mapped --', 'co-authors-plus' ),
546
  'name' => esc_attr( $this->get_post_meta_key( 'linked_account' ) ),
547
  // If we're adding an author or if there is no post author (0), then use -1 (which is show_option_none).
@@ -549,7 +575,7 @@ class CoAuthors_Guest_Authors
549
  'selected' => $linked_account_id,
550
  // Don't let user accounts to be linked to more than one guest author
551
  'exclude' => $linked_account_user_ids,
552
- ) );
553
  echo '</p>';
554
 
555
  remove_filter( 'wp_dropdown_users', array( $this, 'filter_wp_dropdown_users_to_disable' ) );
@@ -575,25 +601,25 @@ class CoAuthors_Guest_Authors
575
 
576
  $fields = $this->get_guest_author_fields( 'name' );
577
  echo '<table class="form-table"><tbody>';
578
- foreach( $fields as $field ) {
579
  $pm_key = $this->get_post_meta_key( $field['key'] );
580
  $value = get_post_meta( $post->ID, $pm_key, true );
581
  echo '<tr><th>';
582
- echo '<label for="' . esc_attr( $pm_key ) . '">' . $field['label'] . '</label>';
583
  echo '</th><td>';
584
-
585
- if( !isset( $field['input'] ) ) {
586
- $field['input'] = "text";
587
  }
588
  $field['input'] = apply_filters( 'coauthors_name_field_type_'. $pm_key , $field['input'] );
589
- switch( $field['input'] ) {
590
- case "checkbox":
591
  echo '<input type="checkbox" name="' . esc_attr( $pm_key ) . '"'. checked( '1', $value, false ) .' value="1"/>';
592
  break;
593
  default:
594
  echo '<input type="'. esc_attr( $field['input'] ) .'" name="' . esc_attr( $pm_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text" />';
595
  break;
596
- }
597
  echo '</td></tr>';
598
  }
599
  echo '</tbody></table>';
@@ -610,25 +636,25 @@ class CoAuthors_Guest_Authors
610
 
611
  $fields = $this->get_guest_author_fields( 'contact-info' );
612
  echo '<table class="form-table"><tbody>';
613
- foreach( $fields as $field ) {
614
  $pm_key = $this->get_post_meta_key( $field['key'] );
615
  $value = get_post_meta( $post->ID, $pm_key, true );
616
  echo '<tr><th>';
617
- echo '<label for="' . esc_attr( $pm_key ) . '">' . $field['label'] . '</label>';
618
  echo '</th><td>';
619
-
620
- if( !isset( $field['input'] ) ) {
621
- $field['input'] = "text";
622
  }
623
  $field['input'] = apply_filters( 'coauthors_name_field_type_'. $pm_key , $field['input'] );
624
- switch( $field['input'] ) {
625
- case "checkbox":
626
  echo '<input type="checkbox" name="' . esc_attr( $pm_key ) . '"'. checked( '1', $value, false ) .' value="1"/>';
627
  break;
628
  default:
629
  echo '<input type="'. esc_attr( $field['input'] ) .'" name="' . esc_attr( $pm_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text" />';
630
  break;
631
- }
632
 
633
  echo '</td></tr>';
634
  }
@@ -646,11 +672,11 @@ class CoAuthors_Guest_Authors
646
 
647
  $fields = $this->get_guest_author_fields( 'about' );
648
  echo '<table class="form-table"><tbody>';
649
- foreach( $fields as $field ) {
650
  $pm_key = $this->get_post_meta_key( $field['key'] );
651
  $value = get_post_meta( $post->ID, $pm_key, true );
652
  echo '<tr><th>';
653
- echo '<label for="' . esc_attr( $pm_key ) . '">' . $field['label'] . '</label>';
654
  echo '</th><td>';
655
  echo '<textarea style="width:300px;margin-bottom:6px;" name="' . esc_attr( $pm_key ) . '">' . esc_textarea( $value ) . '</textarea>';
656
  echo '</td></tr>';
@@ -667,39 +693,46 @@ class CoAuthors_Guest_Authors
667
  */
668
  function manage_guest_author_filter_post_data( $post_data, $original_args ) {
669
 
670
- if ( $post_data['post_type'] != $this->post_type )
671
  return $post_data;
 
672
 
673
  // @todo caps check
674
- if ( !isset( $_POST['guest-author-nonce'] ) || !wp_verify_nonce( $_POST['guest-author-nonce'], 'guest-author-nonce' ) )
675
  return $post_data;
 
676
 
677
  // Validate the display name
678
  if ( empty( $_POST['cap-display_name'] ) ) {
679
- wp_die( __( 'Guest authors cannot be created without display names.', 'co-authors-plus' ) );
680
  }
681
  $post_data['post_title'] = sanitize_text_field( $_POST['cap-display_name'] );
682
 
683
  $slug = sanitize_title( get_post_meta( $original_args['ID'], $this->get_post_meta_key( 'user_login' ), true ) );
684
- if ( ! $slug )
685
  $slug = sanitize_title( $_POST['cap-display_name'] );
 
 
686
  // Uh oh, no guest authors without slugs
687
- if ( ! $slug )
688
- wp_die( __( 'Guest authors cannot be created without display names.', 'co-authors-plus' ) );
 
689
  $post_data['post_name'] = $this->get_post_meta_key( $slug );
690
 
691
  // Guest authors can't be created with the same user_login as a user
692
  $user_nicename = str_replace( 'cap-', '', $slug );
693
  $user = get_user_by( 'slug', $user_nicename );
694
- if ( $user
695
  && is_user_member_of_blog( $user->ID, get_current_blog_id() )
696
- && $user->user_login != get_post_meta( $original_args['ID'], $this->get_post_meta_key( 'linked_account' ), true ) )
697
- wp_die( __( 'Guest authors cannot be created with the same user_login value as a user. Try creating a profile from the user on the Manage Users listing instead.', 'co-authors-plus' ) );
 
698
 
699
  // Guest authors can't have the same post_name value
700
  $guest_author = $this->get_guest_author_by( 'post_name', $post_data['post_name'] );
701
- if ( $guest_author && $guest_author->ID != $original_args['ID'] )
702
- wp_die( __( 'Display name conflicts with another guest author display name.', 'co-authors-plus' ) );
 
703
 
704
  return $post_data;
705
  }
@@ -712,49 +745,57 @@ class CoAuthors_Guest_Authors
712
  function manage_guest_author_save_meta_fields( $post_id, $post ) {
713
  global $coauthors_plus;
714
 
715
- if ( $post->post_type != $this->post_type )
716
  return;
 
717
 
718
  // @todo caps check
719
- if ( !isset( $_POST['guest-author-nonce'] ) || !wp_verify_nonce( $_POST['guest-author-nonce'], 'guest-author-nonce' ) )
720
  return;
 
721
 
722
  // Save our data to post meta
723
  $author_fields = $this->get_guest_author_fields();
724
- foreach( $author_fields as $author_field ) {
725
 
726
  $key = $this->get_post_meta_key( $author_field['key'] );
727
  // 'user_login' should only be saved on post update if it doesn't exist
728
- if ( 'user_login' == $author_field['key'] && !get_post_meta( $post_id, $key, true ) ) {
729
  $display_name_key = $this->get_post_meta_key( 'display_name' );
730
- $temp_slug = sanitize_title( $_POST[$display_name_key] );
731
  update_post_meta( $post_id, $key, $temp_slug );
732
  continue;
733
  }
734
  if ( 'linked_account' == $author_field['key'] ) {
735
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
736
- if ( ! empty( $_POST[$linked_account_key] ) )
737
- $user_id = intval( $_POST[$linked_account_key] );
738
- else
739
  continue;
 
740
  $user = get_user_by( 'id', $user_id );
741
- if ( $user_id > 0 && is_object( $user ) )
742
  $user_login = $user->user_login;
743
- else
744
  $user_login = '';
 
745
  update_post_meta( $post_id, $key, $user_login );
746
  continue;
747
  }
748
 
749
- if ( isset( $author_field['type'] ) && 'checkbox' === $author_field['type'] && ! isset( $_POST[ $key ] ) )
750
  delete_post_meta( $post_id, $key );
 
751
 
752
- if ( !isset( $_POST[$key] ) )
753
  continue;
754
- if ( isset( $author_field['sanitize_function'] ) && is_callable( $author_field['sanitize_function'] ) )
755
- $value = call_user_func( $author_field['sanitize_function'], $_POST[$key] );
756
- else
757
- $value = sanitize_text_field( $_POST[$key] );
 
 
 
758
  update_post_meta( $post_id, $key, $value );
759
  }
760
 
@@ -762,6 +803,10 @@ class CoAuthors_Guest_Authors
762
  $author_term = $coauthors_plus->update_author_term( $author );
763
  // Add the author as a post term
764
  wp_set_post_terms( $post_id, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy, false );
 
 
 
 
765
  }
766
 
767
  /**
@@ -781,16 +826,17 @@ class CoAuthors_Guest_Authors
781
 
782
  if ( false == $force && false !== ( $retval = wp_cache_get( $cache_key, self::$cache_group ) ) ) {
783
  // Properly catch our false condition cache
784
- if ( is_object( $retval ) )
785
  return $retval;
786
- else
787
  return false;
 
788
  }
789
 
790
- switch( $key ) {
791
  case 'ID':
792
  case 'id':
793
- $query = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID=%d", $value );
794
  $post_id = $wpdb->get_var( $query );
795
  if ( empty( $post_id ) ) {
796
  $post_id = '0';
@@ -809,16 +855,19 @@ class CoAuthors_Guest_Authors
809
  case 'user_login':
810
  case 'linked_account':
811
  case 'user_email':
812
- if ( 'login' == $key )
813
  $key = 'user_login';
 
814
  // Ensure we aren't doing the lookup by the prefixed value
815
- if ( 'user_login' == $key )
816
  $value = preg_replace( '#^cap\-#', '', $value );
 
817
  $query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key=%s AND meta_value=%s;", $this->get_post_meta_key( $key ), $value );
818
  $post_id = $wpdb->get_var( $query );
819
  if ( empty( $post_id ) ) {
820
- if ( 'user_login' == $key )
821
  return $this->get_guest_author_by( 'post_name', $value ); // fallback to post_name in case the guest author isn't a linked account
 
822
  $post_id = '0';
823
  }
824
  break;
@@ -839,10 +888,10 @@ class CoAuthors_Guest_Authors
839
 
840
  // Load the guest author fields
841
  $fields = $this->get_guest_author_fields();
842
- foreach( $fields as $field ) {
843
  $key = $field['key'];
844
  $pm_key = $this->get_post_meta_key( $field['key'] );
845
- $guest_author[$key] = get_post_meta( $post_id, $pm_key, true );
846
  }
847
  // Support for non-Latin characters. They're stored as urlencoded slugs
848
  $guest_author['user_login'] = urldecode( $guest_author['user_login'] );
@@ -851,9 +900,9 @@ class CoAuthors_Guest_Authors
851
  $guest_author['user_nicename'] = sanitize_title( $guest_author['user_login'] );
852
  $guest_author['type'] = 'guest-author';
853
 
854
- wp_cache_set( $cache_key, (object)$guest_author, self::$cache_group );
855
 
856
- return (object)$guest_author;
857
  }
858
 
859
  /**
@@ -865,16 +914,18 @@ class CoAuthors_Guest_Authors
865
  */
866
  function get_guest_author_thumbnail( $guest_author, $size ) {
867
  // See if the guest author has an avatar
868
- if ( ! has_post_thumbnail( $guest_author->ID ) )
869
  return null;
 
870
 
871
  $args = array(
872
  'class' => "avatar avatar-{$size} photo",
873
  );
874
- if ( in_array( $size, $this->avatar_sizes ) )
875
  $size = 'guest-author-' . $size;
876
- else
877
  $size = array( $size, $size );
 
878
 
879
  $thumbnail = get_the_post_thumbnail( $guest_author->ID, $size, $args );
880
 
@@ -888,7 +939,7 @@ class CoAuthors_Guest_Authors
888
  */
889
  function get_guest_author_fields( $groups = 'all' ) {
890
 
891
- $groups = (array)$groups;
892
  $global_fields = array(
893
  // Hidden (included in object, no UI elements)
894
  array(
@@ -900,23 +951,23 @@ class CoAuthors_Guest_Authors
900
  // Name
901
  array(
902
  'key' => 'display_name',
903
- 'label' => __( 'Display Name', 'co-authors-plus'),
904
  'group' => 'name',
905
  'required' => true,
906
  ),
907
  array(
908
  'key' => 'first_name',
909
- 'label' => __( 'First Name', 'co-authors-plus'),
910
  'group' => 'name',
911
  ),
912
  array(
913
  'key' => 'last_name',
914
- 'label' => __( 'Last Name', 'co-authors-plus'),
915
  'group' => 'name',
916
  ),
917
  array(
918
  'key' => 'user_login',
919
- 'label' => __( 'Slug', 'co-authors-plus'),
920
  'group' => 'slug',
921
  'required' => true,
922
  ),
@@ -961,9 +1012,10 @@ class CoAuthors_Guest_Authors
961
  ),
962
  );
963
  $fields_to_return = array();
964
- foreach( $global_fields as $single_field ) {
965
- if ( in_array( $single_field['group'], $groups ) || $groups[0] == 'all' && $single_field['group'] != 'hidden' )
966
  $fields_to_return[] = $single_field;
 
967
  }
968
 
969
  return apply_filters( 'coauthors_guest_author_fields', $fields_to_return, $groups );
@@ -978,8 +1030,9 @@ class CoAuthors_Guest_Authors
978
  */
979
  function get_post_meta_key( $key ) {
980
 
981
- if ( 0 !== stripos( $key, 'cap-' ) )
982
  $key = 'cap-' . $key;
 
983
 
984
  return $key;
985
  }
@@ -989,17 +1042,18 @@ class CoAuthors_Guest_Authors
989
  *
990
  * @param string $key A guest author field
991
  * @param string $value The guest author field value
992
- *
993
  * @return string The generated cache key
994
  */
995
  function get_cache_key( $key, $value ) {
996
  // Normalize $key and $value
997
- switch( $key ) {
998
  case 'post_name':
999
  $key = 'user_nicename';
1000
 
1001
- if ( 0 === strpos( $value, 'cap-' ) )
1002
  $value = substr( $value, 4 );
 
1003
 
1004
  break;
1005
 
@@ -1028,10 +1082,11 @@ class CoAuthors_Guest_Authors
1028
  if ( true === $force || false === $retval ) {
1029
  $user_logins = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key=%s AND meta_value !=''", $this->get_post_meta_key( 'linked_account' ) ) );
1030
  $users = array();
1031
- foreach( $user_logins as $user_login ) {
1032
  $user = get_user_by( 'login', $user_login );
1033
- if ( ! $user )
1034
  continue;
 
1035
  $users[] = array(
1036
  'ID' => $user->ID,
1037
  'user_login' => $user->user_login,
@@ -1051,18 +1106,19 @@ class CoAuthors_Guest_Authors
1051
  */
1052
  function filter_update_post_metadata( $retnull, $object_id, $meta_key, $meta_value, $prev_value ) {
1053
 
1054
- if ( $this->post_type != get_post_type( $object_id ) )
1055
- return null;
 
1056
 
1057
  // If the linked_account is changing, invalidate the cache of all linked accounts
1058
  // Don't regenerate though, as we haven't saved the new value
1059
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
1060
- if ( $linked_account_key == $meta_key && $meta_value != get_post_meta( $object_id, $linked_account_key, true ) ) {
1061
  $this->delete_guest_author_cache( $object_id );
1062
  }
1063
 
1064
  // If one of the guest author meta values has changed, we'll need to invalidate all keys
1065
- if ( false !== strpos( $meta_key, 'cap-' ) && $meta_value != get_post_meta( $object_id, $meta_key, true ) ) {
1066
  $this->delete_guest_author_cache( $object_id );
1067
  }
1068
 
@@ -1078,21 +1134,23 @@ class CoAuthors_Guest_Authors
1078
  */
1079
  public function delete_guest_author_cache( $id_or_object ) {
1080
 
1081
- if ( is_object( $id_or_object ) )
1082
  $guest_author = $id_or_object;
1083
- else
1084
- $guest_author = $this->get_guest_author_by( 'ID', $id_or_object );
 
1085
 
1086
  // Delete the lookup cache associated with each old co-author value
1087
  $keys = wp_list_pluck( $this->get_guest_author_fields(), 'key' );
1088
  $keys = array_merge( $keys, array( 'login', 'post_name', 'user_nicename', 'ID' ) );
1089
- foreach( $keys as $key ) {
1090
  $value_key = $key;
1091
 
1092
- if ( 'post_name' == $key )
1093
- $value_key = 'user_nicename';
1094
- else if ( 'login' == $key )
1095
- $value_key = 'user_login';
 
1096
 
1097
  $cache_key = $this->get_cache_key( $key, $guest_author->$value_key );
1098
 
@@ -1102,7 +1160,7 @@ class CoAuthors_Guest_Authors
1102
  // Delete the 'all-linked-accounts' cache
1103
  wp_cache_delete( 'all-linked-accounts', self::$cache_group );
1104
 
1105
- }
1106
 
1107
 
1108
  /**
@@ -1115,19 +1173,19 @@ class CoAuthors_Guest_Authors
1115
 
1116
  // Validate the arguments that have been passed
1117
  $fields = $this->get_guest_author_fields();
1118
- foreach( $fields as $field ) {
1119
 
1120
  // Make sure required fields are there
1121
- if ( isset( $field['required'] ) && $field['required'] && empty( $args[$field['key']] ) ) {
1122
  return new WP_Error( 'field-required', sprintf( __( '%s is a required field', 'co-authors-plus' ), $field['key'] ) );
1123
  }
1124
 
1125
  // The user login field shouldn't collide with any existing users
1126
  if ( 'user_login' == $field['key'] && $existing_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $args['user_login'], true ) ) {
1127
- if ( 'guest-author' == $existing_coauthor->type )
1128
  return new WP_Error( 'duplicate-field', __( 'user_login cannot duplicate existing guest author or mapped user', 'co-authors-plus' ) );
 
1129
  }
1130
-
1131
  }
1132
 
1133
  // Create the primary post object
@@ -1137,22 +1195,28 @@ class CoAuthors_Guest_Authors
1137
  'post_type' => $this->post_type,
1138
  );
1139
  $post_id = wp_insert_post( $new_post, true );
1140
- if ( is_wp_error( $post_id ) )
1141
  return $post_id;
 
1142
 
1143
  // Add all of the fields for the new guest author
1144
- foreach( $fields as $field ) {
1145
  $key = $field['key'];
1146
- if ( empty( $args[$key] ) )
1147
  continue;
 
1148
  $pm_key = $this->get_post_meta_key( $key );
1149
- update_post_meta( $post_id, $pm_key, $args[$key] );
1150
  }
1151
 
1152
  // Make sure the author term exists and that we're assigning it to this post type
1153
  $author_term = $coauthors_plus->update_author_term( $this->get_guest_author_by( 'ID', $post_id ) );
1154
  wp_set_post_terms( $post_id, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy, false );
1155
 
 
 
 
 
1156
  return $post_id;
1157
  }
1158
 
@@ -1169,26 +1233,30 @@ class CoAuthors_Guest_Authors
1169
  global $coauthors_plus;
1170
 
1171
  $guest_author = $this->get_guest_author_by( 'ID', $id );
1172
- if ( ! $guest_author )
1173
  return new WP_Error( 'guest-author-missing', __( 'Guest author does not exist', 'co-authors-plus' ) );
 
1174
 
1175
  $guest_author_term = $coauthors_plus->get_author_term( $guest_author );
1176
 
1177
  if ( $reassign_to ) {
1178
 
1179
  // We're reassigning the guest author's posts user to its linked account
1180
- if ( $guest_author->linked_account == $reassign_to )
1181
  $reassign_to_author = get_user_by( 'login', $reassign_to );
1182
- else
1183
  $reassign_to_author = $coauthors_plus->get_coauthor_by( 'user_login', $reassign_to );
1184
- if ( ! $reassign_to_author )
 
 
1185
  return new WP_Error( 'reassign-to-missing', __( 'Reassignment co-author does not exist', 'co-authors-plus' ) );
 
1186
 
1187
  $reassign_to_term = $coauthors_plus->get_author_term( $reassign_to_author );
1188
  // In the case where the guest author and its linked account shared the same term, we don't want to reassign
1189
- if ( $guest_author_term->term_id != $reassign_to_term->term_id )
1190
  wp_delete_term( $guest_author_term->term_id, $coauthors_plus->coauthor_taxonomy, array( 'default' => $reassign_to_term->term_id, 'force_default' => true ) );
1191
-
1192
  } else {
1193
  wp_delete_term( $guest_author_term->term_id, $coauthors_plus->coauthor_taxonomy );
1194
  }
@@ -1213,25 +1281,28 @@ class CoAuthors_Guest_Authors
1213
  function create_guest_author_from_user_id( $user_id ) {
1214
 
1215
  $user = get_user_by( 'id', $user_id );
1216
- if ( ! $user )
1217
  return new WP_Error( 'invalid-user', __( 'No user exists with that ID', 'co-authors-plus' ) );
 
1218
 
1219
  $guest_author = array();
1220
- foreach( $this->get_guest_author_fields() as $field ) {
1221
  $key = $field['key'];
1222
- if ( ! empty( $user->$key ) )
1223
- $guest_author[$key] = $user->$key;
1224
- else
1225
- $guest_author[$key] = '';
 
1226
  }
1227
  // Don't need the old user ID
1228
  unset( $guest_author['ID'] );
1229
  // Retain the user mapping and try to produce an unique user_login based on the name.
1230
  $guest_author['linked_account'] = $guest_author['user_login'];
1231
- if ( ! empty( $guest_author['display_name'] ) && $guest_author['display_name'] != $guest_author['user_login'] )
1232
  $guest_author['user_login'] = sanitize_title( $guest_author['display_name'] );
1233
- else if ( ! empty( $guest_author['first_name'] ) && ! empty( $guest_author['last_name'] ) )
1234
  $guest_author['user_login'] = sanitize_title( $guest_author['first_name'] . ' ' . $guest_author['last_name'] );
 
1235
 
1236
  $retval = $this->create( $guest_author );
1237
  return $retval;
@@ -1244,11 +1315,13 @@ class CoAuthors_Guest_Authors
1244
  */
1245
  function filter_wp_insert_post_empty_content( $maybe_empty, $postarr ) {
1246
 
1247
- if ( $this->post_type != $postarr['post_type'] )
1248
  return $maybe_empty;
 
1249
 
1250
- if ( empty( $postarr['post_title'] ) )
1251
  return true;
 
1252
 
1253
  return $maybe_empty;
1254
  }
@@ -1265,9 +1338,9 @@ class CoAuthors_Guest_Authors
1265
  */
1266
  function filter_user_row_actions( $actions, $user_object ) {
1267
 
1268
- if ( ! current_user_can( $this->list_guest_authors_cap )
1269
- || is_network_admin() )
1270
  return $actions;
 
1271
 
1272
  $new_actions = array();
1273
  if ( $guest_author = $this->get_guest_author_by( 'linked_account', $user_object->user_login ) ) {
@@ -1279,7 +1352,7 @@ class CoAuthors_Guest_Authors
1279
  'user_id' => $user_object->ID,
1280
  'nonce' => wp_create_nonce( 'create-guest-author' ),
1281
  );
1282
- $create_guest_author_link = add_query_arg( $query_args, admin_url( $this->parent_page ) );
1283
  if ( apply_filters( 'coauthors_show_create_profile_user_link', false ) ) {
1284
  $new_actions['create-guest-author'] = '<a href="' . esc_url( $create_guest_author_link ) . '">' . __( 'Create Profile', 'co-authors-plus' ) . '</a>';
1285
  }
@@ -1294,18 +1367,21 @@ class CoAuthors_Guest_Authors
1294
  * @since 3.0
1295
  */
1296
  function filter_get_avatar( $avatar, $id_or_email, $size, $default ) {
1297
- if ( is_object( $id_or_email ) || !is_email( $id_or_email ) )
1298
  return $avatar;
 
1299
 
1300
  // See if this matches a guest author
1301
  $guest_author = $this->get_guest_author_by( 'user_email', $id_or_email );
1302
- if ( ! $guest_author )
1303
  return $avatar;
 
1304
 
1305
  $thumbnail = $this->get_guest_author_thumbnail( $guest_author, $size );
1306
 
1307
- if ( $thumbnail )
1308
  return $thumbnail;
 
1309
 
1310
  return $avatar;
1311
  }
@@ -1319,19 +1395,20 @@ class CoAuthors_Guest_Authors
1319
 
1320
  // If we're using this at the top of the loop on author.php,
1321
  // our queried object should be set correctly
1322
- if ( !$author_nicename && is_author() && get_queried_object() )
1323
  $author_nicename = get_queried_object()->user_nicename;
 
1324
 
1325
- if ( empty($link) ) {
1326
- $link = add_query_arg( 'author_name', $author_nicename, home_url() );
1327
  } else {
1328
  global $wp_rewrite;
1329
  $link = $wp_rewrite->get_author_permastruct();
1330
  if ( $link ) {
1331
- $link = str_replace('%author%', $author_nicename, $link);
1332
  $link = home_url( user_trailingslashit( $link ) );
1333
  } else {
1334
- $link = add_query_arg( 'author_name', $author_nicename, home_url() );
1335
  }
1336
  }
1337
  return $link;
@@ -1352,16 +1429,16 @@ class CoAuthors_Guest_Authors
1352
  return $feed_link;
1353
  }
1354
 
1355
- // Get author, then check if author is guest-author because
1356
  // that's the only type that will need to be adjusted
1357
  $author = get_queried_object();
1358
- if ( empty ( $author ) || 'guest-author' != $author->type ) {
1359
  return $feed_link;
1360
  }
1361
 
1362
- // The next section is similar to
1363
  // get_author_feed_link() in wp-includes/link-template.php
1364
- $permalink_structure = get_option('permalink_structure');
1365
 
1366
  if ( empty( $feed ) ) {
1367
  $feed = get_default_feed();
@@ -1371,11 +1448,10 @@ class CoAuthors_Guest_Authors
1371
  $link = home_url( "?feed=$feed&amp;author=" . $author->ID );
1372
  } else {
1373
  $link = get_author_posts_url( $author->ID );
1374
- $feed_link = ( $feed == get_default_feed() ) ? 'feed' : "feed/$feed";
1375
- $link = trailingslashit($link) . user_trailingslashit($feed_link, 'feed');
1376
  }
1377
 
1378
  return $link;
1379
  }
1380
-
1381
  }
125
  // Some of the common sizes used by get_avatar
126
  $this->avatar_sizes = array(
127
  32,
128
+ 50,
129
  64,
130
  96,
131
+ 128,
132
  );
133
  $this->avatar_sizes = apply_filters( 'coauthors_guest_author_avatar_sizes', $this->avatar_sizes );
134
+ foreach ( $this->avatar_sizes as $size ) {
135
  add_image_size( 'guest-author-' . $size, $size, $size, true );
136
  }
137
 
149
  function filter_post_updated_messages( $messages ) {
150
  global $post;
151
 
152
+ if ( $this->post_type !== $post->post_type ) {
153
+ return $messages;
154
+ }
155
+
156
  $guest_author = $this->get_guest_author_by( 'ID', $post->ID );
157
  $guest_author_link = $this->filter_author_link( '', $guest_author->ID, $guest_author->user_nicename );
158
 
159
+ $messages[ $this->post_type ] = array(
160
  0 => '', // Unused. Messages start at index 1.
161
  1 => sprintf( __( 'Guest author updated. <a href="%s">View profile</a>', 'co-authors-plus' ), esc_url( $guest_author_link ) ),
162
  2 => __( 'Custom field updated.', 'co-authors-plus' ),
163
  3 => __( 'Custom field deleted.', 'co-authors-plus' ),
164
  4 => __( 'Guest author updated.', 'co-authors-plus' ),
165
  /* translators: %s: date and time of the revision */
166
+ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Guest author restored to revision from %s', 'co-authors-plus' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
167
  6 => sprintf( __( 'Guest author updated. <a href="%s">View profile</a>', 'co-authors-plus' ), esc_url( $guest_author_link ) ),
168
  7 => __( 'Guest author saved.', 'co-authors-plus' ),
169
  8 => sprintf( __( 'Guest author submitted. <a target="_blank" href="%s">Preview profile</a>', 'co-authors-plus' ), esc_url( add_query_arg( 'preview', 'true', $guest_author_link ) ) ),
170
  9 => sprintf( __( 'Guest author scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview profile</a>', 'co-authors-plus' ),
171
+ // translators: Publish box date format, see http://php.net/date
172
  date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( $guest_author_link ) ),
173
+ 10 => sprintf( __( 'Guest author updated. <a target="_blank" href="%s">Preview profile</a>', 'co-authors-plus' ), esc_url( add_query_arg( 'preview', 'true', $guest_author_link ) ) ),
174
  );
175
  return $messages;
176
  }
183
  */
184
  function handle_create_guest_author_action() {
185
 
186
+ if ( ! isset( $_GET['action'], $_GET['nonce'], $_GET['user_id'] ) || 'cap-create-guest-author' !== $_GET['action'] ) {
187
  return;
188
+ }
189
 
190
+ if ( ! wp_verify_nonce( $_GET['nonce'], 'create-guest-author' ) ) {
191
+ wp_die( esc_html__( "Doin' something fishy, huh?", 'co-authors-plus' ) );
192
+ }
193
 
194
+ if ( ! current_user_can( $this->list_guest_authors_cap ) ) {
195
+ wp_die( esc_html__( "You don't have permission to perform this action.", 'co-authors-plus' ) );
196
+ }
197
 
198
  $user_id = intval( $_GET['user_id'] );
199
 
200
  // Create the guest author
201
  $post_id = $this->create_guest_author_from_user_id( $user_id );
202
+ if ( is_wp_error( $post_id ) ) {
203
+ wp_die( esc_html( $post_id->get_error_message() ) );
204
+ }
205
 
206
  // Redirect to the edit Guest Author screen
207
  $edit_link = get_edit_post_link( $post_id, 'redirect' );
208
  $redirect_to = add_query_arg( 'message', 'guest-author-created', $edit_link );
209
+ wp_safe_redirect( esc_url_raw( $redirect_to ) );
210
  exit;
211
 
212
  }
219
  function handle_delete_guest_author_action() {
220
  global $coauthors_plus;
221
 
222
+ if ( ! isset( $_POST['action'], $_POST['reassign'], $_POST['_wpnonce'], $_POST['id'] ) || 'delete-guest-author' != $_POST['action'] ) {
223
  return;
224
+ }
225
 
226
  // Verify the user is who they say they are
227
+ if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'delete-guest-author' ) ) {
228
+ wp_die( esc_html__( "Doin' something fishy, huh?", 'co-authors-plus' ) );
229
+ }
230
 
231
  // Make sure they can perform the action
232
+ if ( ! current_user_can( $this->list_guest_authors_cap ) ) {
233
+ wp_die( esc_html__( "You don't have permission to perform this action.", 'co-authors-plus' ) );
234
+ }
235
 
236
  // Make sure the guest author actually exists
237
+ $guest_author = $this->get_guest_author_by( 'ID', (int) $_POST['id'] );
238
+ if ( ! $guest_author ) {
239
+ wp_die( esc_html( sprintf( __( "%s can't be deleted because it doesn't exist.", 'co-authors-plus' ), $this->labels['singular'] ) ) );
240
+ }
241
 
242
  // Perform the reassignment if needed
243
  $guest_author_term = $coauthors_plus->get_author_term( $guest_author );
244
+ switch ( $_POST['reassign'] ) {
245
  // Leave assigned to the current linked account
246
  case 'leave-assigned':
247
  $reassign_to = $guest_author->linked_account;
250
  case 'reassign-another':
251
  $user_nicename = sanitize_title( $_POST['leave-assigned-to'] );
252
  $reassign_to = $coauthors_plus->get_coauthor_by( 'user_nicename', $user_nicename );
253
+ if ( ! $reassign_to ) {
254
+ wp_die( esc_html__( 'Co-author does not exists. Try again?', 'co-authors-plus' ) );
255
+ }
256
  $reassign_to = $reassign_to->user_login;
257
  break;
258
  // Remove the byline, but don't delete the post
260
  $reassign_to = false;
261
  break;
262
  default:
263
+ wp_die( esc_html__( 'Please make sure to pick an option.', 'co-authors-plus' ) );
264
  break;
265
  }
266
 
269
  $args = array(
270
  'page' => 'view-guest-authors',
271
  );
272
+ if ( is_wp_error( $retval ) ) {
273
  $args['message'] = 'delete-error';
274
+ } else {
275
  $args['message'] = 'guest-author-deleted';
276
+ }
277
 
278
  // Redirect to safety
279
+ $redirect_to = add_query_arg( array_map( 'rawurlencode', $args ), admin_url( $this->parent_page ) );
280
+ wp_safe_redirect( esc_url_raw( $redirect_to ) );
281
  exit;
282
  }
283
 
289
  function handle_ajax_search_coauthors_to_assign() {
290
  global $coauthors_plus;
291
 
292
+ if ( ! current_user_can( $this->list_guest_authors_cap ) ) {
293
  die();
294
+ }
295
 
296
  $search = sanitize_text_field( $_GET['q'] );
297
+ if ( ! empty( $_GET['guest_author'] ) ) {
298
+ $ignore = array( $this->get_guest_author_by( 'ID', (int) $_GET['guest_author'] )->user_login );
299
+ } else {
300
  $ignore = array();
301
+ }
302
 
303
  $results = wp_list_pluck( $coauthors_plus->search_authors( $search, $ignore ), 'user_login' );
304
  $retval = array();
305
+ foreach ( $results as $user_login ) {
306
  $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $user_login );
307
+ $retval[] = (object) array(
308
  'display_name' => $coauthor->display_name,
309
  'user_login' => $coauthor->user_login,
310
  'id' => $coauthor->user_nicename,
311
  );
312
  }
313
+ echo wp_json_encode( $retval );
314
  die();
315
  }
316
 
322
  */
323
  function action_parse_request( $query ) {
324
 
325
+ if ( ! isset( $query->query_vars['author_name'] ) ) {
326
  return $query;
327
+ }
328
 
329
  // No redirection needed on admin requests
330
+ if ( is_admin() ) {
331
  return $query;
332
+ }
333
 
334
  $coauthor = $this->get_guest_author_by( 'linked_account', sanitize_title( $query->query_vars['author_name'] ) );
335
  if ( is_object( $coauthor ) && $query->query_vars['author_name'] != $coauthor->user_login ) {
336
  global $wp_rewrite;
337
  $link = $wp_rewrite->get_author_permastruct();
338
 
339
+ if ( empty( $link ) ) {
340
  $file = home_url( '/' );
341
  $link = $file . '?author_name=' . $coauthor->user_login;
342
  } else {
343
+ $link = str_replace( '%author%', $coauthor->user_login, $link );
344
  $link = home_url( user_trailingslashit( $link ) );
345
  }
346
  wp_safe_redirect( $link );
369
  function action_admin_enqueue_scripts() {
370
  global $pagenow;
371
  // Enqueue our guest author CSS on the related pages
372
+ if ( $this->parent_page === $pagenow && isset( $_GET['page'] ) && 'view-guest-authors' === $_GET['page'] ) {
373
  wp_enqueue_script( 'jquery-select2', plugins_url( 'lib/select2/select2.min.js', dirname( __FILE__ ) ), array( 'jquery' ), COAUTHORS_PLUS_VERSION );
374
  wp_enqueue_style( 'cap-jquery-select2-css', plugins_url( 'lib/select2/select2.css', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
375
 
376
  wp_enqueue_style( 'guest-authors-css', plugins_url( 'css/guest-authors.css', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
377
  wp_enqueue_script( 'guest-authors-js', plugins_url( 'js/guest-authors.js', dirname( __FILE__ ) ), false, COAUTHORS_PLUS_VERSION );
378
+ } else if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) && $this->post_type === get_post_type() ) {
379
  add_action( 'admin_head', array( $this, 'change_title_icon' ) );
380
  }
381
  }
404
  function action_admin_notices() {
405
  global $pagenow;
406
 
407
+ if ( $this->parent_page != $pagenow || ! isset( $_REQUEST['message'] ) ) {
408
  return;
409
+ }
410
 
411
+ switch ( $_REQUEST['message'] ) {
412
  case 'guest-author-deleted':
413
  $message = __( 'Guest author deleted.', 'co-authors-plus' );
414
  break;
417
  break;
418
  }
419
 
420
+ if ( $message ) {
421
  echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
422
+ }
423
  }
424
 
425
  /**
434
  // Remove the submitpost metabox because we have our own
435
  remove_meta_box( 'submitdiv', $this->post_type, 'side' );
436
  remove_meta_box( 'slugdiv', $this->post_type, 'normal' );
437
+ add_meta_box( 'coauthors-manage-guest-author-save', __( 'Save', 'co-authors-plus' ), array( $this, 'metabox_manage_guest_author_save' ), $this->post_type, 'side', 'default' );
438
+ add_meta_box( 'coauthors-manage-guest-author-slug', __( 'Unique Slug', 'co-authors-plus' ), array( $this, 'metabox_manage_guest_author_slug' ), $this->post_type, 'side', 'default' );
439
  // Our metaboxes with co-author details
440
+ add_meta_box( 'coauthors-manage-guest-author-name', __( 'Name', 'co-authors-plus' ), array( $this, 'metabox_manage_guest_author_name' ), $this->post_type, 'normal', 'default' );
441
+ add_meta_box( 'coauthors-manage-guest-author-contact-info', __( 'Contact Info', 'co-authors-plus' ), array( $this, 'metabox_manage_guest_author_contact_info' ), $this->post_type, 'normal', 'default' );
442
  add_meta_box( 'coauthors-manage-guest-author-bio', $this->labels['metabox_about'], array( $this, 'metabox_manage_guest_author_bio' ), $this->post_type, 'normal', 'default' );
443
  }
444
  }
453
  // Allow guest authors to be deleted
454
  if ( isset( $_GET['action'], $_GET['id'], $_GET['_wpnonce'] ) && 'delete' == $_GET['action'] ) {
455
  // Make sure the user is who they say they are
456
+ if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'guest-author-delete' ) ) {
457
+ wp_die( esc_html__( "Doin' something fishy, huh?", 'co-authors-plus' ) );
458
+ }
459
 
460
  // Make sure the guest author actually exists
461
+ $guest_author = $this->get_guest_author_by( 'ID', (int) $_GET['id'] );
462
+ if ( ! $guest_author ) {
463
+ wp_die( esc_html( sprintf( __( "%s can't be deleted because it doesn't exist.", 'co-authors-plus' ), $this->labels['singular'] ) ) );
464
+ }
465
 
466
  echo '<div class="wrap">';
467
  echo '<div class="icon32" id="icon-users"><br/></div>';
468
+ echo '<h2>' . esc_html( sprintf( __( 'Delete %s', 'co-authors-plus ' ), $this->labels['plural'] ) ) . '</h2>';
469
+ echo '<p>' . esc_html( sprintf( __( 'You have specified this %s for deletion:', 'co-authors-plus' ), strtolower( $this->labels['singular'] ) ) ) . '</p>';
470
+ echo '<p>#' . esc_html( $guest_author->ID . ': ' . $guest_author->display_name ) . '</p>';
471
+ echo '<p>' . esc_html( sprintf( __( 'What should be done with posts assigned to this %s?', 'co-authors-plus' ), strtolower( $this->labels['singular'] ) ) ) . '</p>';
472
+ echo '<p class="description">' . esc_html( sprintf( __( "Note: If you'd like to delete the %s and all of their posts, you should delete their posts first and then come back to delete the %s.", 'co-authors-plus' ), strtolower( $this->labels['singular'] ), strtolower( $this->labels['singular'] ) ) ) . '</p>';
473
  echo '<form method="POST" action="' . esc_url( add_query_arg( 'page', 'view-guest-authors', admin_url( $this->parent_page ) ) ) . '">';
474
  // Hidden stuffs
475
  echo '<input type="hidden" name="action" value="delete-guest-author" />';
476
  wp_nonce_field( 'delete-guest-author' );
477
+ echo '<input type="hidden" id="id" name="id" value="' . esc_attr( (int) $_GET['id'] ) . '" />';
478
  echo '<fieldset><ul style="list-style-type:none;">';
479
  // Reassign to another user
480
  echo '<li class="hide-if-no-js"><label for="reassign-another">';
481
+ echo '<input type="radio" id="reassign-another" name="reassign" class="reassign-option" value="reassign-another" />&nbsp;&nbsp;' . esc_html__( 'Reassign to another co-author:', 'co-authors-plus' ) . '&nbsp;&nbsp;</label>';
482
  echo '<input type="hidden" id="leave-assigned-to" name="leave-assigned-to" style="width:200px;" />';
483
  echo '</li>';
484
  // Leave mapped to a linked account
485
  if ( get_user_by( 'login', $guest_author->linked_account ) ) {
486
  echo '<li><label for="leave-assigned">';
487
+ echo '<input type="radio" id="leave-assigned" class="reassign-option" name="reassign" value="leave-assigned" />&nbsp;&nbsp;' . esc_html( sprintf( __( 'Leave posts assigned to the mapped user, %s.', 'co-authors-plus' ) ), $guest_author->linked_account );
488
  echo '</label></li>';
489
  }
490
  // Remove bylines from the posts
491
  echo '<li><label for="remove-byline">';
492
+ echo '<input type="radio" id="remove-byline" class="reassign-option" name="reassign" value="remove-byline" />&nbsp;&nbsp;' . esc_html__( 'Remove byline from posts (but leave each post in its current status).', 'co-authors-plus' );
493
  echo '</label></li>';
494
  echo '</ul></fieldset>';
495
  submit_button( __( 'Confirm Deletion', 'co-authors-plus' ), 'secondary', 'submit', true, array( 'disabled' => 'disabled' ) );
498
  } else {
499
  echo '<div class="wrap">';
500
  echo '<div class="icon32" id="icon-users"><br/></div>';
501
+ echo '<h2>' . esc_html( $this->labels['plural'] );
502
  // @todo caps check for creating a new user
503
  $add_new_link = admin_url( "post-new.php?post_type=$this->post_type" );
504
+ echo '<a href="' . esc_url( $add_new_link ) . '" class="add-new-h2">' . esc_html__( 'Add New', 'co-authors-plus' ) . '</a>';
505
  echo '</h2>';
506
  $cap_list_table = new CoAuthors_WP_List_Table();
507
  $cap_list_table->prepare_items();
522
  function metabox_manage_guest_author_save() {
523
  global $post, $coauthors_plus;
524
 
525
+ if ( in_array( $post->post_status, array( 'pending', 'publish', 'draft' ) ) ) {
526
  $button_text = $this->labels['update_item'];
527
+ } else {
528
  $button_text = $this->labels['add_new_item'];
529
+ }
530
  submit_button( $button_text, 'primary', 'publish', false );
531
 
532
  // Secure all of our requests
550
  // Taken from grist_authors.
551
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
552
  $linked_account = get_post_meta( $post->ID, $linked_account_key, true );
553
+ if ( $user = get_user_by( 'login', $linked_account ) ) {
554
  $linked_account_id = $user->ID;
555
+ } else {
556
  $linked_account_id = -1;
557
+ }
558
 
559
  // If user_login is the same as linked account, don't let the association be removed
560
+ if ( $linked_account == $existing_slug ) {
561
  add_filter( 'wp_dropdown_users', array( $this, 'filter_wp_dropdown_users_to_disable' ) );
562
+ }
563
 
564
  $linked_account_user_ids = wp_list_pluck( $this->get_all_linked_accounts(), 'ID' );
565
+ if ( false !== ( $key = array_search( $linked_account_id, $linked_account_user_ids ) ) ) {
566
+ unset( $linked_account_user_ids[ $key ] );
567
+ }
568
 
569
+ echo '<p><label>' . esc_html__( 'WordPress User Mapping', 'co-authors-plus' ) . '</label> ';
570
+ wp_dropdown_users( apply_filters( 'coauthors_guest_author_linked_account_args', array(
571
  'show_option_none' => __( '-- Not mapped --', 'co-authors-plus' ),
572
  'name' => esc_attr( $this->get_post_meta_key( 'linked_account' ) ),
573
  // If we're adding an author or if there is no post author (0), then use -1 (which is show_option_none).
575
  'selected' => $linked_account_id,
576
  // Don't let user accounts to be linked to more than one guest author
577
  'exclude' => $linked_account_user_ids,
578
+ ) ) );
579
  echo '</p>';
580
 
581
  remove_filter( 'wp_dropdown_users', array( $this, 'filter_wp_dropdown_users_to_disable' ) );
601
 
602
  $fields = $this->get_guest_author_fields( 'name' );
603
  echo '<table class="form-table"><tbody>';
604
+ foreach ( $fields as $field ) {
605
  $pm_key = $this->get_post_meta_key( $field['key'] );
606
  $value = get_post_meta( $post->ID, $pm_key, true );
607
  echo '<tr><th>';
608
+ echo '<label for="' . esc_attr( $pm_key ) . '">' . esc_html( $field['label'] ) . '</label>';
609
  echo '</th><td>';
610
+
611
+ if ( ! isset( $field['input'] ) ) {
612
+ $field['input'] = 'text';
613
  }
614
  $field['input'] = apply_filters( 'coauthors_name_field_type_'. $pm_key , $field['input'] );
615
+ switch ( $field['input'] ) {
616
+ case 'checkbox':
617
  echo '<input type="checkbox" name="' . esc_attr( $pm_key ) . '"'. checked( '1', $value, false ) .' value="1"/>';
618
  break;
619
  default:
620
  echo '<input type="'. esc_attr( $field['input'] ) .'" name="' . esc_attr( $pm_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text" />';
621
  break;
622
+ }
623
  echo '</td></tr>';
624
  }
625
  echo '</tbody></table>';
636
 
637
  $fields = $this->get_guest_author_fields( 'contact-info' );
638
  echo '<table class="form-table"><tbody>';
639
+ foreach ( $fields as $field ) {
640
  $pm_key = $this->get_post_meta_key( $field['key'] );
641
  $value = get_post_meta( $post->ID, $pm_key, true );
642
  echo '<tr><th>';
643
+ echo '<label for="' . esc_attr( $pm_key ) . '">' . esc_html( $field['label'] ) . '</label>';
644
  echo '</th><td>';
645
+
646
+ if ( ! isset( $field['input'] ) ) {
647
+ $field['input'] = 'text';
648
  }
649
  $field['input'] = apply_filters( 'coauthors_name_field_type_'. $pm_key , $field['input'] );
650
+ switch ( $field['input'] ) {
651
+ case 'checkbox':
652
  echo '<input type="checkbox" name="' . esc_attr( $pm_key ) . '"'. checked( '1', $value, false ) .' value="1"/>';
653
  break;
654
  default:
655
  echo '<input type="'. esc_attr( $field['input'] ) .'" name="' . esc_attr( $pm_key ) . '" value="' . esc_attr( $value ) . '" class="regular-text" />';
656
  break;
657
+ }
658
 
659
  echo '</td></tr>';
660
  }
672
 
673
  $fields = $this->get_guest_author_fields( 'about' );
674
  echo '<table class="form-table"><tbody>';
675
+ foreach ( $fields as $field ) {
676
  $pm_key = $this->get_post_meta_key( $field['key'] );
677
  $value = get_post_meta( $post->ID, $pm_key, true );
678
  echo '<tr><th>';
679
+ echo '<label for="' . esc_attr( $pm_key . '">' ) . esc_html( $field['label'] ) . '</label>';
680
  echo '</th><td>';
681
  echo '<textarea style="width:300px;margin-bottom:6px;" name="' . esc_attr( $pm_key ) . '">' . esc_textarea( $value ) . '</textarea>';
682
  echo '</td></tr>';
693
  */
694
  function manage_guest_author_filter_post_data( $post_data, $original_args ) {
695
 
696
+ if ( $post_data['post_type'] != $this->post_type ) {
697
  return $post_data;
698
+ }
699
 
700
  // @todo caps check
701
+ if ( ! isset( $_POST['guest-author-nonce'] ) || ! wp_verify_nonce( $_POST['guest-author-nonce'], 'guest-author-nonce' ) ) {
702
  return $post_data;
703
+ }
704
 
705
  // Validate the display name
706
  if ( empty( $_POST['cap-display_name'] ) ) {
707
+ wp_die( esc_html__( 'Guest authors cannot be created without display names.', 'co-authors-plus' ) );
708
  }
709
  $post_data['post_title'] = sanitize_text_field( $_POST['cap-display_name'] );
710
 
711
  $slug = sanitize_title( get_post_meta( $original_args['ID'], $this->get_post_meta_key( 'user_login' ), true ) );
712
+ if ( ! $slug ) {
713
  $slug = sanitize_title( $_POST['cap-display_name'] );
714
+ }
715
+
716
  // Uh oh, no guest authors without slugs
717
+ if ( ! $slug ) {
718
+ wp_die( esc_html__( 'Guest authors cannot be created without display names.', 'co-authors-plus' ) );
719
+ }
720
  $post_data['post_name'] = $this->get_post_meta_key( $slug );
721
 
722
  // Guest authors can't be created with the same user_login as a user
723
  $user_nicename = str_replace( 'cap-', '', $slug );
724
  $user = get_user_by( 'slug', $user_nicename );
725
+ if ( $user
726
  && is_user_member_of_blog( $user->ID, get_current_blog_id() )
727
+ && $user->user_login != get_post_meta( $original_args['ID'], $this->get_post_meta_key( 'linked_account' ), true ) ) {
728
+ wp_die( esc_html__( 'Guest authors cannot be created with the same user_login value as a user. Try creating a profile from the user on the Manage Users listing instead.', 'co-authors-plus' ) );
729
+ }
730
 
731
  // Guest authors can't have the same post_name value
732
  $guest_author = $this->get_guest_author_by( 'post_name', $post_data['post_name'] );
733
+ if ( $guest_author && $guest_author->ID != $original_args['ID'] ) {
734
+ wp_die( esc_html__( 'Display name conflicts with another guest author display name.', 'co-authors-plus' ) );
735
+ }
736
 
737
  return $post_data;
738
  }
745
  function manage_guest_author_save_meta_fields( $post_id, $post ) {
746
  global $coauthors_plus;
747
 
748
+ if ( $post->post_type != $this->post_type ) {
749
  return;
750
+ }
751
 
752
  // @todo caps check
753
+ if ( ! isset( $_POST['guest-author-nonce'] ) || ! wp_verify_nonce( $_POST['guest-author-nonce'], 'guest-author-nonce' ) ) {
754
  return;
755
+ }
756
 
757
  // Save our data to post meta
758
  $author_fields = $this->get_guest_author_fields();
759
+ foreach ( $author_fields as $author_field ) {
760
 
761
  $key = $this->get_post_meta_key( $author_field['key'] );
762
  // 'user_login' should only be saved on post update if it doesn't exist
763
+ if ( 'user_login' == $author_field['key'] && ! get_post_meta( $post_id, $key, true ) ) {
764
  $display_name_key = $this->get_post_meta_key( 'display_name' );
765
+ $temp_slug = sanitize_title( $_POST[ $display_name_key ] );
766
  update_post_meta( $post_id, $key, $temp_slug );
767
  continue;
768
  }
769
  if ( 'linked_account' == $author_field['key'] ) {
770
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
771
+ if ( ! empty( $_POST[ $linked_account_key ] ) ) {
772
+ $user_id = intval( $_POST[ $linked_account_key ] );
773
+ } else {
774
  continue;
775
+ }
776
  $user = get_user_by( 'id', $user_id );
777
+ if ( $user_id > 0 && is_object( $user ) ) {
778
  $user_login = $user->user_login;
779
+ } else {
780
  $user_login = '';
781
+ }
782
  update_post_meta( $post_id, $key, $user_login );
783
  continue;
784
  }
785
 
786
+ if ( isset( $author_field['input'] ) && 'checkbox' === $author_field['input'] && ! isset( $_POST[ $key ] ) ) {
787
  delete_post_meta( $post_id, $key );
788
+ }
789
 
790
+ if ( ! isset( $_POST[ $key ] ) ) {
791
  continue;
792
+ }
793
+
794
+ if ( isset( $author_field['sanitize_function'] ) && is_callable( $author_field['sanitize_function'] ) ) {
795
+ $value = call_user_func( $author_field['sanitize_function'], $_POST[ $key ] );
796
+ } else {
797
+ $value = sanitize_text_field( $_POST[ $key ] );
798
+ }
799
  update_post_meta( $post_id, $key, $value );
800
  }
801
 
803
  $author_term = $coauthors_plus->update_author_term( $author );
804
  // Add the author as a post term
805
  wp_set_post_terms( $post_id, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy, false );
806
+
807
+ // Explicitly clear all caches, to remove negative caches that may have existed prior to this
808
+ // Guest Author's creation / update
809
+ $this->delete_guest_author_cache( $post_id );
810
  }
811
 
812
  /**
826
 
827
  if ( false == $force && false !== ( $retval = wp_cache_get( $cache_key, self::$cache_group ) ) ) {
828
  // Properly catch our false condition cache
829
+ if ( is_object( $retval ) ) {
830
  return $retval;
831
+ } else {
832
  return false;
833
+ }
834
  }
835
 
836
+ switch ( $key ) {
837
  case 'ID':
838
  case 'id':
839
+ $query = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID=%d AND post_type = %s", $value, $this->post_type );
840
  $post_id = $wpdb->get_var( $query );
841
  if ( empty( $post_id ) ) {
842
  $post_id = '0';
855
  case 'user_login':
856
  case 'linked_account':
857
  case 'user_email':
858
+ if ( 'login' == $key ) {
859
  $key = 'user_login';
860
+ }
861
  // Ensure we aren't doing the lookup by the prefixed value
862
+ if ( 'user_login' == $key ) {
863
  $value = preg_replace( '#^cap\-#', '', $value );
864
+ }
865
  $query = $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key=%s AND meta_value=%s;", $this->get_post_meta_key( $key ), $value );
866
  $post_id = $wpdb->get_var( $query );
867
  if ( empty( $post_id ) ) {
868
+ if ( 'user_login' == $key ) {
869
  return $this->get_guest_author_by( 'post_name', $value ); // fallback to post_name in case the guest author isn't a linked account
870
+ }
871
  $post_id = '0';
872
  }
873
  break;
888
 
889
  // Load the guest author fields
890
  $fields = $this->get_guest_author_fields();
891
+ foreach ( $fields as $field ) {
892
  $key = $field['key'];
893
  $pm_key = $this->get_post_meta_key( $field['key'] );
894
+ $guest_author[ $key ] = get_post_meta( $post_id, $pm_key, true );
895
  }
896
  // Support for non-Latin characters. They're stored as urlencoded slugs
897
  $guest_author['user_login'] = urldecode( $guest_author['user_login'] );
900
  $guest_author['user_nicename'] = sanitize_title( $guest_author['user_login'] );
901
  $guest_author['type'] = 'guest-author';
902
 
903
+ wp_cache_set( $cache_key, (object) $guest_author, self::$cache_group );
904
 
905
+ return (object) $guest_author;
906
  }
907
 
908
  /**
914
  */
915
  function get_guest_author_thumbnail( $guest_author, $size ) {
916
  // See if the guest author has an avatar
917
+ if ( ! has_post_thumbnail( $guest_author->ID ) ) {
918
  return null;
919
+ }
920
 
921
  $args = array(
922
  'class' => "avatar avatar-{$size} photo",
923
  );
924
+ if ( in_array( $size, $this->avatar_sizes ) ) {
925
  $size = 'guest-author-' . $size;
926
+ } else {
927
  $size = array( $size, $size );
928
+ }
929
 
930
  $thumbnail = get_the_post_thumbnail( $guest_author->ID, $size, $args );
931
 
939
  */
940
  function get_guest_author_fields( $groups = 'all' ) {
941
 
942
+ $groups = (array) $groups;
943
  $global_fields = array(
944
  // Hidden (included in object, no UI elements)
945
  array(
951
  // Name
952
  array(
953
  'key' => 'display_name',
954
+ 'label' => __( 'Display Name', 'co-authors-plus' ),
955
  'group' => 'name',
956
  'required' => true,
957
  ),
958
  array(
959
  'key' => 'first_name',
960
+ 'label' => __( 'First Name', 'co-authors-plus' ),
961
  'group' => 'name',
962
  ),
963
  array(
964
  'key' => 'last_name',
965
+ 'label' => __( 'Last Name', 'co-authors-plus' ),
966
  'group' => 'name',
967
  ),
968
  array(
969
  'key' => 'user_login',
970
+ 'label' => __( 'Slug', 'co-authors-plus' ),
971
  'group' => 'slug',
972
  'required' => true,
973
  ),
1012
  ),
1013
  );
1014
  $fields_to_return = array();
1015
+ foreach ( $global_fields as $single_field ) {
1016
+ if ( in_array( $single_field['group'], $groups ) || 'all' === $groups[0] && 'hidden' !== $single_field['group'] ) {
1017
  $fields_to_return[] = $single_field;
1018
+ }
1019
  }
1020
 
1021
  return apply_filters( 'coauthors_guest_author_fields', $fields_to_return, $groups );
1030
  */
1031
  function get_post_meta_key( $key ) {
1032
 
1033
+ if ( 0 !== stripos( $key, 'cap-' ) ) {
1034
  $key = 'cap-' . $key;
1035
+ }
1036
 
1037
  return $key;
1038
  }
1042
  *
1043
  * @param string $key A guest author field
1044
  * @param string $value The guest author field value
1045
+ *
1046
  * @return string The generated cache key
1047
  */
1048
  function get_cache_key( $key, $value ) {
1049
  // Normalize $key and $value
1050
+ switch ( $key ) {
1051
  case 'post_name':
1052
  $key = 'user_nicename';
1053
 
1054
+ if ( 0 === strpos( $value, 'cap-' ) ) {
1055
  $value = substr( $value, 4 );
1056
+ }
1057
 
1058
  break;
1059
 
1082
  if ( true === $force || false === $retval ) {
1083
  $user_logins = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key=%s AND meta_value !=''", $this->get_post_meta_key( 'linked_account' ) ) );
1084
  $users = array();
1085
+ foreach ( $user_logins as $user_login ) {
1086
  $user = get_user_by( 'login', $user_login );
1087
+ if ( ! $user ) {
1088
  continue;
1089
+ }
1090
  $users[] = array(
1091
  'ID' => $user->ID,
1092
  'user_login' => $user->user_login,
1106
  */
1107
  function filter_update_post_metadata( $retnull, $object_id, $meta_key, $meta_value, $prev_value ) {
1108
 
1109
+ if ( $this->post_type != get_post_type( $object_id ) ) {
1110
+ return $retnull;
1111
+ }
1112
 
1113
  // If the linked_account is changing, invalidate the cache of all linked accounts
1114
  // Don't regenerate though, as we haven't saved the new value
1115
  $linked_account_key = $this->get_post_meta_key( 'linked_account' );
1116
+ if ( $linked_account_key == $meta_key && get_post_meta( $object_id, $linked_account_key, true ) !== $meta_value ) {
1117
  $this->delete_guest_author_cache( $object_id );
1118
  }
1119
 
1120
  // If one of the guest author meta values has changed, we'll need to invalidate all keys
1121
+ if ( false !== strpos( $meta_key, 'cap-' ) && get_post_meta( $object_id, $meta_key, true ) !== $meta_value ) {
1122
  $this->delete_guest_author_cache( $object_id );
1123
  }
1124
 
1134
  */
1135
  public function delete_guest_author_cache( $id_or_object ) {
1136
 
1137
+ if ( is_object( $id_or_object ) ) {
1138
  $guest_author = $id_or_object;
1139
+ } else {
1140
+ $guest_author = $this->get_guest_author_by( 'ID', $id_or_object, true );
1141
+ }
1142
 
1143
  // Delete the lookup cache associated with each old co-author value
1144
  $keys = wp_list_pluck( $this->get_guest_author_fields(), 'key' );
1145
  $keys = array_merge( $keys, array( 'login', 'post_name', 'user_nicename', 'ID' ) );
1146
+ foreach ( $keys as $key ) {
1147
  $value_key = $key;
1148
 
1149
+ if ( 'post_name' == $key ) {
1150
+ $value_key = 'user_nicename';
1151
+ } else if ( 'login' == $key ) {
1152
+ $value_key = 'user_login';
1153
+ }
1154
 
1155
  $cache_key = $this->get_cache_key( $key, $guest_author->$value_key );
1156
 
1160
  // Delete the 'all-linked-accounts' cache
1161
  wp_cache_delete( 'all-linked-accounts', self::$cache_group );
1162
 
1163
+ }
1164
 
1165
 
1166
  /**
1173
 
1174
  // Validate the arguments that have been passed
1175
  $fields = $this->get_guest_author_fields();
1176
+ foreach ( $fields as $field ) {
1177
 
1178
  // Make sure required fields are there
1179
+ if ( isset( $field['required'] ) && $field['required'] && empty( $args[ $field['key'] ] ) ) {
1180
  return new WP_Error( 'field-required', sprintf( __( '%s is a required field', 'co-authors-plus' ), $field['key'] ) );
1181
  }
1182
 
1183
  // The user login field shouldn't collide with any existing users
1184
  if ( 'user_login' == $field['key'] && $existing_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $args['user_login'], true ) ) {
1185
+ if ( 'guest-author' == $existing_coauthor->type ) {
1186
  return new WP_Error( 'duplicate-field', __( 'user_login cannot duplicate existing guest author or mapped user', 'co-authors-plus' ) );
1187
+ }
1188
  }
 
1189
  }
1190
 
1191
  // Create the primary post object
1195
  'post_type' => $this->post_type,
1196
  );
1197
  $post_id = wp_insert_post( $new_post, true );
1198
+ if ( is_wp_error( $post_id ) ) {
1199
  return $post_id;
1200
+ }
1201
 
1202
  // Add all of the fields for the new guest author
1203
+ foreach ( $fields as $field ) {
1204
  $key = $field['key'];
1205
+ if ( empty( $args[ $key ] ) ) {
1206
  continue;
1207
+ }
1208
  $pm_key = $this->get_post_meta_key( $key );
1209
+ update_post_meta( $post_id, $pm_key, $args[ $key ] );
1210
  }
1211
 
1212
  // Make sure the author term exists and that we're assigning it to this post type
1213
  $author_term = $coauthors_plus->update_author_term( $this->get_guest_author_by( 'ID', $post_id ) );
1214
  wp_set_post_terms( $post_id, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy, false );
1215
 
1216
+ // Explicitly clear all caches, to remove negative caches that may have existed prior to this
1217
+ // Guest Author's creation
1218
+ $this->delete_guest_author_cache( $post_id );
1219
+
1220
  return $post_id;
1221
  }
1222
 
1233
  global $coauthors_plus;
1234
 
1235
  $guest_author = $this->get_guest_author_by( 'ID', $id );
1236
+ if ( ! $guest_author ) {
1237
  return new WP_Error( 'guest-author-missing', __( 'Guest author does not exist', 'co-authors-plus' ) );
1238
+ }
1239
 
1240
  $guest_author_term = $coauthors_plus->get_author_term( $guest_author );
1241
 
1242
  if ( $reassign_to ) {
1243
 
1244
  // We're reassigning the guest author's posts user to its linked account
1245
+ if ( $guest_author->linked_account == $reassign_to ) {
1246
  $reassign_to_author = get_user_by( 'login', $reassign_to );
1247
+ } else {
1248
  $reassign_to_author = $coauthors_plus->get_coauthor_by( 'user_login', $reassign_to );
1249
+ }
1250
+
1251
+ if ( ! $reassign_to_author ) {
1252
  return new WP_Error( 'reassign-to-missing', __( 'Reassignment co-author does not exist', 'co-authors-plus' ) );
1253
+ }
1254
 
1255
  $reassign_to_term = $coauthors_plus->get_author_term( $reassign_to_author );
1256
  // In the case where the guest author and its linked account shared the same term, we don't want to reassign
1257
+ if ( $guest_author_term->term_id != $reassign_to_term->term_id ) {
1258
  wp_delete_term( $guest_author_term->term_id, $coauthors_plus->coauthor_taxonomy, array( 'default' => $reassign_to_term->term_id, 'force_default' => true ) );
1259
+ }
1260
  } else {
1261
  wp_delete_term( $guest_author_term->term_id, $coauthors_plus->coauthor_taxonomy );
1262
  }
1281
  function create_guest_author_from_user_id( $user_id ) {
1282
 
1283
  $user = get_user_by( 'id', $user_id );
1284
+ if ( ! $user ) {
1285
  return new WP_Error( 'invalid-user', __( 'No user exists with that ID', 'co-authors-plus' ) );
1286
+ }
1287
 
1288
  $guest_author = array();
1289
+ foreach ( $this->get_guest_author_fields() as $field ) {
1290
  $key = $field['key'];
1291
+ if ( ! empty( $user->$key ) ) {
1292
+ $guest_author[ $key ] = $user->$key;
1293
+ } else {
1294
+ $guest_author[ $key ] = '';
1295
+ }
1296
  }
1297
  // Don't need the old user ID
1298
  unset( $guest_author['ID'] );
1299
  // Retain the user mapping and try to produce an unique user_login based on the name.
1300
  $guest_author['linked_account'] = $guest_author['user_login'];
1301
+ if ( ! empty( $guest_author['display_name'] ) && $guest_author['display_name'] != $guest_author['user_login'] ) {
1302
  $guest_author['user_login'] = sanitize_title( $guest_author['display_name'] );
1303
+ } else if ( ! empty( $guest_author['first_name'] ) && ! empty( $guest_author['last_name'] ) ) {
1304
  $guest_author['user_login'] = sanitize_title( $guest_author['first_name'] . ' ' . $guest_author['last_name'] );
1305
+ }
1306
 
1307
  $retval = $this->create( $guest_author );
1308
  return $retval;
1315
  */
1316
  function filter_wp_insert_post_empty_content( $maybe_empty, $postarr ) {
1317
 
1318
+ if ( $this->post_type != $postarr['post_type'] ) {
1319
  return $maybe_empty;
1320
+ }
1321
 
1322
+ if ( empty( $postarr['post_title'] ) ) {
1323
  return true;
1324
+ }
1325
 
1326
  return $maybe_empty;
1327
  }
1338
  */
1339
  function filter_user_row_actions( $actions, $user_object ) {
1340
 
1341
+ if ( ! current_user_can( $this->list_guest_authors_cap ) || is_network_admin() ) {
 
1342
  return $actions;
1343
+ }
1344
 
1345
  $new_actions = array();
1346
  if ( $guest_author = $this->get_guest_author_by( 'linked_account', $user_object->user_login ) ) {
1352
  'user_id' => $user_object->ID,
1353
  'nonce' => wp_create_nonce( 'create-guest-author' ),
1354
  );
1355
+ $create_guest_author_link = add_query_arg( array_map( 'rawurlencode', $query_args ), admin_url( $this->parent_page ) );
1356
  if ( apply_filters( 'coauthors_show_create_profile_user_link', false ) ) {
1357
  $new_actions['create-guest-author'] = '<a href="' . esc_url( $create_guest_author_link ) . '">' . __( 'Create Profile', 'co-authors-plus' ) . '</a>';
1358
  }
1367
  * @since 3.0
1368
  */
1369
  function filter_get_avatar( $avatar, $id_or_email, $size, $default ) {
1370
+ if ( is_object( $id_or_email ) || ! is_email( $id_or_email ) ) {
1371
  return $avatar;
1372
+ }
1373
 
1374
  // See if this matches a guest author
1375
  $guest_author = $this->get_guest_author_by( 'user_email', $id_or_email );
1376
+ if ( ! $guest_author ) {
1377
  return $avatar;
1378
+ }
1379
 
1380
  $thumbnail = $this->get_guest_author_thumbnail( $guest_author, $size );
1381
 
1382
+ if ( $thumbnail ) {
1383
  return $thumbnail;
1384
+ }
1385
 
1386
  return $avatar;
1387
  }
1395
 
1396
  // If we're using this at the top of the loop on author.php,
1397
  // our queried object should be set correctly
1398
+ if ( ! $author_nicename && is_author() && get_queried_object() ) {
1399
  $author_nicename = get_queried_object()->user_nicename;
1400
+ }
1401
 
1402
+ if ( empty( $link ) ) {
1403
+ $link = add_query_arg( 'author_name', rawurlencode( $author_nicename ), home_url() );
1404
  } else {
1405
  global $wp_rewrite;
1406
  $link = $wp_rewrite->get_author_permastruct();
1407
  if ( $link ) {
1408
+ $link = str_replace( '%author%', $author_nicename, $link );
1409
  $link = home_url( user_trailingslashit( $link ) );
1410
  } else {
1411
+ $link = add_query_arg( 'author_name', rawurlencode( $author_nicename ), home_url() );
1412
  }
1413
  }
1414
  return $link;
1429
  return $feed_link;
1430
  }
1431
 
1432
+ // Get author, then check if author is guest-author because
1433
  // that's the only type that will need to be adjusted
1434
  $author = get_queried_object();
1435
+ if ( empty( $author ) || 'guest-author' != $author->type ) {
1436
  return $feed_link;
1437
  }
1438
 
1439
+ // The next section is similar to
1440
  // get_author_feed_link() in wp-includes/link-template.php
1441
+ $permalink_structure = get_option( 'permalink_structure' );
1442
 
1443
  if ( empty( $feed ) ) {
1444
  $feed = get_default_feed();
1448
  $link = home_url( "?feed=$feed&amp;author=" . $author->ID );
1449
  } else {
1450
  $link = get_author_posts_url( $author->ID );
1451
+ $feed_link = ( get_default_feed() === $feed ) ? 'feed' : "feed/$feed";
1452
+ $link = trailingslashit( $link ) . user_trailingslashit( $feed_link, 'feed' );
1453
  }
1454
 
1455
  return $link;
1456
  }
 
1457
  }
php/class-coauthors-template-filters.php CHANGED
@@ -24,11 +24,12 @@ class CoAuthors_Template_Filters {
24
  }
25
 
26
  function filter_the_author_rss( $the_author ) {
27
- if ( !is_feed() || !function_exists( 'coauthors' ) )
28
  return $the_author;
 
29
 
30
- $coauthors = (array)get_coauthors();
31
- if( count($coauthors) >= 1 && isset($coauthors[0]->display_name) ) {
32
  return $coauthors[0]->display_name;
33
  } else {
34
  return $the_author;
@@ -39,11 +40,10 @@ class CoAuthors_Template_Filters {
39
  $coauthors = get_coauthors();
40
 
41
  // remove the first guest author who is added to the first dc:creator element
42
- array_shift($coauthors);
43
 
44
- foreach( $coauthors as $coauthor ) {
45
- echo " <dc:creator><![CDATA[" . $coauthor->display_name . "]]></dc:creator>\n";
46
  }
47
  }
48
-
49
- }
24
  }
25
 
26
  function filter_the_author_rss( $the_author ) {
27
+ if ( ! is_feed() || ! function_exists( 'coauthors' ) ) {
28
  return $the_author;
29
+ }
30
 
31
+ $coauthors = (array) get_coauthors();
32
+ if ( count( $coauthors ) >= 1 && isset( $coauthors[0]->display_name ) ) {
33
  return $coauthors[0]->display_name;
34
  } else {
35
  return $the_author;
40
  $coauthors = get_coauthors();
41
 
42
  // remove the first guest author who is added to the first dc:creator element
43
+ array_shift( $coauthors );
44
 
45
+ foreach ( $coauthors as $coauthor ) {
46
+ echo ' <dc:creator><![CDATA[' . esc_html( $coauthor->display_name ) . "]]></dc:creator>\n";
47
  }
48
  }
49
+ }
 
php/class-coauthors-wp-list-table.php CHANGED
@@ -12,13 +12,14 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
12
  var $is_search = false;
13
 
14
  function __construct() {
15
- if( !empty( $_REQUEST['s'] ) )
16
  $this->is_search = true;
 
17
 
18
  parent::__construct( array(
19
- 'plural' => __( 'Co-Authors', 'co-authors-plus' ),
20
- 'singular' => __( 'Co-Author', 'co-authors-plus' ),
21
- ) );
22
  }
23
 
24
  /**
@@ -34,17 +35,19 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
34
  'first_name' => array( 'first_name', 'ASC' ),
35
  'last_name' => array( 'last_name', 'ASC' ),
36
  );
37
- $_sortable = apply_filters( "coauthors_guest_author_sortable_columns", $this->get_sortable_columns() );
38
 
39
- foreach( (array)$_sortable as $id => $data ) {
40
- if ( empty( $data ) )
41
  continue;
 
42
 
43
  $data = (array) $data;
44
- if ( !isset( $data[1] ) )
45
  $data[1] = false;
 
46
 
47
- $sortable[$id] = $data;
48
  }
49
 
50
  $this->_column_headers = array( $columns, $hidden, $sortable );
@@ -62,7 +65,7 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
62
  );
63
 
64
  if ( isset( $_REQUEST['orderby'] ) ) {
65
- switch( $_REQUEST['orderby'] ) {
66
  case 'display_name':
67
  $args['orderby'] = 'title';
68
  break;
@@ -89,42 +92,45 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
89
  $this->active_filter = 'show-all';
90
  }
91
 
92
- switch( $this->active_filter ) {
93
  case 'with-linked-account':
94
  case 'without-linked-account':
95
  $args['meta_key'] = $coauthors_plus->guest_authors->get_post_meta_key( 'linked_account' );
96
- if ( 'with-linked-account' == $this->active_filter )
97
  $args['meta_compare'] = '!=';
98
- else
99
  $args['meta_compare'] = '=';
 
100
  $args['meta_value'] = '0';
101
  break;
102
  }
103
 
104
- if( $this->is_search )
105
  add_filter( 'posts_where', array( $this, 'filter_query_for_search' ) );
 
106
 
107
  $author_posts = new WP_Query( $args );
108
  $items = array();
109
- foreach( $author_posts->get_posts() as $author_post ) {
110
  $items[] = $coauthors_plus->guest_authors->get_guest_author_by( 'ID', $author_post->ID );
111
  }
112
 
113
- if( $this->is_search )
114
  remove_filter( 'posts_where', array( $this, 'filter_query_for_search' ) );
 
115
 
116
  $this->items = $items;
117
 
118
  $this->set_pagination_args( array(
119
  'total_items' => $author_posts->found_posts,
120
  'per_page' => $per_page,
121
- ) );
122
  }
123
 
124
  function filter_query_for_search( $where ) {
125
  global $wpdb;
126
  $var = '%' . sanitize_text_field( $_REQUEST['s'] ) . '%';
127
- $where .= $wpdb->prepare( ' AND (post_title LIKE %s OR post_name LIKE %s )', $var, $var);
128
  return $where;
129
  }
130
 
@@ -132,7 +138,7 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
132
  * Either there are no guest authors, or the search doesn't match any
133
  */
134
  function no_items() {
135
- _e( 'No matching guest authors were found.', 'co-authors-plus' );
136
  }
137
 
138
  /**
@@ -148,7 +154,7 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
148
  'posts' => __( 'Posts', 'co-authors-plus' ),
149
  );
150
 
151
- $columns = apply_filters( "coauthors_guest_author_manage_columns", $columns );
152
  return $columns;
153
  }
154
 
@@ -157,11 +163,11 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
157
  */
158
  function single_row( $item ) {
159
  static $alternate_class = '';
160
- $alternate_class = ( $alternate_class == '' ? ' alternate' : '' );
161
- $row_class = ' class="guest-author-static' . $alternate_class . '"';
162
 
163
- echo '<tr id="guest-author-' . $item->ID . '"' . $row_class . '>';
164
- echo $this->single_row_columns( $item );
165
  echo '</tr>';
166
  }
167
 
@@ -170,7 +176,7 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
170
  */
171
  function column_default( $item, $column_name ) {
172
 
173
- switch( $column_name ) {
174
  case 'first_name':
175
  case 'last_name':
176
  return $item->$column_name;
@@ -178,7 +184,7 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
178
  return '<a href="' . esc_attr( 'mailto:' . $item->user_email ) . '">' . esc_html( $item->user_email ) . '</a>';
179
 
180
  default:
181
- do_action( "coauthors_guest_author_custom_columns", $column_name, $item->ID );
182
  break;
183
  }
184
  }
@@ -194,13 +200,13 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
194
  'id' => $item->ID,
195
  '_wpnonce' => wp_create_nonce( 'guest-author-delete' ),
196
  );
197
- $item_delete_link = add_query_arg( $args, menu_page_url( 'view-guest-authors', false ) );
198
  $item_view_link = get_author_posts_url( $item->ID, $item->user_nicename );
199
 
200
  $output = '';
201
 
202
  $output .= coauthors_get_avatar( $item, 32 );
203
-
204
  if ( current_user_can( 'edit_post', $item->ID ) ) {
205
  $output .= '<a href="' . esc_url( $item_edit_link ) . '">' . esc_html( $item->display_name ) . '</a>';
206
  } else {
@@ -243,11 +249,12 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
243
  function column_posts( $item ) {
244
  global $coauthors_plus;
245
  $term = $coauthors_plus->get_author_term( $item );
246
- if ( $term )
247
  $count = $term->count;
248
- else
249
  $count = 0;
250
- return '<a href="' . esc_url( add_query_arg( 'author_name', $item->user_login, admin_url( 'edit.php' ) ) ) . '">' . $count . '</a>';
 
251
  }
252
 
253
  /**
@@ -256,16 +263,16 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
256
  function extra_tablenav( $which ) {
257
 
258
  ?><div class="alignleft actions"><?php
259
- if ( 'top' == $which ) {
260
- if ( !empty( $this->filters ) ) {
261
- echo '<select name="filter">';
262
- foreach( $this->filters as $key => $value ) {
263
- echo '<option value="' . esc_attr( $key ) . '" ' . selected( $this->active_filter, $key, false ) . '>' . esc_attr( $value ) . '</option>';
264
- }
265
- echo '</select>';
266
- }
267
- submit_button( __( 'Filter', 'co-authors-plus' ), 'secondary', false, false );
268
  }
 
 
 
 
269
  ?></div><?php
270
  }
271
 
@@ -274,5 +281,4 @@ class CoAuthors_WP_List_Table extends WP_List_Table {
274
  $this->search_box( $coauthors_plus->guest_authors->labels['search_items'], 'guest-authors' );
275
  parent::display();
276
  }
277
-
278
- }
12
  var $is_search = false;
13
 
14
  function __construct() {
15
+ if ( ! empty( $_REQUEST['s'] ) ) {
16
  $this->is_search = true;
17
+ }
18
 
19
  parent::__construct( array(
20
+ 'plural' => __( 'Co-Authors', 'co-authors-plus' ),
21
+ 'singular' => __( 'Co-Author', 'co-authors-plus' ),
22
+ ) );
23
  }
24
 
25
  /**
35
  'first_name' => array( 'first_name', 'ASC' ),
36
  'last_name' => array( 'last_name', 'ASC' ),
37
  );
38
+ $_sortable = apply_filters( 'coauthors_guest_author_sortable_columns', $this->get_sortable_columns() );
39
 
40
+ foreach ( (array) $_sortable as $id => $data ) {
41
+ if ( empty( $data ) ) {
42
  continue;
43
+ }
44
 
45
  $data = (array) $data;
46
+ if ( ! isset( $data[1] ) ) {
47
  $data[1] = false;
48
+ }
49
 
50
+ $sortable[ $id ] = $data;
51
  }
52
 
53
  $this->_column_headers = array( $columns, $hidden, $sortable );
65
  );
66
 
67
  if ( isset( $_REQUEST['orderby'] ) ) {
68
+ switch ( $_REQUEST['orderby'] ) {
69
  case 'display_name':
70
  $args['orderby'] = 'title';
71
  break;
92
  $this->active_filter = 'show-all';
93
  }
94
 
95
+ switch ( $this->active_filter ) {
96
  case 'with-linked-account':
97
  case 'without-linked-account':
98
  $args['meta_key'] = $coauthors_plus->guest_authors->get_post_meta_key( 'linked_account' );
99
+ if ( 'with-linked-account' == $this->active_filter ) {
100
  $args['meta_compare'] = '!=';
101
+ } else {
102
  $args['meta_compare'] = '=';
103
+ }
104
  $args['meta_value'] = '0';
105
  break;
106
  }
107
 
108
+ if ( $this->is_search ) {
109
  add_filter( 'posts_where', array( $this, 'filter_query_for_search' ) );
110
+ }
111
 
112
  $author_posts = new WP_Query( $args );
113
  $items = array();
114
+ foreach ( $author_posts->get_posts() as $author_post ) {
115
  $items[] = $coauthors_plus->guest_authors->get_guest_author_by( 'ID', $author_post->ID );
116
  }
117
 
118
+ if ( $this->is_search ) {
119
  remove_filter( 'posts_where', array( $this, 'filter_query_for_search' ) );
120
+ }
121
 
122
  $this->items = $items;
123
 
124
  $this->set_pagination_args( array(
125
  'total_items' => $author_posts->found_posts,
126
  'per_page' => $per_page,
127
+ ) );
128
  }
129
 
130
  function filter_query_for_search( $where ) {
131
  global $wpdb;
132
  $var = '%' . sanitize_text_field( $_REQUEST['s'] ) . '%';
133
+ $where .= $wpdb->prepare( ' AND (post_title LIKE %s OR post_name LIKE %s )', $var, $var );
134
  return $where;
135
  }
136
 
138
  * Either there are no guest authors, or the search doesn't match any
139
  */
140
  function no_items() {
141
+ esc_html_e( 'No matching guest authors were found.', 'co-authors-plus' );
142
  }
143
 
144
  /**
154
  'posts' => __( 'Posts', 'co-authors-plus' ),
155
  );
156
 
157
+ $columns = apply_filters( 'coauthors_guest_author_manage_columns', $columns );
158
  return $columns;
159
  }
160
 
163
  */
164
  function single_row( $item ) {
165
  static $alternate_class = '';
166
+ $alternate_class = ( '' === $alternate_class ? ' alternate' : '' );
167
+ $row_class = 'guest-author-static' . $alternate_class . '"';
168
 
169
+ echo '<tr id="' . esc_attr( 'guest-author-' . $item->ID ) . '" class="' . esc_attr( $row_class ) . '">';
170
+ $this->single_row_columns( $item );
171
  echo '</tr>';
172
  }
173
 
176
  */
177
  function column_default( $item, $column_name ) {
178
 
179
+ switch ( $column_name ) {
180
  case 'first_name':
181
  case 'last_name':
182
  return $item->$column_name;
184
  return '<a href="' . esc_attr( 'mailto:' . $item->user_email ) . '">' . esc_html( $item->user_email ) . '</a>';
185
 
186
  default:
187
+ do_action( 'coauthors_guest_author_custom_columns', $column_name, $item->ID );
188
  break;
189
  }
190
  }
200
  'id' => $item->ID,
201
  '_wpnonce' => wp_create_nonce( 'guest-author-delete' ),
202
  );
203
+ $item_delete_link = add_query_arg( array_map( 'rawurlencode', $args ), menu_page_url( 'view-guest-authors', false ) );
204
  $item_view_link = get_author_posts_url( $item->ID, $item->user_nicename );
205
 
206
  $output = '';
207
 
208
  $output .= coauthors_get_avatar( $item, 32 );
209
+
210
  if ( current_user_can( 'edit_post', $item->ID ) ) {
211
  $output .= '<a href="' . esc_url( $item_edit_link ) . '">' . esc_html( $item->display_name ) . '</a>';
212
  } else {
249
  function column_posts( $item ) {
250
  global $coauthors_plus;
251
  $term = $coauthors_plus->get_author_term( $item );
252
+ if ( $term ) {
253
  $count = $term->count;
254
+ } else {
255
  $count = 0;
256
+ }
257
+ return '<a href="' . esc_url( add_query_arg( 'author_name', rawurlencode( $item->user_login ), admin_url( 'edit.php' ) ) ) . '">' . $count . '</a>';
258
  }
259
 
260
  /**
263
  function extra_tablenav( $which ) {
264
 
265
  ?><div class="alignleft actions"><?php
266
+ if ( 'top' == $which ) {
267
+ if ( ! empty( $this->filters ) ) {
268
+ echo '<select name="filter">';
269
+ foreach ( $this->filters as $key => $value ) {
270
+ echo '<option value="' . esc_attr( $key ) . '" ' . selected( $this->active_filter, $key, false ) . '>' . esc_attr( $value ) . '</option>';
 
 
 
 
271
  }
272
+ echo '</select>';
273
+ }
274
+ submit_button( __( 'Filter', 'co-authors-plus' ), 'secondary', false, false );
275
+ }
276
  ?></div><?php
277
  }
278
 
281
  $this->search_box( $coauthors_plus->guest_authors->labels['search_items'], 'guest-authors' );
282
  parent::display();
283
  }
284
+ }
 
php/class-wp-cli.php CHANGED
@@ -28,7 +28,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
28
  $users = get_users();
29
  $created = 0;
30
  $skipped = 0;
31
- foreach( $users as $user ) {
32
 
33
  $result = $coauthors_plus->guest_authors->create_guest_author_from_user_id( $user->ID );
34
  if ( is_wp_error( $result ) ) {
@@ -38,7 +38,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
38
  }
39
  }
40
 
41
- WP_CLI::line( "All done! Here are your results:" );
42
  WP_CLI::line( "- {$created} guest author profiles were created" );
43
  WP_CLI::line( "- {$skipped} users already had guest author profiles" );
44
 
@@ -68,46 +68,49 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
68
  $posts = new WP_Query( $args );
69
  $affected = 0;
70
  $count = 0;
 
71
  WP_CLI::line( "Now inspecting or updating {$posts->found_posts} total posts." );
72
- while( $posts->post_count ) {
73
 
74
- foreach( $posts->posts as $single_post ) {
75
 
76
  $count++;
77
-
78
  $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy );
79
- if ( is_wp_error( $terms ) )
80
  WP_CLI::error( $terms->get_error_message() );
 
81
 
82
  if ( ! empty( $terms ) ) {
83
  WP_CLI::line( "{$count}/{$posts->found_posts}) Skipping - Post #{$single_post->ID} '{$single_post->post_title}' already has these terms: " . implode( ', ', wp_list_pluck( $terms, 'name' ) ) );
84
  continue;
85
  }
86
 
87
- $author = ( ! empty( $authors[$single_post->post_author] ) ) ? $authors[$single_post->post_author] : get_user_by( 'id', $single_post->post_author );
88
- $authors[$single_post->post_author] = $author;
89
 
90
- $author_term = ( ! empty( $author_terms[$single_post->post_author] ) ) ? $author_terms[$single_post->post_author] : $coauthors_plus->update_author_term( $author );
91
- $author_terms[$single_post->post_author] = $author_term;
92
 
93
  wp_set_post_terms( $single_post->ID, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy );
94
- WP_CLI::line( "{$count}/{$posts->found_posts}) Added - Post #{$single_post->ID} '{$single_post->post_title}' now has an author term for: " . $author->user_nicename );
95
  $affected++;
96
- if ( $affected && $affected % 10 == 0 )
97
- sleep( 3 );
98
  }
99
 
100
- $this->stop_the_insanity();
101
-
102
- $this->args['paged']++;
103
- $posts = new WP_Query( $this->args );
 
 
 
104
  }
105
- WP_CLI::line( "Updating author terms with new counts" );
106
- foreach( $authors as $author ) {
107
  $coauthors_plus->update_author_term( $author );
108
  }
109
 
110
- WP_CLI::success( "Done! Of {$posts->found_posts} posts, {$affected} now have author terms." );
111
 
112
  }
113
 
@@ -144,18 +147,19 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
144
  $missing_coauthors = array();
145
 
146
  $posts = new WP_Query( $this->args );
147
- while( $posts->post_count ) {
148
 
149
- foreach( $posts->posts as $single_post ) {
150
  $posts_total++;
151
 
152
  // See if the value in the post meta field is the same as any of the existing coauthors
153
  $original_author = get_post_meta( $single_post->ID, $this->args['meta_key'], true );
154
  $existing_coauthors = get_coauthors( $single_post->ID );
155
  $already_associated = false;
156
- foreach( $existing_coauthors as $existing_coauthor ) {
157
- if ( $original_author == $existing_coauthor->user_login )
158
  $already_associated = true;
 
159
  }
160
  if ( $already_associated ) {
161
  $posts_already_associated++;
@@ -164,7 +168,8 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
164
  }
165
 
166
  // Make sure this original author exists as a co-author
167
- if ( !$coauthors_plus->get_coauthor_by( 'user_login', $original_author ) ) {
 
168
  $posts_missing_coauthor++;
169
  $missing_coauthors[] = $original_author;
170
  WP_CLI::line( $posts_total . ': Post #' . $single_post->ID . ' does not have "' . $original_author . '" associated as a coauthor but there is not a coauthor profile' );
@@ -172,26 +177,28 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
172
  }
173
 
174
  // Assign the coauthor to the post
175
- $coauthors_plus->add_coauthors( $single_post->ID, array( $original_author ), $append_coauthors );
176
  WP_CLI::line( $posts_total . ': Post #' . $single_post->ID . ' has been assigned "' . $original_author . '" as the author' );
177
  $posts_associated++;
178
  clean_post_cache( $single_post->ID );
179
  }
180
-
181
  $this->args['paged']++;
182
  $this->stop_the_insanity();
183
  $posts = new WP_Query( $this->args );
184
  }
185
 
186
- WP_CLI::line( "All done! Here are your results:" );
187
- if ( $posts_already_associated )
188
  WP_CLI::line( "- {$posts_already_associated} posts already had the coauthor assigned" );
 
189
  if ( $posts_missing_coauthor ) {
190
  WP_CLI::line( "- {$posts_missing_coauthor} posts reference coauthors that don't exist. These are:" );
191
- WP_CLI::line( " " . implode( ', ', array_unique( $missing_coauthors ) ) );
192
  }
193
- if ( $posts_associated )
194
  WP_CLI::line( "- {$posts_associated} posts now have the proper coauthor" );
 
195
 
196
  }
197
 
@@ -216,28 +223,31 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
216
  $user = get_user_by( 'login', $assoc_args['user_login'] );
217
  $coauthor = $coauthors_plus->get_coauthor_by( 'login', $assoc_args['coauthor'] );
218
 
219
- if ( ! $user )
220
  WP_CLI::error( __( 'Please specify a valid user_login', 'co-authors-plus' ) );
 
221
 
222
- if ( ! $coauthor )
223
  WP_CLI::error( __( 'Please specify a valid co-author login', 'co-authors-plus' ) );
 
224
 
225
  $post_types = implode( "','", $coauthors_plus->supported_post_types );
226
  $posts = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author=%d AND post_type IN ('$post_types')", $user->ID ) );
227
  $affected = 0;
228
- foreach( $posts as $post_id ) {
229
  if ( $coauthors = wp_get_post_terms( $post_id, $coauthors_plus->coauthor_taxonomy ) ) {
230
- WP_CLI::line( sprintf( __( "Skipping - Post #%d already has co-authors assigned: %s", 'co-authors-plus' ), $post_id, implode( ', ', wp_list_pluck( $coauthors, 'slug' ) ) ) );
231
  continue;
232
  }
233
 
234
  $coauthors_plus->add_coauthors( $post_id, array( $coauthor->user_login ) );
235
  WP_CLI::line( sprintf( __( "Updating - Adding %s's byline to post #%d", 'co-authors-plus' ), $coauthor->user_login, $post_id ) );
236
  $affected++;
237
- if ( $affected && $affected % 20 == 0 )
238
  sleep( 5 );
 
239
  }
240
- WP_CLI::success( sprintf( __( "All done! %d posts were affected.", 'co-authors-plus' ), $affected ) );
241
 
242
  }
243
 
@@ -287,19 +297,20 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
287
 
288
  // For each author to migrate, check whether the term exists,
289
  // whether the target term exists, and only do the migration if both are met
290
- $results = (object)array(
291
  'old_term_missing' => 0,
292
  'new_term_exists' => 0,
293
  'success' => 0,
294
  );
295
- foreach( $authors_to_migrate as $old_user => $new_user ) {
296
 
297
- if ( is_numeric( $new_user ) )
298
  $new_user = get_user_by( 'id', $new_user )->user_login;
 
299
 
300
  // The old user should exist as a term
301
  $old_term = $coauthors_plus->get_author_term( $coauthors_plus->get_coauthor_by( 'login', $old_user ) );
302
- if ( !$old_term ) {
303
  WP_CLI::line( "Error: Term '{$old_user}' doesn't exist, skipping" );
304
  $results->old_term_missing++;
305
  continue;
@@ -329,7 +340,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
329
  clean_term_cache( $old_term->term_id, $coauthors_plus->coauthor_taxonomy );
330
  }
331
 
332
- WP_CLI::line( "Reassignment complete. Here are your results:" );
333
  WP_CLI::line( "- $results->success authors were successfully reassigned terms" );
334
  WP_CLI::line( "- $results->new_term_exists authors had their old term merged to their new term" );
335
  WP_CLI::line( "- $results->old_term_missing authors were missing old terms" );
@@ -359,14 +370,17 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
359
  $to_userlogin_prefixed = 'cap-' . $to_userlogin;
360
 
361
  $orig_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $assoc_args['from'] );
362
- if ( ! $orig_coauthor )
363
  WP_CLI::error( "No co-author found for {$assoc_args['from']}" );
 
364
 
365
- if ( ! $to_userlogin )
366
  WP_CLI::error( '--to param must not be empty' );
 
367
 
368
- if ( $coauthors_plus->get_coauthor_by( 'user_login', $to_userlogin ) )
369
- WP_CLI::error( "New user_login value conflicts with existing co-author" );
 
370
 
371
  $orig_term = $coauthors_plus->get_author_term( $orig_coauthor );
372
 
@@ -382,10 +396,10 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
382
  clean_post_cache( $orig_coauthor->ID );
383
  update_post_meta( $orig_coauthor->ID, 'cap-user_login', $to_userlogin );
384
  $coauthors_plus->guest_authors->delete_guest_author_cache( $orig_coauthor->ID );
385
- WP_CLI::line( "Updated guest author profile value too" );
386
  }
387
 
388
- WP_CLI::success( "All done!" );
389
  }
390
 
391
  /**
@@ -402,7 +416,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
402
  'from' => null,
403
  'to' => null,
404
  'post_type' => 'post',
405
- 'dry' => false
406
  );
407
 
408
  $assoc_args = array_merge( $defaults, $assoc_args );
@@ -417,20 +431,23 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
417
 
418
  $orig_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $from_userlogin );
419
 
420
- if ( ! $orig_coauthor )
421
  WP_CLI::error( "No co-author found for $from_userlogin" );
 
422
 
423
- if ( ! $to_userlogin )
424
  WP_CLI::error( '--to param must not be empty' );
 
425
 
426
  $to_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $to_userlogin );
427
 
428
- if ( ! $to_coauthor )
429
  WP_CLI::error( "No co-author found for $to_userlogin" );
 
430
 
431
  WP_CLI::line( "Swapping authorship from {$from_userlogin} to {$to_userlogin}" );
432
 
433
- $query_args = array(
434
  'post_type' => $assoc_args['post_type'],
435
  'order' => 'ASC',
436
  'orderby' => 'ID',
@@ -440,9 +457,9 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
440
  array(
441
  'taxonomy' => $coauthors_plus->coauthor_taxonomy,
442
  'field' => 'slug',
443
- 'terms' => array( $from_userlogin_prefixed )
444
- )
445
- )
446
  );
447
 
448
  $posts = new WP_Query( $query_args );
@@ -451,20 +468,21 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
451
 
452
  WP_CLI::line( "Found $posts->found_posts posts to update." );
453
 
454
- while( $posts->post_count ) {
455
- foreach( $posts->posts as $post ) {
456
  $coauthors = get_coauthors( $post->ID );
457
 
458
- if ( ! is_array( $coauthors ) || ! count( $coauthors ) )
459
  continue;
 
460
 
461
  $coauthors = wp_list_pluck( $coauthors, 'user_login' );
462
 
463
  $posts_total++;
464
-
465
  if ( ! $dry ) {
466
  // Remove the $from_userlogin from $coauthors
467
- foreach( $coauthors as $index => $user_login ) {
468
  if ( $from_userlogin === $user_login ) {
469
  unset( $coauthors[ $index ] );
470
 
@@ -477,21 +495,26 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
477
 
478
  // By not passing $append = false as the 3rd param, we replace all existing coauthors
479
  $coauthors_plus->add_coauthors( $post->ID, $coauthors, false );
480
-
481
  WP_CLI::line( $posts_total . ': Post #' . $post->ID . ' has been assigned "' . $to_userlogin . '" as a co-author' );
482
-
483
  clean_post_cache( $post->ID );
484
  } else {
485
  WP_CLI::line( $posts_total . ': Post #' . $post->ID . ' will be assigned "' . $to_userlogin . '" as a co-author' );
486
  }
487
  }
488
 
 
 
 
 
 
489
  $this->stop_the_insanity();
490
 
491
  $posts = new WP_Query( $query_args );
492
  }
493
 
494
- WP_CLI::success( "All done!" );
495
  }
496
 
497
  /**
@@ -518,10 +541,10 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
518
  $this->args = wp_parse_args( $assoc_args, $defaults );
519
 
520
  $posts = new WP_Query( $this->args );
521
- while( $posts->post_count ) {
 
 
522
 
523
- foreach( $posts->posts as $single_post ) {
524
-
525
  $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy );
526
  if ( empty( $terms ) ) {
527
  $saved = array(
@@ -535,7 +558,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
535
  }
536
 
537
  $this->stop_the_insanity();
538
-
539
  $this->args['paged']++;
540
  $posts = new WP_Query( $this->args );
541
  }
@@ -548,15 +571,15 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
548
  * they can easily collide with terms in other taxonomies
549
  *
550
  * @since 3.0
551
- *
552
  * @subcommand migrate-author-terms
553
  */
554
  public function migrate_author_terms( $args, $assoc_args ) {
555
  global $coauthors_plus;
556
 
557
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, array( 'hide_empty' => false ) );
558
- WP_CLI::line( "Now migrating up to " . count( $author_terms ) . " terms" );
559
- foreach( $author_terms as $author_term ) {
560
  // Term is already prefixed. We're good.
561
  if ( preg_match( '#^cap\-#', $author_term->slug, $matches ) ) {
562
  WP_CLI::line( "Term {$author_term->slug} ({$author_term->term_id}) is already prefixed, skipping" );
@@ -579,7 +602,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
579
  );
580
  wp_update_term( $author_term->term_id, $coauthors_plus->coauthor_taxonomy, $args );
581
  }
582
- WP_CLI::success( "All done! Grab a cold one (Affogatto)" );
583
  }
584
 
585
  /**
@@ -592,8 +615,8 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
592
  public function update_author_terms() {
593
  global $coauthors_plus;
594
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, array( 'hide_empty' => false ) );
595
- WP_CLI::line( "Now updating " . count( $author_terms ) . " terms" );
596
- foreach( $author_terms as $author_term ) {
597
  $old_count = $author_term->count;
598
  $coauthor = $coauthors_plus->get_coauthor_by( 'user_nicename', $author_term->slug );
599
  $coauthors_plus->update_author_term( $coauthor );
@@ -604,7 +627,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
604
  }
605
  // Create author terms for any users that don't have them
606
  $users = get_users();
607
- foreach( $users as $user ) {
608
  $term = $coauthors_plus->get_author_term( $user );
609
  if ( empty( $term ) || empty( $term->description ) ) {
610
  $coauthors_plus->update_author_term( $user );
@@ -621,15 +644,15 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
621
  'posts_per_page' => 100,
622
  'paged' => 1,
623
  'update_meta_cache' => false,
624
- 'fields' => 'ids'
625
  );
626
 
627
  $posts = new WP_Query( $args );
628
  $count = 0;
629
  WP_CLI::line( "Now inspecting or updating {$posts->found_posts} Guest Authors." );
630
 
631
- while( $posts->post_count ) {
632
- foreach( $posts->posts as $guest_author_id ) {
633
  $count++;
634
 
635
  $guest_author = $coauthors_plus->guest_authors->get_guest_author_by( 'ID', $guest_author_id );
@@ -650,13 +673,13 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
650
  }
651
 
652
  $this->stop_the_insanity();
653
-
654
  $args['paged']++;
655
  $posts = new WP_Query( $args );
656
  }
657
  }
658
-
659
- WP_CLI::success( "All done" );
660
  }
661
 
662
  /**
@@ -671,13 +694,14 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
671
 
672
  $ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='revision' AND post_status='inherit'" );
673
 
674
- WP_CLI::line( "Found " . count( $ids ) . " revisions to look through" );
675
  $affected = 0;
676
- foreach( $ids as $post_id ) {
677
 
678
  $terms = wp_get_post_terms( $post_id, 'author' );
679
- if ( ! $terms )
680
  continue;
 
681
 
682
  WP_CLI::line( "#{$post_id}: Removing " . implode( ',', wp_list_pluck( $terms, 'slug' ) ) );
683
  wp_set_post_terms( $post_id, array(), 'author' );
@@ -690,7 +714,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
690
  * Subcommand to create guest authors from an author list in a WXR file
691
  *
692
  * @subcommand create-guest-authors-from-wxr
693
- * @synopsis --file=</path/to/file.wxr>
694
  */
695
  public function create_guest_authors_from_wxr( $args, $assoc_args ) {
696
  global $coauthors_plus;
@@ -700,17 +724,20 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
700
  );
701
  $this->args = wp_parse_args( $assoc_args, $defaults );
702
 
703
- if ( empty( $this->args['file'] ) || ! is_readable( $this->args['file'] ) )
704
  WP_CLI::error( 'Please specify a valid WXR file with the --file arg.' );
 
705
 
706
- if ( ! class_exists( 'WXR_Parser' ) )
707
  require_once( WP_CONTENT_DIR . '/admin-plugins/wordpress-importer/parsers.php' );
 
708
 
709
  $parser = new WXR_Parser();
710
  $import_data = $parser->parse( $this->args['file'] );
711
 
712
- if ( is_wp_error( $import_data ) )
713
  WP_CLI::error( 'Failed to read WXR file.' );
 
714
 
715
  // Get author nodes
716
  $authors = $import_data['authors'];
@@ -737,7 +764,7 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
737
  * Subcommand to create guest authors from an author list in a CSV file
738
  *
739
  * @subcommand create-guest-authors-from-csv
740
- * @synopsis --file=</path/to/file.csv>
741
  */
742
  public function create_guest_authors_from_csv( $args, $assoc_args ) {
743
  global $coauthors_plus;
@@ -747,38 +774,41 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
747
  );
748
  $this->args = wp_parse_args( $assoc_args, $defaults );
749
 
750
- if ( empty( $this->args['file'] ) || ! is_readable( $this->args['file'] ) )
751
  WP_CLI::error( 'Please specify a valid CSV file with the --file arg.' );
 
752
 
753
  $file = fopen( $this->args['file'], 'r' );
754
 
755
- if ( ! $file )
756
  WP_CLI::error( 'Failed to read file.' );
 
757
 
758
  $authors = array();
759
 
760
  $row = 0;
761
  while ( false !== ( $data = fgetcsv( $file ) ) ) {
762
- if ( $row == 0 ) {
763
  $field_keys = array_map( 'trim', $data );
764
  // TODO: bail if required fields not found
765
  } else {
766
  $row_data = array_map( 'trim', $data );
767
  $author_data = array();
768
- foreach( (array) $row_data as $col_num => $val ) {
769
  // Don't use the value of the field key isn't set
770
- if ( empty( $field_keys[$col_num] ) )
771
- continue;
772
- $author_data[$field_keys[$col_num]] = $val;
 
773
  }
774
-
775
  $authors[] = $author_data;
776
  }
777
  $row++;
778
  }
779
  fclose( $file );
780
 
781
- WP_CLI::line( "Found " . count( $authors ) . " authors in CSV" );
782
 
783
  foreach ( $authors as $author ) {
784
  WP_CLI::line( sprintf( 'Processing author %s (%s)', $author['user_login'], $author['user_email'] ) );
@@ -830,12 +860,13 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
830
  if ( $guest_author_id ) {
831
  WP_CLI::line( sprintf( '-- Created as guest author #%s', $guest_author_id ) );
832
 
833
- if ( isset( $author['author_id'] ) )
834
  update_post_meta( $guest_author_id, '_original_author_id', $author['ID'] );
 
835
 
836
  update_post_meta( $guest_author_id, '_original_author_login', $author['user_login'] );
837
  } else {
838
- WP_CLI::warning( "-- Failed to create guest author." );
839
  }
840
  } else {
841
  WP_CLI::line( sprintf( '-- Author already exists (ID #%s); skipping.', $guest_author->ID ) );
@@ -850,16 +881,17 @@ class CoAuthorsPlus_Command extends WP_CLI_Command {
850
 
851
  $wpdb->queries = array(); // or define( 'WP_IMPORTING', true );
852
 
853
- if ( !is_object( $wp_object_cache ) )
854
  return;
 
855
 
856
  $wp_object_cache->group_ops = array();
857
  $wp_object_cache->stats = array();
858
  $wp_object_cache->memcache_debug = array();
859
  $wp_object_cache->cache = array();
860
 
861
- if( is_callable( $wp_object_cache, '__remoteset' ) )
862
  $wp_object_cache->__remoteset(); // important
 
863
  }
864
-
865
- }
28
  $users = get_users();
29
  $created = 0;
30
  $skipped = 0;
31
+ foreach ( $users as $user ) {
32
 
33
  $result = $coauthors_plus->guest_authors->create_guest_author_from_user_id( $user->ID );
34
  if ( is_wp_error( $result ) ) {
38
  }
39
  }
40
 
41
+ WP_CLI::line( 'All done! Here are your results:' );
42
  WP_CLI::line( "- {$created} guest author profiles were created" );
43
  WP_CLI::line( "- {$skipped} users already had guest author profiles" );
44
 
68
  $posts = new WP_Query( $args );
69
  $affected = 0;
70
  $count = 0;
71
+ $total_posts = $posts->found_posts;
72
  WP_CLI::line( "Now inspecting or updating {$posts->found_posts} total posts." );
73
+ while ( $posts->post_count ) {
74
 
75
+ foreach ( $posts->posts as $single_post ) {
76
 
77
  $count++;
78
+
79
  $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy );
80
+ if ( is_wp_error( $terms ) ) {
81
  WP_CLI::error( $terms->get_error_message() );
82
+ }
83
 
84
  if ( ! empty( $terms ) ) {
85
  WP_CLI::line( "{$count}/{$posts->found_posts}) Skipping - Post #{$single_post->ID} '{$single_post->post_title}' already has these terms: " . implode( ', ', wp_list_pluck( $terms, 'name' ) ) );
86
  continue;
87
  }
88
 
89
+ $author = ( ! empty( $authors[ $single_post->post_author ] ) ) ? $authors[ $single_post->post_author ] : get_user_by( 'id', $single_post->post_author );
90
+ $authors[ $single_post->post_author ] = $author;
91
 
92
+ $author_term = ( ! empty( $author_terms[ $single_post->post_author ] ) ) ? $author_terms[ $single_post->post_author ] : $coauthors_plus->update_author_term( $author );
93
+ $author_terms[ $single_post->post_author ] = $author_term;
94
 
95
  wp_set_post_terms( $single_post->ID, array( $author_term->slug ), $coauthors_plus->coauthor_taxonomy );
96
+ WP_CLI::line( "{$count}/{$total_posts}) Added - Post #{$single_post->ID} '{$single_post->post_title}' now has an author term for: " . $author->user_nicename );
97
  $affected++;
 
 
98
  }
99
 
100
+ if ( $count && 0 === $count % 500 ) {
101
+ $this->stop_the_insanity();
102
+ sleep( 1 );
103
+ }
104
+
105
+ $args['paged']++;
106
+ $posts = new WP_Query( $args );
107
  }
108
+ WP_CLI::line( 'Updating author terms with new counts' );
109
+ foreach ( $authors as $author ) {
110
  $coauthors_plus->update_author_term( $author );
111
  }
112
 
113
+ WP_CLI::success( "Done! Of {$total_posts} posts, {$affected} now have author terms." );
114
 
115
  }
116
 
147
  $missing_coauthors = array();
148
 
149
  $posts = new WP_Query( $this->args );
150
+ while ( $posts->post_count ) {
151
 
152
+ foreach ( $posts->posts as $single_post ) {
153
  $posts_total++;
154
 
155
  // See if the value in the post meta field is the same as any of the existing coauthors
156
  $original_author = get_post_meta( $single_post->ID, $this->args['meta_key'], true );
157
  $existing_coauthors = get_coauthors( $single_post->ID );
158
  $already_associated = false;
159
+ foreach ( $existing_coauthors as $existing_coauthor ) {
160
+ if ( $original_author == $existing_coauthor->user_login ) {
161
  $already_associated = true;
162
+ }
163
  }
164
  if ( $already_associated ) {
165
  $posts_already_associated++;
168
  }
169
 
170
  // Make sure this original author exists as a co-author
171
+ if ( ( ! $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $original_author ) ) &&
172
+ ( ! $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', sanitize_title( $original_author ) ) ) ) {
173
  $posts_missing_coauthor++;
174
  $missing_coauthors[] = $original_author;
175
  WP_CLI::line( $posts_total . ': Post #' . $single_post->ID . ' does not have "' . $original_author . '" associated as a coauthor but there is not a coauthor profile' );
177
  }
178
 
179
  // Assign the coauthor to the post
180
+ $coauthors_plus->add_coauthors( $single_post->ID, array( $coauthor->user_nicename ), $append_coauthors );
181
  WP_CLI::line( $posts_total . ': Post #' . $single_post->ID . ' has been assigned "' . $original_author . '" as the author' );
182
  $posts_associated++;
183
  clean_post_cache( $single_post->ID );
184
  }
185
+
186
  $this->args['paged']++;
187
  $this->stop_the_insanity();
188
  $posts = new WP_Query( $this->args );
189
  }
190
 
191
+ WP_CLI::line( 'All done! Here are your results:' );
192
+ if ( $posts_already_associated ) {
193
  WP_CLI::line( "- {$posts_already_associated} posts already had the coauthor assigned" );
194
+ }
195
  if ( $posts_missing_coauthor ) {
196
  WP_CLI::line( "- {$posts_missing_coauthor} posts reference coauthors that don't exist. These are:" );
197
+ WP_CLI::line( ' ' . implode( ', ', array_unique( $missing_coauthors ) ) );
198
  }
199
+ if ( $posts_associated ) {
200
  WP_CLI::line( "- {$posts_associated} posts now have the proper coauthor" );
201
+ }
202
 
203
  }
204
 
223
  $user = get_user_by( 'login', $assoc_args['user_login'] );
224
  $coauthor = $coauthors_plus->get_coauthor_by( 'login', $assoc_args['coauthor'] );
225
 
226
+ if ( ! $user ) {
227
  WP_CLI::error( __( 'Please specify a valid user_login', 'co-authors-plus' ) );
228
+ }
229
 
230
+ if ( ! $coauthor ) {
231
  WP_CLI::error( __( 'Please specify a valid co-author login', 'co-authors-plus' ) );
232
+ }
233
 
234
  $post_types = implode( "','", $coauthors_plus->supported_post_types );
235
  $posts = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author=%d AND post_type IN ('$post_types')", $user->ID ) );
236
  $affected = 0;
237
+ foreach ( $posts as $post_id ) {
238
  if ( $coauthors = wp_get_post_terms( $post_id, $coauthors_plus->coauthor_taxonomy ) ) {
239
+ WP_CLI::line( sprintf( __( 'Skipping - Post #%d already has co-authors assigned: %s', 'co-authors-plus' ), $post_id, implode( ', ', wp_list_pluck( $coauthors, 'slug' ) ) ) );
240
  continue;
241
  }
242
 
243
  $coauthors_plus->add_coauthors( $post_id, array( $coauthor->user_login ) );
244
  WP_CLI::line( sprintf( __( "Updating - Adding %s's byline to post #%d", 'co-authors-plus' ), $coauthor->user_login, $post_id ) );
245
  $affected++;
246
+ if ( $affected && 0 === $affected % 20 ) {
247
  sleep( 5 );
248
+ }
249
  }
250
+ WP_CLI::success( sprintf( __( 'All done! %d posts were affected.', 'co-authors-plus' ), $affected ) );
251
 
252
  }
253
 
297
 
298
  // For each author to migrate, check whether the term exists,
299
  // whether the target term exists, and only do the migration if both are met
300
+ $results = (object) array(
301
  'old_term_missing' => 0,
302
  'new_term_exists' => 0,
303
  'success' => 0,
304
  );
305
+ foreach ( $authors_to_migrate as $old_user => $new_user ) {
306
 
307
+ if ( is_numeric( $new_user ) ) {
308
  $new_user = get_user_by( 'id', $new_user )->user_login;
309
+ }
310
 
311
  // The old user should exist as a term
312
  $old_term = $coauthors_plus->get_author_term( $coauthors_plus->get_coauthor_by( 'login', $old_user ) );
313
+ if ( ! $old_term ) {
314
  WP_CLI::line( "Error: Term '{$old_user}' doesn't exist, skipping" );
315
  $results->old_term_missing++;
316
  continue;
340
  clean_term_cache( $old_term->term_id, $coauthors_plus->coauthor_taxonomy );
341
  }
342
 
343
+ WP_CLI::line( 'Reassignment complete. Here are your results:' );
344
  WP_CLI::line( "- $results->success authors were successfully reassigned terms" );
345
  WP_CLI::line( "- $results->new_term_exists authors had their old term merged to their new term" );
346
  WP_CLI::line( "- $results->old_term_missing authors were missing old terms" );
370
  $to_userlogin_prefixed = 'cap-' . $to_userlogin;
371
 
372
  $orig_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $assoc_args['from'] );
373
+ if ( ! $orig_coauthor ) {
374
  WP_CLI::error( "No co-author found for {$assoc_args['from']}" );
375
+ }
376
 
377
+ if ( ! $to_userlogin ) {
378
  WP_CLI::error( '--to param must not be empty' );
379
+ }
380
 
381
+ if ( $coauthors_plus->get_coauthor_by( 'user_login', $to_userlogin ) ) {
382
+ WP_CLI::error( 'New user_login value conflicts with existing co-author' );
383
+ }
384
 
385
  $orig_term = $coauthors_plus->get_author_term( $orig_coauthor );
386
 
396
  clean_post_cache( $orig_coauthor->ID );
397
  update_post_meta( $orig_coauthor->ID, 'cap-user_login', $to_userlogin );
398
  $coauthors_plus->guest_authors->delete_guest_author_cache( $orig_coauthor->ID );
399
+ WP_CLI::line( 'Updated guest author profile value too' );
400
  }
401
 
402
+ WP_CLI::success( 'All done!' );
403
  }
404
 
405
  /**
416
  'from' => null,
417
  'to' => null,
418
  'post_type' => 'post',
419
+ 'dry' => false,
420
  );
421
 
422
  $assoc_args = array_merge( $defaults, $assoc_args );
431
 
432
  $orig_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $from_userlogin );
433
 
434
+ if ( ! $orig_coauthor ) {
435
  WP_CLI::error( "No co-author found for $from_userlogin" );
436
+ }
437
 
438
+ if ( ! $to_userlogin ) {
439
  WP_CLI::error( '--to param must not be empty' );
440
+ }
441
 
442
  $to_coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $to_userlogin );
443
 
444
+ if ( ! $to_coauthor ) {
445
  WP_CLI::error( "No co-author found for $to_userlogin" );
446
+ }
447
 
448
  WP_CLI::line( "Swapping authorship from {$from_userlogin} to {$to_userlogin}" );
449
 
450
+ $query_args = array(
451
  'post_type' => $assoc_args['post_type'],
452
  'order' => 'ASC',
453
  'orderby' => 'ID',
457
  array(
458
  'taxonomy' => $coauthors_plus->coauthor_taxonomy,
459
  'field' => 'slug',
460
+ 'terms' => array( $from_userlogin_prefixed ),
461
+ ),
462
+ ),
463
  );
464
 
465
  $posts = new WP_Query( $query_args );
468
 
469
  WP_CLI::line( "Found $posts->found_posts posts to update." );
470
 
471
+ while ( $posts->post_count ) {
472
+ foreach ( $posts->posts as $post ) {
473
  $coauthors = get_coauthors( $post->ID );
474
 
475
+ if ( ! is_array( $coauthors ) || ! count( $coauthors ) ) {
476
  continue;
477
+ }
478
 
479
  $coauthors = wp_list_pluck( $coauthors, 'user_login' );
480
 
481
  $posts_total++;
482
+
483
  if ( ! $dry ) {
484
  // Remove the $from_userlogin from $coauthors
485
+ foreach ( $coauthors as $index => $user_login ) {
486
  if ( $from_userlogin === $user_login ) {
487
  unset( $coauthors[ $index ] );
488
 
495
 
496
  // By not passing $append = false as the 3rd param, we replace all existing coauthors
497
  $coauthors_plus->add_coauthors( $post->ID, $coauthors, false );
498
+
499
  WP_CLI::line( $posts_total . ': Post #' . $post->ID . ' has been assigned "' . $to_userlogin . '" as a co-author' );
500
+
501
  clean_post_cache( $post->ID );
502
  } else {
503
  WP_CLI::line( $posts_total . ': Post #' . $post->ID . ' will be assigned "' . $to_userlogin . '" as a co-author' );
504
  }
505
  }
506
 
507
+ // In dry mode, we must manually advance the page
508
+ if ( $dry ) {
509
+ $query_args['paged']++;
510
+ }
511
+
512
  $this->stop_the_insanity();
513
 
514
  $posts = new WP_Query( $query_args );
515
  }
516
 
517
+ WP_CLI::success( 'All done!' );
518
  }
519
 
520
  /**
541
  $this->args = wp_parse_args( $assoc_args, $defaults );
542
 
543
  $posts = new WP_Query( $this->args );
544
+ while ( $posts->post_count ) {
545
+
546
+ foreach ( $posts->posts as $single_post ) {
547
 
 
 
548
  $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy );
549
  if ( empty( $terms ) ) {
550
  $saved = array(
558
  }
559
 
560
  $this->stop_the_insanity();
561
+
562
  $this->args['paged']++;
563
  $posts = new WP_Query( $this->args );
564
  }
571
  * they can easily collide with terms in other taxonomies
572
  *
573
  * @since 3.0
574
+ *
575
  * @subcommand migrate-author-terms
576
  */
577
  public function migrate_author_terms( $args, $assoc_args ) {
578
  global $coauthors_plus;
579
 
580
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, array( 'hide_empty' => false ) );
581
+ WP_CLI::line( 'Now migrating up to ' . count( $author_terms ) . ' terms' );
582
+ foreach ( $author_terms as $author_term ) {
583
  // Term is already prefixed. We're good.
584
  if ( preg_match( '#^cap\-#', $author_term->slug, $matches ) ) {
585
  WP_CLI::line( "Term {$author_term->slug} ({$author_term->term_id}) is already prefixed, skipping" );
602
  );
603
  wp_update_term( $author_term->term_id, $coauthors_plus->coauthor_taxonomy, $args );
604
  }
605
+ WP_CLI::success( 'All done! Grab a cold one (Affogatto)' );
606
  }
607
 
608
  /**
615
  public function update_author_terms() {
616
  global $coauthors_plus;
617
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, array( 'hide_empty' => false ) );
618
+ WP_CLI::line( 'Now updating ' . count( $author_terms ) . ' terms' );
619
+ foreach ( $author_terms as $author_term ) {
620
  $old_count = $author_term->count;
621
  $coauthor = $coauthors_plus->get_coauthor_by( 'user_nicename', $author_term->slug );
622
  $coauthors_plus->update_author_term( $coauthor );
627
  }
628
  // Create author terms for any users that don't have them
629
  $users = get_users();
630
+ foreach ( $users as $user ) {
631
  $term = $coauthors_plus->get_author_term( $user );
632
  if ( empty( $term ) || empty( $term->description ) ) {
633
  $coauthors_plus->update_author_term( $user );
644
  'posts_per_page' => 100,
645
  'paged' => 1,
646
  'update_meta_cache' => false,
647
+ 'fields' => 'ids',
648
  );
649
 
650
  $posts = new WP_Query( $args );
651
  $count = 0;
652
  WP_CLI::line( "Now inspecting or updating {$posts->found_posts} Guest Authors." );
653
 
654
+ while ( $posts->post_count ) {
655
+ foreach ( $posts->posts as $guest_author_id ) {
656
  $count++;
657
 
658
  $guest_author = $coauthors_plus->guest_authors->get_guest_author_by( 'ID', $guest_author_id );
673
  }
674
 
675
  $this->stop_the_insanity();
676
+
677
  $args['paged']++;
678
  $posts = new WP_Query( $args );
679
  }
680
  }
681
+
682
+ WP_CLI::success( 'All done' );
683
  }
684
 
685
  /**
694
 
695
  $ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='revision' AND post_status='inherit'" );
696
 
697
+ WP_CLI::line( 'Found ' . count( $ids ) . ' revisions to look through' );
698
  $affected = 0;
699
+ foreach ( $ids as $post_id ) {
700
 
701
  $terms = wp_get_post_terms( $post_id, 'author' );
702
+ if ( ! $terms ) {
703
  continue;
704
+ }
705
 
706
  WP_CLI::line( "#{$post_id}: Removing " . implode( ',', wp_list_pluck( $terms, 'slug' ) ) );
707
  wp_set_post_terms( $post_id, array(), 'author' );
714
  * Subcommand to create guest authors from an author list in a WXR file
715
  *
716
  * @subcommand create-guest-authors-from-wxr
717
+ * @synopsis --file=<file>
718
  */
719
  public function create_guest_authors_from_wxr( $args, $assoc_args ) {
720
  global $coauthors_plus;
724
  );
725
  $this->args = wp_parse_args( $assoc_args, $defaults );
726
 
727
+ if ( empty( $this->args['file'] ) || ! is_readable( $this->args['file'] ) ) {
728
  WP_CLI::error( 'Please specify a valid WXR file with the --file arg.' );
729
+ }
730
 
731
+ if ( ! class_exists( 'WXR_Parser' ) ) {
732
  require_once( WP_CONTENT_DIR . '/admin-plugins/wordpress-importer/parsers.php' );
733
+ }
734
 
735
  $parser = new WXR_Parser();
736
  $import_data = $parser->parse( $this->args['file'] );
737
 
738
+ if ( is_wp_error( $import_data ) ) {
739
  WP_CLI::error( 'Failed to read WXR file.' );
740
+ }
741
 
742
  // Get author nodes
743
  $authors = $import_data['authors'];
764
  * Subcommand to create guest authors from an author list in a CSV file
765
  *
766
  * @subcommand create-guest-authors-from-csv
767
+ * @synopsis --file=<file>
768
  */
769
  public function create_guest_authors_from_csv( $args, $assoc_args ) {
770
  global $coauthors_plus;
774
  );
775
  $this->args = wp_parse_args( $assoc_args, $defaults );
776
 
777
+ if ( empty( $this->args['file'] ) || ! is_readable( $this->args['file'] ) ) {
778
  WP_CLI::error( 'Please specify a valid CSV file with the --file arg.' );
779
+ }
780
 
781
  $file = fopen( $this->args['file'], 'r' );
782
 
783
+ if ( ! $file ) {
784
  WP_CLI::error( 'Failed to read file.' );
785
+ }
786
 
787
  $authors = array();
788
 
789
  $row = 0;
790
  while ( false !== ( $data = fgetcsv( $file ) ) ) {
791
+ if ( 0 === $row ) {
792
  $field_keys = array_map( 'trim', $data );
793
  // TODO: bail if required fields not found
794
  } else {
795
  $row_data = array_map( 'trim', $data );
796
  $author_data = array();
797
+ foreach ( (array) $row_data as $col_num => $val ) {
798
  // Don't use the value of the field key isn't set
799
+ if ( empty( $field_keys[ $col_num ] ) ) {
800
+ continue;
801
+ }
802
+ $author_data[ $field_keys[ $col_num ] ] = $val;
803
  }
804
+
805
  $authors[] = $author_data;
806
  }
807
  $row++;
808
  }
809
  fclose( $file );
810
 
811
+ WP_CLI::line( 'Found ' . count( $authors ) . ' authors in CSV' );
812
 
813
  foreach ( $authors as $author ) {
814
  WP_CLI::line( sprintf( 'Processing author %s (%s)', $author['user_login'], $author['user_email'] ) );
860
  if ( $guest_author_id ) {
861
  WP_CLI::line( sprintf( '-- Created as guest author #%s', $guest_author_id ) );
862
 
863
+ if ( isset( $author['author_id'] ) ) {
864
  update_post_meta( $guest_author_id, '_original_author_id', $author['ID'] );
865
+ }
866
 
867
  update_post_meta( $guest_author_id, '_original_author_login', $author['user_login'] );
868
  } else {
869
+ WP_CLI::warning( '-- Failed to create guest author.' );
870
  }
871
  } else {
872
  WP_CLI::line( sprintf( '-- Author already exists (ID #%s); skipping.', $guest_author->ID ) );
881
 
882
  $wpdb->queries = array(); // or define( 'WP_IMPORTING', true );
883
 
884
+ if ( ! is_object( $wp_object_cache ) ) {
885
  return;
886
+ }
887
 
888
  $wp_object_cache->group_ops = array();
889
  $wp_object_cache->stats = array();
890
  $wp_object_cache->memcache_debug = array();
891
  $wp_object_cache->cache = array();
892
 
893
+ if ( is_callable( $wp_object_cache, '__remoteset' ) ) {
894
  $wp_object_cache->__remoteset(); // important
895
+ }
896
  }
897
+ }
 
php/integrations/amp.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ add_action( 'pre_amp_render_post', 'cap_add_amp_actions' );
4
+ function cap_add_amp_actions() {
5
+ add_filter( 'amp_post_template_metadata', 'cap_update_amp_json_metadata', 10, 2 );
6
+ add_filter( 'amp_post_template_file', 'cap_set_amp_author_meta_template', 10, 3 );
7
+ }
8
+
9
+ function cap_update_amp_json_metadata( $metadata, $post ) {
10
+ $authors = get_coauthors( $post->ID );
11
+
12
+ $authors_json = array();
13
+ foreach ( $authors as $author ) {
14
+ $authors_json[] = array(
15
+ '@type' => 'Person',
16
+ 'name' => $author->display_name,
17
+ );
18
+ }
19
+ $metadata['author'] = $authors_json;
20
+
21
+ return $metadata;
22
+ }
23
+
24
+ function cap_set_amp_author_meta_template( $file, $type, $post ) {
25
+ if ( 'meta-author' === $type ) {
26
+ $file = dirname( __FILE__ ) . '/amp/meta-author.php';
27
+ }
28
+ return $file;
29
+ }
php/integrations/amp/meta-author.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php $coauthors = get_coauthors( $this->get( 'post_id' ) ); ?>
2
+ <li class="amp-wp-byline">
3
+ <?php coauthors(); ?>
4
+ </li>
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Co-Authors Plus ===
2
  Contributors: batmoo, danielbachhuber, automattic
3
  Tags: authors, users, multiple authors, coauthors, multi-author, publishing
4
- Tested up to: 4.5
5
- Requires at least: 3.7
6
- Stable tag: 3.1.1
7
 
8
  Assign multiple bylines to posts, pages, and custom post types via a search-as-you-type input box
9
 
@@ -57,6 +57,16 @@ Bug fixes and minor enhancements
57
 
58
  == Changelog ==
59
 
 
 
 
 
 
 
 
 
 
 
60
  = 3.1.1 (Mar. 20, 2014) =
61
  * Bug fix: Co-authors selection UI should appear when creating a new post too.
62
 
@@ -77,7 +87,7 @@ Bug fixes and minor enhancements
77
  * Better support for installing Co-Authors Plus as a symlinked directory. [Follow these instructions](http://kaspars.net/blog/wordpress/plugins-via-symlinks) to filter `plugins_url`.
78
  * Links to authors' posts pages to comply to hCard microformat, which Google depends on.
79
  * New `coauthors_emails()` template tag to list email addresses of the co-authors. Props [benlk](https://github.com/benlk).
80
- * Bug fix: Remove extraneous space between last two co-authors output. Props [johnciacia](https://github.com/johnciacia).
81
  * Updated French translation, courtesy of Jojaba (via email).
82
 
83
  = 3.0.6 (Dec. 9, 2013) =
@@ -196,8 +206,8 @@ Bug fixes and minor enhancements
196
  = 1.2.0 (Jun. 16, 2012) =
197
  * FIX: Added compatibility for WordPress 2.8
198
  * FIX: Added new template tags (get_the_coauthor_meta & the_coauthor_meta) to fix issues related to displaying author info on author archive pages. See [Other Notes](http://wordpress.org/extend/plugins/co-authors-plus/other_notes/) for details.
199
- * FIX: Plugin should now work for plugins not using the 'wp_' DB prefix
200
- * FIX: Coauthors should no longer be alphabetically reordered when the post is updated
201
  * FIX: Plugin now used WordPress native AJAX calls to tighten security
202
  * DOCS: Added details about the new template tags
203
 
1
  === Co-Authors Plus ===
2
  Contributors: batmoo, danielbachhuber, automattic
3
  Tags: authors, users, multiple authors, coauthors, multi-author, publishing
4
+ Tested up to: 4.5.2
5
+ Requires at least: 4.1
6
+ Stable tag: 3.2
7
 
8
  Assign multiple bylines to posts, pages, and custom post types via a search-as-you-type input box
9
 
57
 
58
  == Changelog ==
59
 
60
+ = 3.2 =
61
+ Various minor bug and security fixes
62
+
63
+ = 3.1.2 (Aug. 31, 2015) =
64
+ * Minor bug fixes and coding standards changes.
65
+ * The author's display name is now filtered through the_author in coauthors_posts_links_single()
66
+
67
+ = ??? (??? ?? ????) =
68
+ * New Russian and Ukrainian translations, courtesy of [Jurko Chervony](http://skinik.name/).
69
+
70
  = 3.1.1 (Mar. 20, 2014) =
71
  * Bug fix: Co-authors selection UI should appear when creating a new post too.
72
 
87
  * Better support for installing Co-Authors Plus as a symlinked directory. [Follow these instructions](http://kaspars.net/blog/wordpress/plugins-via-symlinks) to filter `plugins_url`.
88
  * Links to authors' posts pages to comply to hCard microformat, which Google depends on.
89
  * New `coauthors_emails()` template tag to list email addresses of the co-authors. Props [benlk](https://github.com/benlk).
90
+ * Bug fix: Remove extraneous space between last two co-authors output. Props [johnciacia](https://github.com/johnciacia).
91
  * Updated French translation, courtesy of Jojaba (via email).
92
 
93
  = 3.0.6 (Dec. 9, 2013) =
206
  = 1.2.0 (Jun. 16, 2012) =
207
  * FIX: Added compatibility for WordPress 2.8
208
  * FIX: Added new template tags (get_the_coauthor_meta & the_coauthor_meta) to fix issues related to displaying author info on author archive pages. See [Other Notes](http://wordpress.org/extend/plugins/co-authors-plus/other_notes/) for details.
209
+ * FIX: Plugin should now work for plugins not using the 'wp_' DB prefix
210
+ * FIX: Coauthors should no longer be alphabetically reordered when the post is updated
211
  * FIX: Plugin now used WordPress native AJAX calls to tighten security
212
  * DOCS: Added details about the new template tags
213
 
screenshot-1.png CHANGED
Binary file
screenshot-2.png CHANGED
Binary file
screenshot-3.png CHANGED
Binary file
template-tags.php CHANGED
@@ -2,33 +2,38 @@
2
 
3
  function get_coauthors( $post_id = 0 ) {
4
  global $post, $post_ID, $coauthors_plus, $wpdb;
5
-
6
  $coauthors = array();
7
- $post_id = (int)$post_id;
8
- if ( !$post_id && $post_ID )
9
  $post_id = $post_ID;
10
- if ( !$post_id && $post )
 
 
11
  $post_id = $post->ID;
12
-
 
13
  if ( $post_id ) {
14
  $coauthor_terms = get_the_terms( $post_id, $coauthors_plus->coauthor_taxonomy );
15
-
16
- if ( is_array( $coauthor_terms ) && !empty( $coauthor_terms ) ) {
17
- foreach( $coauthor_terms as $coauthor ) {
18
  $coauthor_slug = preg_replace( '#^cap\-#', '', $coauthor->slug );
19
- $post_author = $coauthors_plus->get_coauthor_by( 'user_nicename', $coauthor_slug );
20
  // In case the user has been deleted while plugin was deactivated
21
- if ( !empty( $post_author ) )
22
  $coauthors[] = $post_author;
 
23
  }
24
- } else if ( !$coauthors_plus->force_guest_authors ) {
25
- if ( $post ) {
26
  $post_author = get_userdata( $post->post_author );
27
  } else {
28
- $post_author = get_userdata( $wpdb->get_var( $wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d", $post_id ) ) );
29
  }
30
- if ( !empty( $post_author ) )
31
  $coauthors[] = $post_author;
 
32
  } // the empty else case is because if we force guest authors, we don't ever care what value wp_posts.post_author has.
33
  }
34
  return $coauthors;
@@ -36,29 +41,38 @@ function get_coauthors( $post_id = 0 ) {
36
 
37
  /**
38
  * Checks to see if the the specified user is author of the current global post or post (if specified)
39
- * @param object|int $user
40
  * @param int $post_id
41
  */
42
  function is_coauthor_for_post( $user, $post_id = 0 ) {
43
  global $post;
44
-
45
- if( ! $post_id && $post )
46
  $post_id = $post->ID;
47
- if( ! $post_id )
 
 
48
  return false;
 
49
 
50
- if ( ! $user )
51
  return false;
52
-
 
53
  $coauthors = get_coauthors( $post_id );
54
  if ( is_numeric( $user ) ) {
55
  $user = get_userdata( $user );
56
  $user = $user->user_login;
 
 
 
 
57
  }
58
-
59
- foreach( $coauthors as $coauthor ) {
60
- if ( $user == $coauthor->user_login || $user == $coauthor->linked_account )
61
  return true;
 
62
  }
63
  return false;
64
  }
@@ -69,56 +83,61 @@ class CoAuthorsIterator {
69
  var $current_author;
70
  var $authordata_array;
71
  var $count;
72
-
73
- function CoAuthorsIterator( $postID = 0 ){
74
  global $post, $authordata, $wpdb;
75
- $postID = (int)$postID;
76
- if( !$postID && $post )
77
- $postID = (int)$post->ID;
78
- if( !$postID )
79
- trigger_error(__('No post ID provided for CoAuthorsIterator constructor. Are you not in a loop or is $post not set?', 'co-authors-plus')); //return null;
 
 
 
80
 
81
  $this->original_authordata = $this->current_author = $authordata;
82
  $this->authordata_array = get_coauthors( $postID );
83
-
84
- $this->count = count($this->authordata_array);
85
  }
86
-
87
- function iterate(){
88
  global $authordata;
89
  $this->position++;
90
-
91
  //At the end of the loop
92
- if( $this->position > $this->count-1 ){
93
  $authordata = $this->current_author = $this->original_authordata;
94
  $this->position = -1;
95
  return false;
96
  }
97
-
98
  //At the beginning of the loop
99
- if( $this->position == 0 && !empty( $authordata ) )
100
  $this->original_authordata = $authordata;
101
-
102
- $authordata = $this->current_author = $this->authordata_array[$this->position];
103
-
 
104
  return true;
105
  }
106
-
107
- function get_position(){
108
- if ( $this->position === -1 )
109
  return false;
 
110
  return $this->position;
111
  }
112
- function is_last(){
113
- return $this->position === $this->count-1;
114
  }
115
- function is_first(){
116
  return $this->position === 0;
117
  }
118
- function count(){
119
  return $this->count;
120
  }
121
- function get_all(){
122
  return $this->authordata_array;
123
  }
124
  }
@@ -133,51 +152,56 @@ function coauthors__echo( $tag, $type = 'tag', $separators = array(), $tag_args
133
  $default_between_last = ( defined( 'COAUTHORS_DEFAULT_BETWEEN_LAST' ) ) ? COAUTHORS_DEFAULT_BETWEEN_LAST : __( ' and ', 'co-authors-plus' );
134
  $default_after = ( defined( 'COAUTHORS_DEFAULT_AFTER' ) ) ? COAUTHORS_DEFAULT_AFTER : '';
135
 
136
- if( ! isset( $separators['before'] ) || $separators['before'] === NULL )
137
  $separators['before'] = apply_filters( 'coauthors_default_before', $default_before );
138
- if( ! isset( $separators['between'] ) || $separators['between'] === NULL )
 
139
  $separators['between'] = apply_filters( 'coauthors_default_between', $default_between );
140
- if( ! isset( $separators['betweenLast'] ) || $separators['betweenLast'] === NULL )
 
141
  $separators['betweenLast'] = apply_filters( 'coauthors_default_between_last', $default_between_last );
142
- if( ! isset( $separators['after'] ) || $separators['after'] === NULL )
 
143
  $separators['after'] = apply_filters( 'coauthors_default_after', $default_after );
 
144
 
145
  $output = '';
146
-
147
  $i = new CoAuthorsIterator();
148
  $output .= $separators['before'];
149
  $i->iterate();
150
  do {
151
  $author_text = '';
152
-
153
- if( $type == 'tag' )
154
  $author_text = $tag( $tag_args );
155
- elseif( $type == 'field' && isset( $i->current_author->$tag ) )
156
  $author_text = $i->current_author->$tag;
157
- elseif( $type == 'callback' && is_callable( $tag ) )
158
  $author_text = call_user_func( $tag, $i->current_author );
159
-
 
160
  // Fallback to user_login if we get something empty
161
- if( empty( $author_text ) )
162
  $author_text = $i->current_author->user_login;
163
-
 
164
  // Append separators
165
- if ( ! $i->is_first() && $i->count() > 2 )
166
- $output .= $separators['between'];
167
-
168
- if ( $i->is_last() && $i->count() > 1 ) {
169
- $output = rtrim( $output, $separators['between'] );
170
- $output .= $separators['betweenLast'];
171
  }
172
-
173
- $output .= $author_text;
174
- } while( $i->iterate() );
175
-
176
  $output .= $separators['after'];
177
-
178
- if( $echo )
179
  echo $output;
180
-
 
181
  return $output;
182
  }
183
 
@@ -191,12 +215,12 @@ function coauthors__echo( $tag, $type = 'tag', $separators = array(), $tag_args
191
  * @param string $after What should appear after the presentation of co-authors
192
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
193
  */
194
- function coauthors( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ){
195
  return coauthors__echo('display_name', 'field', array(
196
  'between' => $between,
197
  'betweenLast' => $betweenLast,
198
  'before' => $before,
199
- 'after' => $after
200
  ), null, $echo );
201
  }
202
 
@@ -210,12 +234,12 @@ function coauthors( $between = null, $betweenLast = null, $before = null, $after
210
  * @param string $after What should appear after the presentation of co-authors
211
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
212
  */
213
- function coauthors_posts_links( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ){
214
  return coauthors__echo('coauthors_posts_links_single', 'callback', array(
215
  'between' => $between,
216
  'betweenLast' => $betweenLast,
217
  'before' => $before,
218
- 'after' => $after
219
  ), null, $echo );
220
  }
221
 
@@ -223,26 +247,35 @@ function coauthors_posts_links( $between = null, $betweenLast = null, $before =
223
  * Outputs a single co-author linked to their post archive.
224
  *
225
  * @param object $author
226
- * @return string
227
  */
228
  function coauthors_posts_links_single( $author ) {
 
 
 
 
 
 
 
 
 
229
  $args = array(
230
  'before_html' => '',
231
  'href' => get_author_posts_url( $author->ID, $author->user_nicename ),
232
  'rel' => 'author',
233
- 'title' => sprintf( __( 'Posts by %s', 'co-authors-plus' ), get_the_author() ),
234
- 'class' => 'url fn',
235
- 'text' => get_the_author(),
236
- 'after_html' => ''
237
  );
238
  $args = apply_filters( 'coauthors_posts_link', $args, $author );
239
  $single_link = sprintf(
240
- '<a href="%1$s" title="%2$s" class="%3$s" rel="%4$s">%5$s</a>',
241
- esc_url( $args['href'] ),
242
- esc_attr( $args['title'] ),
243
- esc_attr( $args['class'] ),
244
- esc_attr( $args['rel'] ),
245
- esc_html( $args['text'] )
246
  );
247
  return $args['before_html'] . $single_link . $args['after_html'];
248
  }
@@ -256,12 +289,12 @@ function coauthors_posts_links_single( $author ) {
256
  * @param string $after What should appear after the presentation of co-authors
257
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
258
  */
259
- function coauthors_firstnames($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ){
260
  return coauthors__echo('get_the_author_meta', 'tag', array(
261
  'between' => $between,
262
  'betweenLast' => $betweenLast,
263
  'before' => $before,
264
- 'after' => $after
265
  ), 'first_name', $echo );
266
  }
267
 
@@ -274,12 +307,12 @@ function coauthors_firstnames($between = null, $betweenLast = null, $before = nu
274
  * @param string $after What should appear after the presentation of co-authors
275
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
276
  */
277
- function coauthors_lastnames($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
278
- return coauthors__echo('get_the_author_meta', 'tag', array(
279
  'between' => $between,
280
  'betweenLast' => $betweenLast,
281
  'before' => $before,
282
- 'after' => $after
283
  ), 'last_name', $echo );
284
  }
285
 
@@ -292,12 +325,12 @@ function coauthors_lastnames($between = null, $betweenLast = null, $before = nul
292
  * @param string $after What should appear after the presentation of co-authors
293
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
294
  */
295
- function coauthors_nicknames($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
296
- return coauthors__echo('get_the_author_meta', 'tag', array(
297
  'between' => $between,
298
  'betweenLast' => $betweenLast,
299
  'before' => $before,
300
- 'after' => $after
301
  ), 'nickname', $echo );
302
  }
303
 
@@ -310,12 +343,12 @@ function coauthors_nicknames($between = null, $betweenLast = null, $before = nul
310
  * @param string $after What should appear after the presentation of co-authors
311
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
312
  */
313
- function coauthors_links($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
314
- return coauthors__echo('coauthors_links_single', 'callback', array(
315
  'between' => $between,
316
  'betweenLast' => $betweenLast,
317
  'before' => $before,
318
- 'after' => $after
319
  ), null, $echo );
320
  }
321
 
@@ -328,12 +361,12 @@ function coauthors_links($between = null, $betweenLast = null, $before = null, $
328
  * @param string $after What should appear after the presentation of email addresses
329
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
330
  */
331
- function coauthors_emails($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
332
- return coauthors__echo('get_the_author_meta', 'tag', array(
333
  'between' => $between,
334
  'betweenLast' => $betweenLast,
335
  'before' => $before,
336
- 'after' => $after
337
  ), 'user_email', $echo );
338
  }
339
 
@@ -341,13 +374,13 @@ function coauthors_emails($between = null, $betweenLast = null, $before = null,
341
  * Outputs a single co-author, linked to their website if they've provided one.
342
  *
343
  * @param object $author
344
- * @return string
345
  */
346
  function coauthors_links_single( $author ) {
347
- if ( get_the_author_meta('url') ) {
348
  return sprintf( '<a href="%s" title="%s" rel="external">%s</a>',
349
- get_the_author_meta('url'),
350
- esc_attr( sprintf(__("Visit %s&#8217;s website"), get_the_author()) ),
351
  get_the_author()
352
  );
353
  } else {
@@ -364,31 +397,31 @@ function coauthors_links_single( $author ) {
364
  * @param string $after What should appear after the presentation of co-authors
365
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
366
  */
367
- function coauthors_IDs($between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
368
- return coauthors__echo('ID', 'field', array(
369
  'between' => $between,
370
  'betweenLast' => $betweenLast,
371
  'before' => $before,
372
- 'after' => $after
373
  ), null, $echo );
374
  }
375
 
376
  function get_the_coauthor_meta( $field ) {
377
  global $wp_query, $post;
378
-
379
  $coauthors = get_coauthors();
380
  $meta = array();
381
-
382
- foreach( $coauthors as $coauthor ) {
383
  $user_id = $coauthor->ID;
384
- $meta[$user_id] = get_the_author_meta( $field, $user_id );
385
  }
386
  return $meta;
387
  }
388
 
389
  function the_coauthor_meta( $field, $user_id = 0 ) {
390
  // TODO: need before after options
391
- echo get_the_coauthor_meta($field, $user_id);
392
  }
393
 
394
  /**
@@ -424,56 +457,64 @@ function coauthors_wp_list_authors( $args = array() ) {
424
  $term_args = array(
425
  'orderby' => 'name',
426
  'hide_empty' => 0,
427
- 'number' => (int)$args['number'],
428
  );
429
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, $term_args );
430
  $authors = array();
431
- foreach( $author_terms as $author_term ) {
432
  // Something's wrong in the state of Denmark
433
- if ( false === ( $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $author_term->name ) ) )
434
  continue;
 
 
 
435
 
436
- $authors[$author_term->name] = $coauthor;
437
-
438
- $authors[$author_term->name]->post_count = $author_term->count;
439
  }
440
 
 
 
441
  foreach ( (array) $authors as $author ) {
442
 
443
  $link = '';
444
 
445
- if ( $args['show_fullname'] && ( $author->first_name && $author->last_name ) )
446
  $name = "$author->first_name $author->last_name";
447
- else
448
  $name = $author->display_name;
449
-
450
 
451
  if ( ! $args['html'] ) {
452
- if ( $author->post_count == 0 ) {
453
- if ( ! $args['hide_empty'] )
454
  $return .= $name . ', ';
455
- } else
 
456
  $return .= $name . ', ';
 
457
 
458
  // No need to go further to process HTML.
459
  continue;
460
  }
461
 
462
- if ( ! ( $author->post_count == 0 && $args['hide_empty'] ) && 'list' == $args['style'] )
463
  $return .= '<li>';
464
- if ( $author->post_count == 0 ) {
465
- if ( ! $args['hide_empty'] )
 
466
  $link = $name;
 
467
  } else {
468
- $link = '<a href="' . get_author_posts_url( $author->ID, $author->user_nicename ) . '" title="' . esc_attr( sprintf( __("Posts by %s", 'co-authors-plus' ), $name ) ) . '">' . esc_html( $name ) . '</a>';
469
 
470
- if ( (! empty( $args['feed_image'] ) ) || ( ! empty( $args['feed'] ) ) ) {
471
  $link .= ' ';
472
- if ( empty( $args['feed_image'] ) )
473
  $link .= '(';
 
474
  $link .= '<a href="' . get_author_feed_link( $author->ID ) . '"';
475
 
476
- if ( !empty( $args['feed'] ) ) {
477
  $title = ' title="' . esc_attr( $args['feed'] ) . '"';
478
  $alt = ' alt="' . esc_attr( $args['feed'] ) . '"';
479
  $name = $feed;
@@ -482,32 +523,36 @@ function coauthors_wp_list_authors( $args = array() ) {
482
 
483
  $link .= '>';
484
 
485
- if ( ! empty( $args['feed_image'] ) )
486
- $link .= "<img src=\"" . esc_url( $args['feed_image'] ) . "\" style=\"border: none;\"$alt$title" . ' />';
487
- else
488
  $link .= $name;
 
489
 
490
  $link .= '</a>';
491
 
492
- if ( empty( $args['feed_image'] ) )
493
  $link .= ')';
 
494
  }
495
 
496
- if ( $args['optioncount'] )
497
  $link .= ' ('. $author->post_count . ')';
498
-
499
  }
500
 
501
- if ( ! ( $author->post_count == 0 && $args['hide_empty'] ) && 'list' == $args['style'] )
502
  $return .= $link . '</li>';
503
- else if ( ! $args['hide_empty'] )
504
  $return .= $link . ', ';
 
505
  }
506
 
507
  $return = trim( $return, ', ' );
508
 
509
- if ( ! $args['echo'] )
510
  return $return;
 
511
  echo $return;
512
  }
513
 
@@ -517,9 +562,9 @@ function coauthors_wp_list_authors( $args = array() ) {
517
  * Since Guest Authors doesn't enforce unique email addresses, simply loading the avatar by email won't work when
518
  * multiple Guest Authors share the same address.
519
  *
520
- * This is a replacement for using get_avatar(), which only operates on email addresses and cannot differentiate
521
  * between Guest Authors (who may share an email) and regular user accounts
522
- *
523
  * @param object $coauthor The Co Author or Guest Author object
524
  * @param int $size The desired size
525
  * @return string The image tag for the avatar, or an empty string if none could be determined
@@ -527,20 +572,23 @@ function coauthors_wp_list_authors( $args = array() ) {
527
  function coauthors_get_avatar( $coauthor, $size = 32, $default = '', $alt = false ) {
528
  global $coauthors_plus;
529
 
530
- if ( ! is_object( $coauthor ) )
531
  return '';
 
532
 
533
  if ( isset( $coauthor->type ) && 'guest-author' == $coauthor->type ) {
534
  $guest_author_thumbnail = $coauthors_plus->guest_authors->get_guest_author_thumbnail( $coauthor, $size );
535
 
536
- if ( $guest_author_thumbnail )
537
  return $guest_author_thumbnail;
 
538
  }
539
 
540
  // Make sure we're dealing with an object for which we can retrieve an email
541
- if ( isset( $coauthor->user_email ) )
542
  return get_avatar( $coauthor->user_email, $size, $default, $alt );
 
543
 
544
  // Nothing matched, an invalid object was passed.
545
  return '';
546
- }
2
 
3
  function get_coauthors( $post_id = 0 ) {
4
  global $post, $post_ID, $coauthors_plus, $wpdb;
5
+
6
  $coauthors = array();
7
+ $post_id = (int) $post_id;
8
+ if ( ! $post_id && $post_ID ) {
9
  $post_id = $post_ID;
10
+ }
11
+
12
+ if ( ! $post_id && $post ) {
13
  $post_id = $post->ID;
14
+ }
15
+
16
  if ( $post_id ) {
17
  $coauthor_terms = get_the_terms( $post_id, $coauthors_plus->coauthor_taxonomy );
18
+
19
+ if ( is_array( $coauthor_terms ) && ! empty( $coauthor_terms ) ) {
20
+ foreach ( $coauthor_terms as $coauthor ) {
21
  $coauthor_slug = preg_replace( '#^cap\-#', '', $coauthor->slug );
22
+ $post_author = $coauthors_plus->get_coauthor_by( 'user_nicename', $coauthor_slug );
23
  // In case the user has been deleted while plugin was deactivated
24
+ if ( ! empty( $post_author ) ) {
25
  $coauthors[] = $post_author;
26
+ }
27
  }
28
+ } else if ( ! $coauthors_plus->force_guest_authors ) {
29
+ if ( $post && $post_id == $post->ID ) {
30
  $post_author = get_userdata( $post->post_author );
31
  } else {
32
+ $post_author = get_userdata( $wpdb->get_var( $wpdb->prepare( "SELECT post_author FROM $wpdb->posts WHERE ID = %d", $post_id ) ) );
33
  }
34
+ if ( ! empty( $post_author ) ) {
35
  $coauthors[] = $post_author;
36
+ }
37
  } // the empty else case is because if we force guest authors, we don't ever care what value wp_posts.post_author has.
38
  }
39
  return $coauthors;
41
 
42
  /**
43
  * Checks to see if the the specified user is author of the current global post or post (if specified)
44
+ * @param object|int $user
45
  * @param int $post_id
46
  */
47
  function is_coauthor_for_post( $user, $post_id = 0 ) {
48
  global $post;
49
+
50
+ if ( ! $post_id && $post ) {
51
  $post_id = $post->ID;
52
+ }
53
+
54
+ if ( ! $post_id ) {
55
  return false;
56
+ }
57
 
58
+ if ( ! $user ) {
59
  return false;
60
+ }
61
+
62
  $coauthors = get_coauthors( $post_id );
63
  if ( is_numeric( $user ) ) {
64
  $user = get_userdata( $user );
65
  $user = $user->user_login;
66
+ } else if ( isset( $user->user_login ) ) {
67
+ $user = $user->user_login;
68
+ } else {
69
+ return false;
70
  }
71
+
72
+ foreach ( $coauthors as $coauthor ) {
73
+ if ( $user == $coauthor->user_login || $user == $coauthor->linked_account ) {
74
  return true;
75
+ }
76
  }
77
  return false;
78
  }
83
  var $current_author;
84
  var $authordata_array;
85
  var $count;
86
+
87
+ function __construct( $postID = 0 ) {
88
  global $post, $authordata, $wpdb;
89
+ $postID = (int) $postID;
90
+ if ( ! $postID && $post ) {
91
+ $postID = (int) $post->ID;
92
+ }
93
+
94
+ if ( ! $postID ) {
95
+ trigger_error( esc_html__( 'No post ID provided for CoAuthorsIterator constructor. Are you not in a loop or is $post not set?', 'co-authors-plus' ) ); // return null;
96
+ }
97
 
98
  $this->original_authordata = $this->current_author = $authordata;
99
  $this->authordata_array = get_coauthors( $postID );
100
+
101
+ $this->count = count( $this->authordata_array );
102
  }
103
+
104
+ function iterate() {
105
  global $authordata;
106
  $this->position++;
107
+
108
  //At the end of the loop
109
+ if ( $this->position > $this->count - 1 ) {
110
  $authordata = $this->current_author = $this->original_authordata;
111
  $this->position = -1;
112
  return false;
113
  }
114
+
115
  //At the beginning of the loop
116
+ if ( 0 === $this->position && ! empty( $authordata ) ) {
117
  $this->original_authordata = $authordata;
118
+ }
119
+
120
+ $authordata = $this->current_author = $this->authordata_array[ $this->position ];
121
+
122
  return true;
123
  }
124
+
125
+ function get_position() {
126
+ if ( $this->position === -1 ) {
127
  return false;
128
+ }
129
  return $this->position;
130
  }
131
+ function is_last() {
132
+ return $this->position === $this->count - 1;
133
  }
134
+ function is_first() {
135
  return $this->position === 0;
136
  }
137
+ function count() {
138
  return $this->count;
139
  }
140
+ function get_all() {
141
  return $this->authordata_array;
142
  }
143
  }
152
  $default_between_last = ( defined( 'COAUTHORS_DEFAULT_BETWEEN_LAST' ) ) ? COAUTHORS_DEFAULT_BETWEEN_LAST : __( ' and ', 'co-authors-plus' );
153
  $default_after = ( defined( 'COAUTHORS_DEFAULT_AFTER' ) ) ? COAUTHORS_DEFAULT_AFTER : '';
154
 
155
+ if ( ! isset( $separators['before'] ) || null === $separators['before'] ) {
156
  $separators['before'] = apply_filters( 'coauthors_default_before', $default_before );
157
+ }
158
+ if ( ! isset( $separators['between'] ) || null === $separators['between'] ) {
159
  $separators['between'] = apply_filters( 'coauthors_default_between', $default_between );
160
+ }
161
+ if ( ! isset( $separators['betweenLast'] ) || null === $separators['betweenLast'] ) {
162
  $separators['betweenLast'] = apply_filters( 'coauthors_default_between_last', $default_between_last );
163
+ }
164
+ if ( ! isset( $separators['after'] ) || null === $separators['after'] ) {
165
  $separators['after'] = apply_filters( 'coauthors_default_after', $default_after );
166
+ }
167
 
168
  $output = '';
169
+
170
  $i = new CoAuthorsIterator();
171
  $output .= $separators['before'];
172
  $i->iterate();
173
  do {
174
  $author_text = '';
175
+
176
+ if ( 'tag' === $type ) {
177
  $author_text = $tag( $tag_args );
178
+ } elseif ( 'field' === $type && isset( $i->current_author->$tag ) ) {
179
  $author_text = $i->current_author->$tag;
180
+ } elseif ( 'callback' === $type && is_callable( $tag ) ) {
181
  $author_text = call_user_func( $tag, $i->current_author );
182
+ }
183
+
184
  // Fallback to user_login if we get something empty
185
+ if ( empty( $author_text ) ) {
186
  $author_text = $i->current_author->user_login;
187
+ }
188
+
189
  // Append separators
190
+ if ( $i->count() - $i->position == 1 ) { // last author or only author
191
+ $output .= $author_text;
192
+ } elseif ( $i->count() - $i->position == 2 ) { // second to last
193
+ $output .= $author_text . $separators['betweenLast'];
194
+ } else {
195
+ $output .= $author_text . $separators['between'];
196
  }
197
+ } while ( $i->iterate() );
198
+
 
 
199
  $output .= $separators['after'];
200
+
201
+ if ( $echo ) {
202
  echo $output;
203
+ }
204
+
205
  return $output;
206
  }
207
 
215
  * @param string $after What should appear after the presentation of co-authors
216
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
217
  */
218
+ function coauthors( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
219
  return coauthors__echo('display_name', 'field', array(
220
  'between' => $between,
221
  'betweenLast' => $betweenLast,
222
  'before' => $before,
223
+ 'after' => $after,
224
  ), null, $echo );
225
  }
226
 
234
  * @param string $after What should appear after the presentation of co-authors
235
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
236
  */
237
+ function coauthors_posts_links( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
238
  return coauthors__echo('coauthors_posts_links_single', 'callback', array(
239
  'between' => $between,
240
  'betweenLast' => $betweenLast,
241
  'before' => $before,
242
+ 'after' => $after,
243
  ), null, $echo );
244
  }
245
 
247
  * Outputs a single co-author linked to their post archive.
248
  *
249
  * @param object $author
250
+ * @return string
251
  */
252
  function coauthors_posts_links_single( $author ) {
253
+ // Return if the fields we are trying to use are not sent
254
+ if ( ! isset( $author->ID, $author->user_nicename, $author->display_name ) ) {
255
+ _doing_it_wrong(
256
+ 'coauthors_posts_links_single',
257
+ 'Invalid author object used',
258
+ '3.2'
259
+ );
260
+ return;
261
+ }
262
  $args = array(
263
  'before_html' => '',
264
  'href' => get_author_posts_url( $author->ID, $author->user_nicename ),
265
  'rel' => 'author',
266
+ 'title' => sprintf( __( 'Posts by %s', 'co-authors-plus' ), apply_filters( 'the_author', $author->display_name ) ),
267
+ 'class' => 'author url fn',
268
+ 'text' => apply_filters( 'the_author', $author->display_name ),
269
+ 'after_html' => '',
270
  );
271
  $args = apply_filters( 'coauthors_posts_link', $args, $author );
272
  $single_link = sprintf(
273
+ '<a href="%1$s" title="%2$s" class="%3$s" rel="%4$s">%5$s</a>',
274
+ esc_url( $args['href'] ),
275
+ esc_attr( $args['title'] ),
276
+ esc_attr( $args['class'] ),
277
+ esc_attr( $args['rel'] ),
278
+ esc_html( $args['text'] )
279
  );
280
  return $args['before_html'] . $single_link . $args['after_html'];
281
  }
289
  * @param string $after What should appear after the presentation of co-authors
290
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
291
  */
292
+ function coauthors_firstnames( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
293
  return coauthors__echo('get_the_author_meta', 'tag', array(
294
  'between' => $between,
295
  'betweenLast' => $betweenLast,
296
  'before' => $before,
297
+ 'after' => $after,
298
  ), 'first_name', $echo );
299
  }
300
 
307
  * @param string $after What should appear after the presentation of co-authors
308
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
309
  */
310
+ function coauthors_lastnames( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
311
+ return coauthors__echo( 'get_the_author_meta', 'tag', array(
312
  'between' => $between,
313
  'betweenLast' => $betweenLast,
314
  'before' => $before,
315
+ 'after' => $after,
316
  ), 'last_name', $echo );
317
  }
318
 
325
  * @param string $after What should appear after the presentation of co-authors
326
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
327
  */
328
+ function coauthors_nicknames( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
329
+ return coauthors__echo( 'get_the_author_meta', 'tag', array(
330
  'between' => $between,
331
  'betweenLast' => $betweenLast,
332
  'before' => $before,
333
+ 'after' => $after,
334
  ), 'nickname', $echo );
335
  }
336
 
343
  * @param string $after What should appear after the presentation of co-authors
344
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
345
  */
346
+ function coauthors_links( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
347
+ return coauthors__echo( 'coauthors_links_single', 'callback', array(
348
  'between' => $between,
349
  'betweenLast' => $betweenLast,
350
  'before' => $before,
351
+ 'after' => $after,
352
  ), null, $echo );
353
  }
354
 
361
  * @param string $after What should appear after the presentation of email addresses
362
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
363
  */
364
+ function coauthors_emails( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
365
+ return coauthors__echo( 'get_the_author_meta', 'tag', array(
366
  'between' => $between,
367
  'betweenLast' => $betweenLast,
368
  'before' => $before,
369
+ 'after' => $after,
370
  ), 'user_email', $echo );
371
  }
372
 
374
  * Outputs a single co-author, linked to their website if they've provided one.
375
  *
376
  * @param object $author
377
+ * @return string
378
  */
379
  function coauthors_links_single( $author ) {
380
+ if ( get_the_author_meta( 'url' ) ) {
381
  return sprintf( '<a href="%s" title="%s" rel="external">%s</a>',
382
+ get_the_author_meta( 'url' ),
383
+ esc_attr( sprintf( __( 'Visit %s&#8217;s website' ), get_the_author() ) ),
384
  get_the_author()
385
  );
386
  } else {
397
  * @param string $after What should appear after the presentation of co-authors
398
  * @param bool $echo Whether the co-authors should be echoed or returned. Defaults to true.
399
  */
400
+ function coauthors_ids( $between = null, $betweenLast = null, $before = null, $after = null, $echo = true ) {
401
+ return coauthors__echo( 'ID', 'field', array(
402
  'between' => $between,
403
  'betweenLast' => $betweenLast,
404
  'before' => $before,
405
+ 'after' => $after,
406
  ), null, $echo );
407
  }
408
 
409
  function get_the_coauthor_meta( $field ) {
410
  global $wp_query, $post;
411
+
412
  $coauthors = get_coauthors();
413
  $meta = array();
414
+
415
+ foreach ( $coauthors as $coauthor ) {
416
  $user_id = $coauthor->ID;
417
+ $meta[ $user_id ] = get_the_author_meta( $field, $user_id );
418
  }
419
  return $meta;
420
  }
421
 
422
  function the_coauthor_meta( $field, $user_id = 0 ) {
423
  // TODO: need before after options
424
+ echo get_the_coauthor_meta( $field, $user_id );
425
  }
426
 
427
  /**
457
  $term_args = array(
458
  'orderby' => 'name',
459
  'hide_empty' => 0,
460
+ 'number' => (int) $args['number'],
461
  );
462
  $author_terms = get_terms( $coauthors_plus->coauthor_taxonomy, $term_args );
463
  $authors = array();
464
+ foreach ( $author_terms as $author_term ) {
465
  // Something's wrong in the state of Denmark
466
+ if ( false === ( $coauthor = $coauthors_plus->get_coauthor_by( 'user_login', $author_term->name ) ) ) {
467
  continue;
468
+ }
469
+
470
+ $authors[ $author_term->name ] = $coauthor;
471
 
472
+ $authors[ $author_term->name ]->post_count = $author_term->count;
 
 
473
  }
474
 
475
+ $authors = apply_filters( 'coauthors_wp_list_authors_array', $authors );
476
+
477
  foreach ( (array) $authors as $author ) {
478
 
479
  $link = '';
480
 
481
+ if ( $args['show_fullname'] && ( $author->first_name && $author->last_name ) ) {
482
  $name = "$author->first_name $author->last_name";
483
+ } else {
484
  $name = $author->display_name;
485
+ }
486
 
487
  if ( ! $args['html'] ) {
488
+ if ( 0 === $author->post_count ) {
489
+ if ( ! $args['hide_empty'] ) {
490
  $return .= $name . ', ';
491
+ }
492
+ } else {
493
  $return .= $name . ', ';
494
+ }
495
 
496
  // No need to go further to process HTML.
497
  continue;
498
  }
499
 
500
+ if ( ! ( 0 === $author->post_count && $args['hide_empty'] ) && 'list' == $args['style'] ) {
501
  $return .= '<li>';
502
+ }
503
+ if ( 0 === $author->post_count ) {
504
+ if ( ! $args['hide_empty'] ) {
505
  $link = $name;
506
+ }
507
  } else {
508
+ $link = '<a href="' . get_author_posts_url( $author->ID, $author->user_nicename ) . '" title="' . esc_attr( sprintf( __( 'Posts by %s', 'co-authors-plus' ), $name ) ) . '">' . esc_html( $name ) . '</a>';
509
 
510
+ if ( ( ! empty( $args['feed_image'] ) ) || ( ! empty( $args['feed'] ) ) ) {
511
  $link .= ' ';
512
+ if ( empty( $args['feed_image'] ) ) {
513
  $link .= '(';
514
+ }
515
  $link .= '<a href="' . get_author_feed_link( $author->ID ) . '"';
516
 
517
+ if ( ! empty( $args['feed'] ) ) {
518
  $title = ' title="' . esc_attr( $args['feed'] ) . '"';
519
  $alt = ' alt="' . esc_attr( $args['feed'] ) . '"';
520
  $name = $feed;
523
 
524
  $link .= '>';
525
 
526
+ if ( ! empty( $args['feed_image'] ) ) {
527
+ $link .= '<img src="' . esc_url( $args['feed_image'] ) . "\" style=\"border: none;\"$alt$title" . ' />';
528
+ } else {
529
  $link .= $name;
530
+ }
531
 
532
  $link .= '</a>';
533
 
534
+ if ( empty( $args['feed_image'] ) ) {
535
  $link .= ')';
536
+ }
537
  }
538
 
539
+ if ( $args['optioncount'] ) {
540
  $link .= ' ('. $author->post_count . ')';
541
+ }
542
  }
543
 
544
+ if ( ! ( 0 === $author->post_count && $args['hide_empty'] ) && 'list' == $args['style'] ) {
545
  $return .= $link . '</li>';
546
+ } else if ( ! $args['hide_empty'] ) {
547
  $return .= $link . ', ';
548
+ }
549
  }
550
 
551
  $return = trim( $return, ', ' );
552
 
553
+ if ( ! $args['echo'] ) {
554
  return $return;
555
+ }
556
  echo $return;
557
  }
558
 
562
  * Since Guest Authors doesn't enforce unique email addresses, simply loading the avatar by email won't work when
563
  * multiple Guest Authors share the same address.
564
  *
565
+ * This is a replacement for using get_avatar(), which only operates on email addresses and cannot differentiate
566
  * between Guest Authors (who may share an email) and regular user accounts
567
+ *
568
  * @param object $coauthor The Co Author or Guest Author object
569
  * @param int $size The desired size
570
  * @return string The image tag for the avatar, or an empty string if none could be determined
572
  function coauthors_get_avatar( $coauthor, $size = 32, $default = '', $alt = false ) {
573
  global $coauthors_plus;
574
 
575
+ if ( ! is_object( $coauthor ) ) {
576
  return '';
577
+ }
578
 
579
  if ( isset( $coauthor->type ) && 'guest-author' == $coauthor->type ) {
580
  $guest_author_thumbnail = $coauthors_plus->guest_authors->get_guest_author_thumbnail( $coauthor, $size );
581
 
582
+ if ( $guest_author_thumbnail ) {
583
  return $guest_author_thumbnail;
584
+ }
585
  }
586
 
587
  // Make sure we're dealing with an object for which we can retrieve an email
588
+ if ( isset( $coauthor->user_email ) ) {
589
  return get_avatar( $coauthor->user_email, $size, $default, $alt );
590
+ }
591
 
592
  // Nothing matched, an invalid object was passed.
593
  return '';
594
+ }
tests/bootstrap.php CHANGED
@@ -1,7 +1,9 @@
1
  <?php
2
 
3
- $_tests_dir = getenv('WP_TESTS_DIR');
4
- if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
 
 
5
 
6
  require_once $_tests_dir . '/includes/functions.php';
7
 
1
  <?php
2
 
3
+ $_tests_dir = getenv( 'WP_TESTS_DIR' );
4
+ if ( ! $_tests_dir ) {
5
+ $_tests_dir = '/tmp/wordpress-tests-lib';
6
+ }
7
 
8
  require_once $_tests_dir . '/includes/functions.php';
9
 
tests/coauthorsplus-testcase.php CHANGED
@@ -64,5 +64,4 @@ class CoAuthorsPlus_TestCase extends WP_UnitTestCase {
64
  parent::tearDown();
65
  $wpdb->suppress_errors( $this->suppress );
66
  }
67
-
68
- }
64
  parent::tearDown();
65
  $wpdb->suppress_errors( $this->suppress );
66
  }
67
+ }
 
tests/test-author-queries.php CHANGED
@@ -4,14 +4,14 @@
4
  */
5
 
6
  class Test_Author_Queries extends CoAuthorsPlus_TestCase {
7
-
8
  /**
9
  * On author pages, the queried object should only be set
10
  * to a user that's not a member of the blog if they
11
  * have at least one published post. This matches core behavior.
12
- *
13
  * @see https://core.trac.wordpress.org/changeset/27290
14
- */
15
  function test_author_queried_object_fix() {
16
  global $wp_rewrite, $coauthors_plus;
17
 
@@ -20,7 +20,7 @@ class Test_Author_Queries extends CoAuthorsPlus_TestCase {
20
  */
21
  $author1 = $this->factory->user->create( array( 'user_login' => 'msauthor1' ) );
22
  $author2 = $this->factory->user->create( array( 'user_login' => 'msauthor2' ) );
23
- $blog2 = $this->factory->blog->create( array( 'user_id' => $author1 ) );
24
 
25
  switch_to_blog( $blog2 );
26
  $wp_rewrite->init();
@@ -30,7 +30,7 @@ class Test_Author_Queries extends CoAuthorsPlus_TestCase {
30
  'post_content' => rand_str(),
31
  'post_title' => rand_str(),
32
  'post_author' => $author1,
33
- ) );
34
 
35
  /**
36
  * Author 1 is an author on the blog
@@ -84,6 +84,5 @@ class Test_Author_Queries extends CoAuthorsPlus_TestCase {
84
 
85
  restore_current_blog();
86
 
87
- }
88
-
89
- }
4
  */
5
 
6
  class Test_Author_Queries extends CoAuthorsPlus_TestCase {
7
+
8
  /**
9
  * On author pages, the queried object should only be set
10
  * to a user that's not a member of the blog if they
11
  * have at least one published post. This matches core behavior.
12
+ *
13
  * @see https://core.trac.wordpress.org/changeset/27290
14
+ */
15
  function test_author_queried_object_fix() {
16
  global $wp_rewrite, $coauthors_plus;
17
 
20
  */
21
  $author1 = $this->factory->user->create( array( 'user_login' => 'msauthor1' ) );
22
  $author2 = $this->factory->user->create( array( 'user_login' => 'msauthor2' ) );
23
+ $blog2 = $this->factory->blog->create( array( 'user_id' => $author1 ) );
24
 
25
  switch_to_blog( $blog2 );
26
  $wp_rewrite->init();
30
  'post_content' => rand_str(),
31
  'post_title' => rand_str(),
32
  'post_author' => $author1,
33
+ ) );
34
 
35
  /**
36
  * Author 1 is an author on the blog
84
 
85
  restore_current_blog();
86
 
87
+ }
88
+ }
 
tests/test-manage-coauthors.php CHANGED
@@ -27,7 +27,7 @@ class Test_Manage_CoAuthors extends CoAuthorsPlus_TestCase {
27
  /**
28
  * When a co-author is assigned to a post, the post author value
29
  * should be set appropriately
30
- *
31
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/140
32
  */
33
  public function test_add_coauthor_updates_post_author() {
@@ -46,7 +46,7 @@ class Test_Manage_CoAuthors extends CoAuthorsPlus_TestCase {
46
 
47
  /**
48
  * Post published count should default to 'post', but be filterable
49
- *
50
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/170
51
  */
52
  public function test_post_publish_count_for_coauthor() {
@@ -94,5 +94,4 @@ class Test_Manage_CoAuthors extends CoAuthorsPlus_TestCase {
94
  $this->assertEquals( 1, count_user_posts( $editor1->ID ) );
95
 
96
  }
97
-
98
- }
27
  /**
28
  * When a co-author is assigned to a post, the post author value
29
  * should be set appropriately
30
+ *
31
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/140
32
  */
33
  public function test_add_coauthor_updates_post_author() {
46
 
47
  /**
48
  * Post published count should default to 'post', but be filterable
49
+ *
50
  * @see https://github.com/Automattic/Co-Authors-Plus/issues/170
51
  */
52
  public function test_post_publish_count_for_coauthor() {
94
  $this->assertEquals( 1, count_user_posts( $editor1->ID ) );
95
 
96
  }
97
+ }
 
upgrade.php CHANGED
@@ -1,46 +1,48 @@
1
  <?php
2
  function coauthors_plus_upgrade( $from ) {
3
  // TODO: handle upgrade failures
4
-
5
- if( $from < 2.0 ) coauthors_plus_upgrade_20();
 
 
6
  }
7
 
8
- /**
9
  * Upgrade to 2.0
10
  * Updates coauthors from old meta-based storage to taxonomy-based
11
  */
12
- function coauthors_plus_upgrade_20 () {
13
  global $coauthors_plus;
14
-
15
  // Get all posts with meta_key _coauthor
16
- $all_posts = get_posts(array('numberposts' => '-1', 'meta_key' => '_coauthor'));
17
-
18
- if(is_array($all_posts)) {
19
- foreach($all_posts as $single_post) {
20
-
21
  // reset execution time limit
22
  set_time_limit( 60 );
23
-
24
  // create new array
25
  $coauthors = array();
26
  // get author id -- try to use get_profile
27
- $coauthor = get_user_by( 'id', (int)$single_post->post_author );
28
- if ( is_object( $coauthor ) )
29
  $coauthors[] = $coauthor->user_login;
 
30
  // get coauthors id
31
- $legacy_coauthors = get_post_meta($single_post->ID, '_coauthor');
32
-
33
- if(is_array($legacy_coauthors)) {
34
- //echo '<p>Has Legacy coauthors';
35
- foreach($legacy_coauthors as $legacy_coauthor) {
36
- $legacy_coauthor_login = get_user_by( 'id', (int)$legacy_coauthor );
37
- if ( is_object( $legacy_coauthor_login ) && ! in_array( $legacy_coauthor_login->user_login, $coauthors ) ) $coauthors[] = $legacy_coauthor_login->user_login;
 
38
  }
39
- } else {
40
- // No Legacy coauthors
41
  }
42
- $coauthors_plus->add_coauthors($single_post->ID, $coauthors);
43
-
44
  }
45
  }
46
  }
1
  <?php
2
  function coauthors_plus_upgrade( $from ) {
3
  // TODO: handle upgrade failures
4
+
5
+ if ( $from < 2.0 ) {
6
+ coauthors_plus_upgrade_20();
7
+ }
8
  }
9
 
10
+ /**
11
  * Upgrade to 2.0
12
  * Updates coauthors from old meta-based storage to taxonomy-based
13
  */
14
+ function coauthors_plus_upgrade_20() {
15
  global $coauthors_plus;
16
+
17
  // Get all posts with meta_key _coauthor
18
+ $all_posts = get_posts( array( 'numberposts' => '-1', 'meta_key' => '_coauthor' ) );
19
+
20
+ if ( is_array( $all_posts ) ) {
21
+ foreach ( $all_posts as $single_post ) {
22
+
23
  // reset execution time limit
24
  set_time_limit( 60 );
25
+
26
  // create new array
27
  $coauthors = array();
28
  // get author id -- try to use get_profile
29
+ $coauthor = get_user_by( 'id', (int) $single_post->post_author );
30
+ if ( is_object( $coauthor ) ) {
31
  $coauthors[] = $coauthor->user_login;
32
+ }
33
  // get coauthors id
34
+ $legacy_coauthors = get_post_meta( $single_post->ID, '_coauthor' );
35
+
36
+ if ( is_array( $legacy_coauthors ) ) {
37
+ foreach ( $legacy_coauthors as $legacy_coauthor ) {
38
+ $legacy_coauthor_login = get_user_by( 'id', (int) $legacy_coauthor );
39
+ if ( is_object( $legacy_coauthor_login ) && ! in_array( $legacy_coauthor_login->user_login, $coauthors ) ) {
40
+ $coauthors[] = $legacy_coauthor_login->user_login;
41
+ }
42
  }
 
 
43
  }
44
+ $coauthors_plus->add_coauthors( $single_post->ID, $coauthors );
45
+
46
  }
47
  }
48
  }