diff --git a/.travis.yml b/.travis.yml index da7b0e08..9e4f89af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,34 @@ language: php php: - - 5.3 - - 5.5 + - "nightly" env: - WP_VERSION=latest - - WP_VERSION=4.1 - - WP_VERSION=4.0 + +matrix: + include: +# nightly+latest already included above as first build. +# - php: "nightly" +# env: WP_VERSION=latest + - php: "nightly" + env: WP_VERSION=4.6 + - php: "nightly" + env: WP_VERSION=4.5 + - php: "5.2" + env: WP_VERSION=latest + - php: "5.2" + env: WP_VERSION=4.6 + - php: "5.2" + env: WP_VERSION=4.5 + - php: "5.6" + env: WP_VERSION=latest + - php: "5.6" + env: WP_VERSION=4.6 + - php: "5.6" + env: WP_VERSION=4.5 before_script: - - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION + - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION -script: - - make lint - - make phpunit +script: phpunit diff --git a/co-authors-plus.php b/co-authors-plus.php index 339184a9..f537e168 100644 --- a/co-authors-plus.php +++ b/co-authors-plus.php @@ -3,7 +3,7 @@ Plugin Name: Co-Authors Plus Plugin URI: http://wordpress.org/extend/plugins/co-authors-plus/ 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. -Version: 3.1.2 +Version: 3.2.1 Author: Mohammad Jangda, Daniel Bachhuber, Automattic Copyright: 2008-2015 Shared and distributed between Mohammad Jangda, Daniel Bachhuber, Weston Ruter @@ -24,7 +24,7 @@ */ -define( 'COAUTHORS_PLUS_VERSION', '3.1.2' ); +define( 'COAUTHORS_PLUS_VERSION', '3.2.1' ); require_once( dirname( __FILE__ ) . '/template-tags.php' ); require_once( dirname( __FILE__ ) . '/deprecated.php' ); @@ -611,12 +611,17 @@ function posts_join_filter( $join, $query ) { } // Check to see that JOIN hasn't already been added. Props michaelingp and nbaxley - $term_relationship_join = " INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)"; + $term_relationship_inner_join = " INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)"; + $term_relationship_left_join = " LEFT JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)"; + $term_taxonomy_join = " INNER JOIN {$wpdb->term_taxonomy} ON ( {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id )"; - if ( false === strpos( $join, trim( $term_relationship_join ) ) ) { - $join .= str_replace( 'INNER JOIN', 'LEFT JOIN', $term_relationship_join ); + // 4.6+ uses a LEFT JOIN for tax queries so we need to check for both + if ( false === strpos( $join, trim( $term_relationship_inner_join ) ) + && false === strpos( $join, trim( $term_relationship_left_join ) ) ) { + $join .= $term_relationship_left_join; } + if ( false === strpos( $join, trim( $term_taxonomy_join ) ) ) { $join .= str_replace( 'INNER JOIN', 'LEFT JOIN', $term_taxonomy_join ); } @@ -1595,6 +1600,7 @@ function cap_filter_comment_moderation_email_recipients( $recipients, $comment_i if ( isset( $post_id ) ) { $coauthors = get_coauthors( $post_id ); + $extra_recipients = array(); foreach ( $coauthors as $user ) { if ( ! empty( $user->user_email ) ) { $extra_recipients[] = $user->user_email; diff --git a/php/class-coauthors-guest-authors.php b/php/class-coauthors-guest-authors.php index 90537899..5c322ed0 100644 --- a/php/class-coauthors-guest-authors.php +++ b/php/class-coauthors-guest-authors.php @@ -675,11 +675,21 @@ function metabox_manage_guest_author_bio() { foreach ( $fields as $field ) { $pm_key = $this->get_post_meta_key( $field['key'] ); $value = get_post_meta( $post->ID, $pm_key, true ); - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; + printf( ' + + + + + + + + + ', + esc_attr( $pm_key ), + esc_html( $field['label'] ), + esc_attr( $pm_key ), + esc_textarea( $value ) + ); } echo ''; diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php index 8dcf1ee2..644eff93 100644 --- a/php/class-wp-cli.php +++ b/php/class-wp-cli.php @@ -28,6 +28,10 @@ public function create_guest_authors( $args, $assoc_args ) { $users = get_users(); $created = 0; $skipped = 0; + $count = count( $users ); + + WP_CLI::line( "Attempting to create guest author profiles for {$count} users" ); + $progress = \WP_CLI\Utils\make_progress_bar( 'Creating Profiles', $count ); foreach ( $users as $user ) { $result = $coauthors_plus->guest_authors->create_guest_author_from_user_id( $user->ID ); @@ -36,7 +40,10 @@ public function create_guest_authors( $args, $assoc_args ) { } else { $created++; } + + $progress->tick(); } + $progress->finish(); WP_CLI::line( 'All done! Here are your results:' ); WP_CLI::line( "- {$created} guest author profiles were created" ); @@ -76,7 +83,8 @@ public function create_terms_for_posts() { $count++; - $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy ); + $terms = get_the_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy ); + if ( is_wp_error( $terms ) ) { WP_CLI::error( $terms->get_error_message() ); } @@ -235,7 +243,7 @@ public function assign_user_to_coauthor( $args, $assoc_args ) { $posts = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author=%d AND post_type IN ('$post_types')", $user->ID ) ); $affected = 0; foreach ( $posts as $post_id ) { - if ( $coauthors = wp_get_post_terms( $post_id, $coauthors_plus->coauthor_taxonomy ) ) { + if ( $coauthors = get_the_terms( $post_id, $coauthors_plus->coauthor_taxonomy ) ) { WP_CLI::line( sprintf( __( 'Skipping - Post #%d already has co-authors assigned: %s', 'co-authors-plus' ), $post_id, implode( ', ', wp_list_pluck( $coauthors, 'slug' ) ) ) ); continue; } @@ -544,8 +552,8 @@ public function list_posts_without_terms( $args, $assoc_args ) { while ( $posts->post_count ) { foreach ( $posts->posts as $single_post ) { - - $terms = wp_get_post_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy ); + + $terms = get_the_terms( $single_post->ID, $coauthors_plus->coauthor_taxonomy ); if ( empty( $terms ) ) { $saved = array( $single_post->ID, @@ -697,8 +705,8 @@ public function remove_terms_from_revisions() { WP_CLI::line( 'Found ' . count( $ids ) . ' revisions to look through' ); $affected = 0; foreach ( $ids as $post_id ) { - - $terms = wp_get_post_terms( $post_id, 'author' ); + + $terms = get_the_terms( $post_id, $coauthors_plus->coauthor_taxonomy ); if ( ! $terms ) { continue; } diff --git a/readme.txt b/readme.txt index 608d7e83..8ca2a6b9 100644 --- a/readme.txt +++ b/readme.txt @@ -1,9 +1,9 @@ === Co-Authors Plus === Contributors: batmoo, danielbachhuber, automattic Tags: authors, users, multiple authors, coauthors, multi-author, publishing -Tested up to: 4.5 +Tested up to: 4.6 Requires at least: 4.1 -Stable tag: 3.1.1 +Stable tag: 3.2.1 Assign multiple bylines to posts, pages, and custom post types via a search-as-you-type input box @@ -57,11 +57,15 @@ Bug fixes and minor enhancements == Changelog == += 3.2.1 (May 16, 2016) = +* Hotfix for broken Guest Author bio metabox (props JS Morisset) + += 3.2 (May 12, 2016) = +Various minor bug and security fixes + = 3.1.2 (Aug. 31, 2015) = * Minor bug fixes and coding standards changes. * The author's display name is now filtered through the_author in coauthors_posts_links_single() - -= ??? (??? ?? ????) = * New Russian and Ukrainian translations, courtesy of [Jurko Chervony](http://skinik.name/). = 3.1.1 (Mar. 20, 2014) = diff --git a/tests/coauthorsplus-testcase.php b/tests/coauthorsplus-testcase.php index eb56cd81..99116c10 100644 --- a/tests/coauthorsplus-testcase.php +++ b/tests/coauthorsplus-testcase.php @@ -3,65 +3,11 @@ /** * Base unit test class for Co-Authors Plus */ - class CoAuthorsPlus_TestCase extends WP_UnitTestCase { - - protected $suppress = false; - public function setUp() { - global $wpdb; parent::setUp(); - $this->suppress = $wpdb->suppress_errors(); - - $_SERVER['REMOTE_ADDR'] = ''; - - $this->author1 = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'author1' ) ); - $this->editor1 = $this->factory->user->create( array( 'role' => 'editor', 'user_login' => 'editor2' ) ); - - $post = array( - 'post_author' => $this->author1, - 'post_status' => 'publish', - 'post_content' => rand_str(), - 'post_title' => rand_str(), - 'post_type' => 'post', - ); - - $this->author1_post1 = wp_insert_post( $post ); - - $post = array( - 'post_author' => $this->author1, - 'post_status' => 'publish', - 'post_content' => rand_str(), - 'post_title' => rand_str(), - 'post_type' => 'post', - ); - - $this->author1_post2 = wp_insert_post( $post ); - - $page = array( - 'post_author' => $this->author1, - 'post_status' => 'publish', - 'post_content' => rand_str(), - 'post_title' => rand_str(), - 'post_type' => 'page', - ); - - $this->author1_page1 = wp_insert_post( $page ); - - $page = array( - 'post_author' => $this->author1, - 'post_status' => 'publish', - 'post_content' => rand_str(), - 'post_title' => rand_str(), - 'post_type' => 'page', - ); - - $this->author1_page2 = wp_insert_post( $page ); - } - public function tearDown() { - global $wpdb; - parent::tearDown(); - $wpdb->suppress_errors( $this->suppress ); + global $coauthors_plus; + $this->_cap = $coauthors_plus; } } diff --git a/tests/test-author-queried-object.php b/tests/test-author-queried-object.php new file mode 100644 index 00000000..94e357f8 --- /dev/null +++ b/tests/test-author-queried-object.php @@ -0,0 +1,88 @@ +factory->user->create( array( 'user_login' => 'msauthor1' ) ); + $author2 = $this->factory->user->create( array( 'user_login' => 'msauthor2' ) ); + $blog2 = $this->factory->blog->create( array( 'user_id' => $author1 ) ); + + switch_to_blog( $blog2 ); + $wp_rewrite->init(); + + $blog2_post1 = $this->factory->post->create( array( + 'post_status' => 'publish', + 'post_content' => rand_str(), + 'post_title' => rand_str(), + 'post_author' => $author1, + ) ); + + /** + * Author 1 is an author on the blog + */ + $this->go_to( get_author_posts_url( $author1 ) ); + $this->assertQueryTrue( 'is_author', 'is_archive' ); + + /** + * Author 2 is not yet an author on the blog + */ + $this->go_to( get_author_posts_url( $author2 ) ); + $this->assertQueryTrue( 'is_404' ); + + // Add the user to the blog + add_user_to_blog( $blog2, $author2, 'author' ); + + /** + * Author 2 is now on the blog, but not yet published + */ + $this->go_to( get_author_posts_url( $author2 ) ); + $this->assertQueryTrue( 'is_author', 'is_archive' ); + + // Add the user as an author on the original post + $author2_obj = get_user_by( 'id', $author2 ); + $coauthors_plus->add_coauthors( $blog2_post1, array( $author2_obj->user_login ), true ); + + /** + * Author 2 is now on the blog, and published + */ + $this->go_to( get_author_posts_url( $author2 ) ); + $this->assertQueryTrue( 'is_author', 'is_archive' ); + + // Remove the user from the blog + remove_user_from_blog( $author2, $blog2 ); + + /** + * Author 2 was removed from the blog, but still a published author + */ + $this->go_to( get_author_posts_url( $author2 ) ); + $this->assertQueryTrue( 'is_author', 'is_archive' ); + + // Delete the user from the network + wpmu_delete_user( $author2 ); + + /** + * Author 2 is no more + */ + $this->go_to( get_author_posts_url( $author2 ) ); + $this->assertQueryTrue( 'is_404' ); + $this->assertEquals( false, get_user_by( 'id', $author2 ) ); + + restore_current_blog(); + + } +} diff --git a/tests/test-author-queries.php b/tests/test-author-queries.php index 2f6c1524..d6d58c7a 100644 --- a/tests/test-author-queries.php +++ b/tests/test-author-queries.php @@ -1,88 +1,129 @@ factory->user->create( array( 'user_login' => 'msauthor1' ) ); - $author2 = $this->factory->user->create( array( 'user_login' => 'msauthor2' ) ); - $blog2 = $this->factory->blog->create( array( 'user_id' => $author1 ) ); - - switch_to_blog( $blog2 ); - $wp_rewrite->init(); - - $blog2_post1 = $this->factory->post->create( array( + public function test__author_arg__user_is_post_author() { + $author_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author = get_userdata( $author_id ); + $post_id = $this->factory->post->create( array( + 'post_author' => $author_id, 'post_status' => 'publish', - 'post_content' => rand_str(), - 'post_title' => rand_str(), - 'post_author' => $author1, + 'post_type' => 'post', ) ); + $this->_cap->add_coauthors( $post_id, array( $author->user_login ) ); - /** - * Author 1 is an author on the blog - */ - $this->go_to( get_author_posts_url( $author1 ) ); - $this->assertQueryTrue( 'is_author', 'is_archive' ); - - /** - * Author 2 is not yet an author on the blog - */ - $this->go_to( get_author_posts_url( $author2 ) ); - $this->assertQueryTrue( 'is_404' ); - - // Add the user to the blog - add_user_to_blog( $blog2, $author2, 'author' ); - - /** - * Author 2 is now on the blog, but not yet published - */ - $this->go_to( get_author_posts_url( $author2 ) ); - $this->assertQueryTrue( 'is_author', 'is_archive' ); - - // Add the user as an author on the original post - $author2_obj = get_user_by( 'id', $author2 ); - $coauthors_plus->add_coauthors( $blog2_post1, array( $author2_obj->user_login ), true ); - - /** - * Author 2 is now on the blog, and published - */ - $this->go_to( get_author_posts_url( $author2 ) ); - $this->assertQueryTrue( 'is_author', 'is_archive' ); - - // Remove the user from the blog - remove_user_from_blog( $author2, $blog2 ); - - /** - * Author 2 was removed from the blog, but still a published author - */ - $this->go_to( get_author_posts_url( $author2 ) ); - $this->assertQueryTrue( 'is_author', 'is_archive' ); - - // Delete the user from the network - wpmu_delete_user( $author2 ); - - /** - * Author 2 is no more - */ - $this->go_to( get_author_posts_url( $author2 ) ); - $this->assertQueryTrue( 'is_404' ); - $this->assertEquals( false, get_user_by( 'id', $author2 ) ); - - restore_current_blog(); + $query = new WP_Query( array( + 'author' => $author_id, + ) ); + + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); + } + + public function test__author_name_arg__user_is_post_author() { + $author_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author = get_userdata( $author_id ); + $post_id = $this->factory->post->create( array( + 'post_author' => $author_id, + 'post_status' => 'publish', + 'post_type' => 'post', + ) ); + $this->_cap->add_coauthors( $post_id, array( $author->user_login ) ); + + $query = new WP_Query( array( + 'author_name' => $author->user_login, + ) ); + + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); + } + + public function test__author_name_arg__user_is_coauthor() { + $author1_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author1 = get_userdata( $author1_id ); + $author2_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'superman' ) ); + $author2 = get_userdata( $author2_id ); + + $post_id = $this->factory->post->create( array( + 'post_author' => $author1_id, + 'post_status' => 'publish', + 'post_type' => 'post', + ) ); + $this->_cap->add_coauthors( $post_id, array( $author1->user_login, $author2->user_login ) ); + + $query = new WP_Query( array( + 'author_name' => $author2->user_login, + ) ); + + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); + } + + public function test__author_arg__user_is_coauthor__author_arg() { + return; // TODO: re-enable; fails currently because WordPress generates query as `post_author IN (id)` which doesn't match our regex in the posts_where filter. + + $author1_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author1 = get_userdata( $author1_id ); + $author2_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'superman' ) ); + $author2 = get_userdata( $author2_id ); + + $post_id = $this->factory->post->create( array( + 'post_author' => $author1_id, + 'post_status' => 'publish', + 'post_type' => 'post', + ) ); + $this->_cap->add_coauthors( $post_id, array( $author1->user_login, $author2->user_login ) ); + + $query = new WP_Query( array( + 'author' => $author2_id, + ) ); + + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); + } + + public function test__author_name_arg_plus_tax_query__user_is_post_author() { + $author_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author = get_userdata( $author_id ); + $post_id = $this->factory->post->create( array( + 'post_author' => $author_id, + 'post_status' => 'publish', + 'post_type' => 'post', + ) ); + $this->_cap->add_coauthors( $post_id, array( $author->user_login ) ); + wp_set_post_terms( $post_id, 'test', 'post_tag' ); + + $query = new WP_Query( array( + 'author_name' => $author->user_login, + 'tag' => 'test', + ) ); + + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); + } + + public function tests__author_name_arg_plus_tax_query__is_coauthor() { + return; // TODO: re-enable; fails currently because our posts_join_filter doesn't add an exclusive JOIN on relationships + taxonomy to match the query mods we make. We'd need aliased JOINs on relationships + taxonomy on top of the JOIN that the tax query already adds. + + $author1_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'batman' ) ); + $author1 = get_userdata( $author1_id ); + $author2_id = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'superman' ) ); + $author2 = get_userdata( $author2_id ); + + $post_id = $this->factory->post->create( array( + 'post_author' => $author1_id, + 'post_status' => 'publish', + 'post_type' => 'post', + ) ); + $this->_cap->add_coauthors( $post_id, array( $author1->user_login, $author2->user_login ) ); + wp_set_post_terms( $post_id, 'test', 'post_tag' ); + + $query = new WP_Query( array( + 'author_name' => $author2->user_login, + 'tag' => 'test', + ) ); + $this->assertEquals( 1, count( $query->posts ) ); + $this->assertEquals( $post_id, $query->posts[ 0 ]->ID ); } } diff --git a/tests/test-manage-coauthors.php b/tests/test-manage-coauthors.php index 1f5b1945..fad2f9ca 100644 --- a/tests/test-manage-coauthors.php +++ b/tests/test-manage-coauthors.php @@ -2,6 +2,57 @@ class Test_Manage_CoAuthors extends CoAuthorsPlus_TestCase { + public function setUp() { + parent::setUp(); + + $this->author1 = $this->factory->user->create( array( 'role' => 'author', 'user_login' => 'author1' ) ); + $this->editor1 = $this->factory->user->create( array( 'role' => 'editor', 'user_login' => 'editor2' ) ); + + $post = array( + 'post_author' => $this->author1, + 'post_status' => 'publish', + 'post_content' => rand_str(), + 'post_title' => rand_str(), + 'post_type' => 'post', + ); + + $this->author1_post1 = wp_insert_post( $post ); + + $post = array( + 'post_author' => $this->author1, + 'post_status' => 'publish', + 'post_content' => rand_str(), + 'post_title' => rand_str(), + 'post_type' => 'post', + ); + + $this->author1_post2 = wp_insert_post( $post ); + + $page = array( + 'post_author' => $this->author1, + 'post_status' => 'publish', + 'post_content' => rand_str(), + 'post_title' => rand_str(), + 'post_type' => 'page', + ); + + $this->author1_page1 = wp_insert_post( $page ); + + $page = array( + 'post_author' => $this->author1, + 'post_status' => 'publish', + 'post_content' => rand_str(), + 'post_title' => rand_str(), + 'post_type' => 'page', + ); + + $this->author1_page2 = wp_insert_post( $page ); + } + + public function tearDown() { + parent::tearDown(); + } + /** * Test assigning a Co-Author to a post */ diff --git a/wpcom-helper.php b/wpcom-helper.php new file mode 100644 index 00000000..0e9c6cff --- /dev/null +++ b/wpcom-helper.php @@ -0,0 +1,227 @@ +is_enabled() && ! in_array( get_option( 'template' ), $wpcom_coauthors_plus_auto_apply_themes ) ) + add_action( 'admin_notices', function() { + + // Allow this to be short-circuted in mu-plugins + if ( ! apply_filters( 'wpcom_coauthors_show_enterprise_notice', true ) ) + return; + + echo '

' . __( "Co-Authors Plus isn't yet integrated with your theme. Please contact support to make it happen." ) . '

'; + } ); +} + +/** + * We want to let Elasticsearch know that it should search the author taxonomy's name as a search field + * See: https://elasticsearchp2.wordpress.com/2015/01/08/in-36757-z-vanguard-says-they/ + * + * @param $es_wp_query_args The ElasticSearch Query Parameters + * @param $query + * + * @return mixed + */ +function co_author_plus_es_support( $es_wp_query_args, $query ){ + if ( empty( $es_wp_query_args['query_fields'] ) ) { + $es_wp_query_args['query_fields'] = array( 'title', 'content', 'author', 'tag', 'category' ); + } + + // Search CAP author names + $es_wp_query_args['query_fields'][] = 'taxonomy.author.name'; + + // Filter based on CAP names + if ( !empty( $query->query['author'] ) ) { + $es_wp_query_args['terms']['author'] = 'cap-' . $query->query['author']; + } + + return $es_wp_query_args; +} +add_filter('wpcom_elasticsearch_wp_query_args', 'co_author_plus_es_support', 10, 2 ); + + +/** + * Change the post authors in the subscription email. + * + * Creates an array of authors, that will be used later. + * + * @param $author WP_User the original author + * @param $post_id + * + * @return array of coauthors + */ +add_filter( 'wpcom_subscriber_email_author', function( $author, $post_id ) { + + $authors = get_coauthors( $post_id ); + return $authors; + +}, 10, 2 ); + +/** + * Change the author avatar url. If there are multiple authors, link the avatar to the post. + * + * @param $author_url + * @param $post_id + * @param $authors + * + * @return string with new author url. + */ +add_filter( 'wpcom_subscriber_email_author_url', function( $author_url, $post_id, $authors ) { + if( is_array( $authors ) ) { + if ( count( $authors ) > 1 ) { + return get_permalink( $post_id ); + } + + return get_author_posts_url( $authors[0]->ID, $authors[0]->user_nicename ); + } + + return get_author_posts_url( $authors->ID, $authors->user_nicename ); +}, 10, 3); + +/** + * Change the avatar to be the avatar of the first author + * + * @param $author_avatar + * @param $post_id + * @param $authors + * + * @return string with the html for the avatar + */ +add_filter( 'wpcom_subscriber_email_author_avatar', function( $author_avatar, $post_id, $authors ) { + if( is_array( $authors ) ) + return coauthors_get_avatar( $authors[0], 50 ); + + return coauthors_get_avatar( $authors, 50 ); +}, 10, 3); + +/** + * Changes the author byline in the subscription email to include all the authors of the post + * + * @param $author_byline + * @param $post_id + * @param $authors + * + * @return string with the byline html + */ +add_filter( 'wpcom_subscriber_email_author_byline_html', function( $author_byline, $post_id, $authors ) { + // Check if $authors is a valid array + if( ! is_array( $authors ) ) { + $authors = array( $authors ); + } + + $byline = 'by '; + foreach( $authors as $author ) { + $byline .= '' . esc_html( $author->display_name ) . ''; + if ( $author != end( $authors ) ) { + $byline .= ', '; + } + } + + return $byline; +}, 10, 3); + +/** + * Change the meta information to include all the authors + * + * @param $meta + * @param $post_id + * @param $authors + * + * @return array with new meta information + */ +add_filter( 'wpcom_subscriber_email_meta', function( $meta, $post_id, $authors ) { + // Check if $authors is a valid array + if( ! is_array( $authors ) ) { + $authors = array( $authors ); + } + + $author_meta = ''; + foreach( $authors as $author ) { + $author_meta .= '' . esc_html( $author->display_name ) . ''; + + if ( $author != end( $authors ) ) { + $author_meta .= ', '; + } + } + + // Only the first entry of meta includes the author listing + $meta[0] = $author_meta; + + return $meta; +}, 10, 3); + +/** + * Change the author information in the text-only subscription email. + * + * @param $author + * @param $post_id + * + * @returns string with the authors + */ +add_filter( 'wpcom_subscriber_text_email_author', function( $author, $post_id ) { + // Check if $authors is a valid array + $authors = get_coauthors( $post_id ); + + $author_text = ''; + foreach( $authors as $author ) { + $author_text .= esc_html( $author->display_name ); + if ( $author != end( $authors ) ) { + $author_text .= ', '; + } + } + + return $author_text; +}, 10, 2); + +/** + * Replace author_url in oembed endpoint response + * Since the oembed specification does not allow multiple urls, we'll go with the first coauthor + * + * The function is meant as a filter for `get_author_posts_url` function, which it is using as well + * Recursion is prevented by a simple check agains original attributes passed to the funciton. That + * also prevents execution in case the only coauthor is real author. + * + * This function is hooked only to oembed endpoint and it should stay that way + */ + +function wpcom_vip_cap_replace_author_link( $link, $author_id, $author_nicename ) { + + //get coauthors and iterate to the first one + //in case there are no coauthors, the Iterator returns current author + $i = new CoAuthorsIterator(); + $i->iterate(); + + //check if the current $author_id and $author_nicename is not the same as the first coauthor + if ( $i->current_author->ID !== $author_id || $i->current_author->user_nicename !== $author_nicename ) { + + //alter the author_url + $link = get_author_posts_url( $i->current_author->ID, $i->current_author->user_nicename ); + + } + + return $link; +} +//Hook the above callback only on oembed endpoint reply +if ( true === defined( 'WPCOM_VIP_IS_OEMBED' ) && true === constant( 'WPCOM_VIP_IS_OEMBED' ) && true === apply_filters( 'wpcom_vip_coauthors_replace_oembed', false, 'author_url' ) ) { + add_filter( 'author_link', 'wpcom_vip_cap_replace_author_link', 99, 3 ); +}