10up / distributor

Share content between your websites.
https://distributorplugin.com
GNU General Public License v2.0
629 stars 154 forks source link

Post author uses API user instead of author. #751

Open siniger opened 3 years ago

siniger commented 3 years ago

Describe the bug We have selected the option in Setting: For linked distributed posts, replace the author name and link with the original site name and link.

but when a new post is distributed the Author is the API user and not the post author.

Steps to Reproduce 1.create new post

  1. distributed it

Expected behavior created post to be distributed with the original Author

Screenshots

Environment information

dinhtungdu commented 3 years ago

@siniger, can you share with us the Site Health Debug Info? I can't reproduce your issue on my end which uses WP 5.7.1 (both single site and multisite).

Also, what does the API user mean?

but when a new post is distributed the Author is the API user and not the post author.

Note that when you check the option, the post author and link are replaced by the Site name and site URL, not the post author.

jmslbam commented 3 years ago

By accident I was researching an issue with the current logged in user and saw this ticket. Does @siniger refer to this line of code? https://github.com/10up/distributor/blob/develop/includes/classes/ExternalConnections/WordPressExternalConnection.php#L907

While InternalConnections can re-use the author_id of the original author because it's a Network site?

ldollard commented 3 years ago

Hi I have the same issue and by API he means the user that the application password is being used from on the remote website. So that the remote website user-name that has the application password gets added as the author to posts.

Has anyone found a solution to this issue yet?

Thanks

Luke

dinhtungdu commented 3 years ago

@siniger @jmslbam @ldollard Can you please help me test the #767 to see if it fixes your issue?

jeffpaul commented 3 years ago

@siniger can you please confirm from your original description if you have the Override Author Byline setting checked?:

checked

...or unchecked?:

unchecked

Thanks! Jeff.

ldollard commented 3 years ago

@dinhtungdu not sure what happened, but i replied to this that it wasn't working correctly after updating the includes file, it seems to do something, but is not changing the user in the backend of metadata, but weirdly a plugin I use called simple author partially picks up the change as seen in these images.

https://we.tl/t-7GsPQeM2ig

ldollard commented 3 years ago

I also have this checked:

Override Author Byline checked
dinhtungdu commented 3 years ago

@ldollard The PR #767 doesn't fully resolve this issue and our team is reviewing this issue again. So there won't be updated to #767 until further notice.

In the meantime, you can follow this workaround to have the author display correctly:

anthonythorne commented 3 years ago

I am interested in this feature as well. The client I work for has asked me to create a solution, for which I've added this file to the mu-plugins.

/**
 * Extends features for the distributor plugin.
 */
class DistributorExt {

    /**
     * Initialise any hooks.
     */
    public function setup() {
        add_action( 'dt_pull_post', [ $this, 'pull_post' ], 99, 3 );
    }

    /**
     * Update the post author.
     *
     * Action triggered when a post is pulled via distributor.
     * Fires after a post is pulled via Distributor and after `restore_current_blog()`.
     *
     * @param int                     $new_post_id The new post ID that was pulled.
     * @param \Distributor\Connection $connection  The Distributor connection pulling the post.
     * @param array                   $post_array  The original post data retrieved via the connection.
     *
     */
    function pull_post( $new_post_id, $connection, $post_array ) {

        $post = get_post( $new_post_id );

        // Bail early.
        if ( ! $post || ! isset( $post_array['post_author'] ) ) {
            return;
        }

        // Get the original author id from the blog.
        $author_id = (int) sanitize_text_field( $post_array['post_author'] );

        // Check if the user is on this blog, if not add them.
        $author_id = $this->check_and_add_blog_author( $author_id );

        // Author not given access to this blog.
        if ( ! $author_id ) {
            return;
        }

        $this->update_post_author( $post, $author_id );

    }

    /**
     * Check the user is already on this blog, if not and they exist on another, add them.
     *
     * @param int $author_id The author ID.
     *
     * @return int
     */
    protected function check_and_add_blog_author( $author_id ) {

        // Bail early.
        if ( ! is_multisite() ) {
            return 0;
        }

        $user = get_user_by( 'id', $author_id );

        // Bail early.
        if ( ! $user ) {
            return 0;
        }

        $current_blog_id = get_current_blog_id();

        $blogs_of_user = get_blogs_of_user( $user->ID );

        // The user doesnt belong on any other blogs, but exist within the User base.
        // Add them to this blog, with the "editor" role.
        if ( ! $blogs_of_user ) {
            add_user_to_blog( $current_blog_id, $user->ID, 'editor' );
            return $user->ID;
        }

        $user_blog_roles = [];

        // Check if the user exists on the blog and bail early.
        foreach ( $blogs_of_user as $blog_of_user ) {
            if ( $blog_of_user->userblog_id === $current_blog_id ) {
                // Bail early, the user exists on this blog.
                return $user->ID;

            } else {

                // Switch to the users blog, and get their role ready for latter.
                switch_to_blog( $blog_of_user->userblog_id );

                $blog_user = get_user_by( 'id', $user->ID );

                if ( $blog_user->roles ) {
                    $user_blog_roles[] = $blog_user->roles;
                }

                restore_current_blog();
            }
        }

        $user_blog_roles = $this->combine_roles( $user_blog_roles );

        // Bail early.
        if ( ! $user_blog_roles ) {
            return $user->ID;
        }

        $allowed_roles = [
            'editor',
            'us_syndicated_author',
        ];

        foreach ( $allowed_roles as $role ) {

            // Add the user and bail early if the role matches an allowed role.
            if ( in_array( $role, $user_blog_roles, true ) ) {
                add_user_to_blog( $current_blog_id, $user->ID, $role );
                break;
            }
        }

        return $user->ID;
    }

    /**
     * Process a the post without using wp_update_post(), this prevents changes to the post dates in teh database.
     *
     * @param WP_Post|int $post   The Post object or ID of the post to process.
     * @param int        $author_id The author id for the post.
     */
    protected function update_post_author( $post, $author_id ) {

        global $wpdb;

        if ( (int) $post->post_author !== $author_id ) {

            $wpdb->update( // phpcs:ignore
                $wpdb->posts,
                [ 'post_author' => $author_id ],
                [ 'ID' => $post->ID ],
                [ '%d' ],
                [ '%d' ]
            );
        }
    }

    /**
     * Combine roles from all user blogs.
     *
     * @param $array
     *
     * @return array|false
     */
    protected function combine_roles( $array ) {

        foreach ( $array as $index => $roles ) {
            foreach ( $roles as $roles_index => $role ) {
                $array[ $index ][ $role ] = $role;
                unset( $array[ $index ][ $roles_index ] );
            }
        }

        $array = call_user_func_array( 'array_merge', $array ? : [ [] ] );

        return is_array( $array ) ? $array : [];
    }

}

// Load the extension.
add_action( 'plugins_loaded', function () {

    // Bail early if the plugin is not active.
    if ( ! is_plugin_active( 'distributor-stable/distributor.php' ) ) {
        return;
    }

    ( new DistributorExt() )->setup();
}, 11 );

This of course is tailored to my usage, and I am yet to test updating authors on the linked post, on the original blog.