Plugin Directory

Changeset 2697320


Ignore:
Timestamp:
03/21/2022 08:56:27 PM (4 years ago)
Author:
audienceplayer
Message:
  • released version 3.3.3
Location:
audienceplayer
Files:
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • audienceplayer/tags/3.3.3/audienceplayer.php

    r2694680 r2697320  
    99Description: AudiencePlayer integration
    1010Author: AudiencePlayer
    11 Version: 3.3.2
     11Version: 3.3.3
    1212Author URI: https://www.audienceplayer.com
    1313Text Domain: audienceplayer
  • audienceplayer/tags/3.3.3/languages/audienceplayer-wordpress-plugin.pot

    r2694680 r2697320  
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: 3.3.2\n"
     5"Project-Id-Version: 3.3.3\n"
    66"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/audienceplayer\n"
    77"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  • audienceplayer/tags/3.3.3/readme.txt

    r2694680 r2697320  
    11=== AudiencePlayer ===
    22Contributors: audienceplayer
    3 Stable tag: 3.3.2
     3Stable tag: 3.3.3
    44Tested up to: 5.9
    55Requires at least: 5.5
  • audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php

    r2694680 r2697320  
    3939
    4040        // Main plugin version number here and in main plugin file header are automatically overwritten in gulp-build script
    41         PLUGIN_VERSION = '3.3.2',
     41        PLUGIN_VERSION = '3.3.3',
    4242
    4343        // DB migration version number is maintained here
  • audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php

    r2694680 r2697320  
    6262    private $isNewUserAuthenticationRequest = false;
    6363    private $isNewUserAuthenticationSyncRequest = false;
     64    private $isChangeAttemptedOnPassword = false;
     65    private $isChangeAttemptedOnEmail = false;
    6466    private $validatedOrders = [];
    6567
     
    373375
    374376                        // Retrieve id from WP_User (if there was an error, $userResult is instance of WP_Error
    375                         $wordpressUserId = ($userResult->ID ?? null);
     377                        $wordpressUserId = $self->assembleCallbackWordpressUserId($userResult);
    376378                        // Fetch user password
    377                         $userPassword = $userPassword ?: ($_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '');
     379                        $userPassword = $userPassword ?: $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password']);
    378380                        // login-property is an e-mail address and its related user does not yet exist locally
    379                         $userLogin = $userLogin ?: ($_REQUEST['log'] ?? $_REQUEST['login'] ?? $_REQUEST['email'] ?? '');
     381                        $userLogin = $userLogin ?: $self->assembleSubmittedRequestProperty(['log', 'login', 'email']);
    380382
    381383                        if (
     
    441443                    $self->isNewUserAuthenticationRequest &&
    442444                    $self->isNewUserAuthenticationSyncRequest &&
    443                     $user && is_object($user) && is_a($user, 'WP_User')
     445                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user))
    444446                ) {
    445447                    $userArgs = [];
    446                     if ($password = $_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '') {
     448                    if ($password = $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password'])) {
    447449                        $userArgs['password'] = $password;
     450                        $self->isChangeAttemptedOnPassword = true;
    448451                    }
    449452                    // user was just successfully authenticated and logged in Wordpress and must now be forcefully synched with AudiencePlayer
    450                     $self->syncAudiencePlayerUserAuthentication($user->ID, $userArgs, true, true, Constants::USER_METADATA_SYNC_DIRECTION_WP2A);
     453                    $self->syncAudiencePlayerUserAuthentication($wordpressUserId, $userArgs, true, true, Constants::USER_METADATA_SYNC_DIRECTION_WP2A);
    451454                }
    452455
     
    454457
    455458            }, 10, 3);
    456 
    457             // "login_form_lostpassword"/"login_form_retrievepassword": Runs immediately before given action "lostpassword" or "retrievepassword" is processed.
    458             // Ensures local user is first created, if it exists remotely.
    459             $lostPasswordCallback = function () use ($self) {
    460 
    461                 if (
    462                     isset($_REQUEST['wp-submit']) &&
    463                     ($userLogin = $_REQUEST['user_login'] ?? $_REQUEST['log'] ?? $_REQUEST['login'] ?? $_REQUEST['email'] ?? '') &&
    464                     filter_var($userLogin, FILTER_VALIDATE_EMAIL) &&
    465                     (false === (username_exists($userLogin) || email_exists($userLogin))) &&
    466                     ($remoteUser = $self->fetchRemoteAudiencePlayerUser(0, $userLogin))
    467                 ) {
    468 
    469                     $userArgs = [
    470                         'user_login' => $userLogin,
    471                         'user_pass' => \wp_generate_password(),
    472                         'user_nicename' => $remoteUser->name,
    473                         'display_name' => $remoteUser->name,
    474                     ];
    475 
    476                     return $self->syncAudiencePlayerUserToWordpress($remoteUser->id, $userLogin, $userArgs, false);
    477                 }
    478             };
    479             \add_action('login_form_lostpassword', $lostPasswordCallback);
    480             \add_action('login_form_retrievepassword', $lostPasswordCallback);
    481 
    482             // "after_password_reset": Runs immediately upon completion of function \reset_password.
    483             // Update the password for given user
    484             \add_action('after_password_reset', function ($user = null, $newPassword = '') use ($self) {
    485                 if (
    486                     $user &&
    487                     ($user->ID ?? null) &&
    488                     ($newPassword = trim($newPassword) ?: trim($_REQUEST['pass1'] ?? $_REQUEST['pass2'] ?? ''))
    489                 ) {
    490                     $self->syncWordpressUserToAudiencePlayer($user->ID, ['password' => $newPassword]);
    491                 }
    492 
    493                 return true;
    494             });
    495459        }
    496460    }
     
    522486                    $userArgs['name'] = $name;
    523487                }
    524                 if ($password = $self->fetchDetectedNewUserRegistrationPassword(trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {
     488                if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) {
    525489                    $userArgs['password'] = $password;
    526490                }
    527                 if ($newUserEmail = $newUserEmail ?: ($_REQUEST['user_email'] ?? null)) {
     491                if ($newUserEmail = $newUserEmail ?: $self->assembleSubmittedRequestProperty(['user_email'])) {
    528492                    $self->syncWordpressUserRegisterAction($newUserEmail, $userArgs, $wpError);
    529493                }
     
    542506                    $self->isNewUserRegistrationRequest = true;
    543507
    544                     if (isset($_REQUEST['pass2'])) {
    545                         $self->newUserRegistrationPassword = $_REQUEST['pass2'];
     508                    if ($password = $self->assembleSubmittedRequestProperty(['pass2'])) {
     509                        $self->newUserRegistrationPassword = $password;
    546510                    }
    547511                }
     
    562526                if ($self->isNewUserRegistrationRequest) {
    563527
    564                     if (trim($_REQUEST['email'] ?? '')) {
    565                         $userArgs['email'] = trim(\sanitize_email($_REQUEST['email'] ?? ''));
    566                     }
    567                     if ($password = $self->fetchDetectedNewUserRegistrationPassword(trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {
     528                    if ($email = $self->assembleSubmittedRequestProperty(['email'])) {
     529                        $userArgs['email'] = trim(\sanitize_email($email));
     530                    }
     531                    if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) {
    568532                        $userArgs['password'] = $password;
    569533                    }
     
    595559                    // Parse properties eligible for AudiencePlayer sync
    596560                    $userArgs = [];
    597                     if (trim($_REQUEST['email'] ?? '')) {
    598                         $userArgs['email'] = trim($_REQUEST['email'] ?? '');
    599                     }
    600                     if (trim($_REQUEST['pass2'] ?? '')) {
    601                         $userArgs['password'] = trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? '');
     561                    if ($email = $self->assembleSubmittedRequestProperty(['email'])) {
     562                        $userArgs['email'] = \sanitize_email($email);
     563                        $self->isChangeAttemptedOnEmail = true;
     564                    }
     565                    if ($password = $self->assembleSubmittedRequestProperty(['pass2', 'user_pass'])) {
     566                        $userArgs['password'] = $password;
     567                        $self->isChangeAttemptedOnPassword = true;
    602568                    }
    603569                    if ($name = $self->helper->parseUserFullNameFromUserData($_REQUEST)) {
     
    611577                        $wpError
    612578                    );
     579
    613580                    if ($result) {
    614581                        // change-validation e-mail is sent early on in "admin-filters.php": \add_action('personal_options_update', 'send_confirmation_on_profile_email');
     
    625592            // if user has entered confirm-change-email-flow by clicking on link e-mail "email_change_email"
    626593            // "get_user_metadata": Runs very shortly after user has clicked on the " profile.php?newuseremail" link an
    627             // in e-mail to confirm change of e-mail address, and has antered the "newuseremail"-flow in user-edit.php
     594            // in e-mail to confirm change of e-mail address, and has entered the "newuseremail"-flow in user-edit.php
    628595            // Before the applicable metakey (containing the new e-mail address) is parsed, we inject an AudiencePlayer
    629596            // check.
     
    634601                // recreated evaluation logic contained in user-edit.php to obtain the new e-mail address
    635602                if (
     603                    !$self->isChangeAttemptedOnEmail &&
    636604                    defined('IS_PROFILE_PAGE') &&
    637605                    IS_PROFILE_PAGE &&
     
    646614                    if ($new_email && ($new_email['newemail'] ?? null) && hash_equals($new_email['hash'], $_REQUEST['newuseremail'])) {
    647615
     616                        $self->isChangeAttemptedOnEmail = true;
     617
    648618                        $userArgs = ['email' => trim($new_email['newemail'] ?? '')];
    649619
     
    657627                        if (false === $result) {
    658628                            // @TODO: consider creating the missing Wordpress user
    659                             //$this->createWordpressUser($currentUserData);
     629                            //$self->createWordpressUser($currentUserData);
    660630                            \delete_user_meta($wordpressUserId, '_new_email');
    661                             \wp_die($this->fetchTranslations('dialogue_email_address_exists_conflict'));
     631                            \wp_die($self->fetchTranslations('dialogue_email_address_exists_conflict'));
    662632                            return false;
    663633                        }
     
    668638
    669639            }, 10, 5);
     640
     641            // "login_form_lostpassword"/"login_form_retrievepassword": Runs immediately before given action "lostpassword" or "retrievepassword" is processed.
     642            // Ensures local user is first created, if it exists remotely.
     643            $lostPasswordCallback = function ($args = null) use ($self) {
     644
     645                if (
     646                    isset($_REQUEST['wp-submit']) &&
     647                    ($userLogin = $self->assembleSubmittedRequestProperty(['user_login', 'log', 'login', 'email'])) &&
     648                    filter_var($userLogin, FILTER_VALIDATE_EMAIL) &&
     649                    (false === (username_exists($userLogin) || email_exists($userLogin))) &&
     650                    ($remoteUser = $self->fetchRemoteAudiencePlayerUser(0, $userLogin))
     651                ) {
     652
     653                    $userArgs = [
     654                        'user_login' => $userLogin,
     655                        'user_pass' => \wp_generate_password(),
     656                        'user_nicename' => $remoteUser->name,
     657                        'display_name' => $remoteUser->name,
     658                    ];
     659
     660                    $self->isChangeAttemptedOnPassword = true;
     661
     662                    return $self->syncAudiencePlayerUserToWordpress($remoteUser->id, $userLogin, $userArgs, false);
     663                }
     664
     665                return $args;
     666            };
     667            \add_action('login_form_lostpassword', $lostPasswordCallback);
     668            \add_action('login_form_retrievepassword', $lostPasswordCallback);
     669
     670            // "after_password_reset": Runs immediately upon completion of function \reset_password (e.g. when wp_set_password() is used).
     671            // Update the password for given user
     672            \add_action('after_password_reset', function ($user = null, $newPassword = '') use ($self) {
     673                if (
     674                    !$self->isChangeAttemptedOnPassword &&
     675                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) &&
     676                    ($newPassword = trim($newPassword) ?: $self->assembleSubmittedRequestProperty(['pass1', 'pass2']))
     677                ) {
     678                    $self->isChangeAttemptedOnPassword = true;
     679                    $self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword]);
     680                }
     681
     682                return true;
     683            }, 10, 2);
     684
     685            \add_action('password_reset', function ($user = null, $newPassword = null) use ($self) {
     686                if (
     687                    !$self->isChangeAttemptedOnPassword &&
     688                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) &&
     689                    ($newPassword = trim($newPassword) ?: $self->assembleSubmittedRequestProperty(['pass1', 'pass2', 'password_1', 'password_2']))
     690                ) {
     691                    $self->isChangeAttemptedOnPassword = true;
     692                    $self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword]);
     693                }
     694
     695                return true;
     696            });
     697
     698            // "send_password_change_email": Fires near the end of \wp_update_user(), which may be used by other plugins to update user email/password
     699            \add_action('send_password_change_email', function ($send, $user = null, $userdata = null) use ($self) {
     700
     701                $wordpressUserId = $self->assembleCallbackWordpressUserId($user);
     702
     703                if (
     704                    !$self->isChangeAttemptedOnPassword &&
     705                    $wordpressUserId &&
     706                    // password_1, password_2 are used by plugins such as WooCommerce
     707                    ($newPassword = $self->assembleSubmittedRequestProperty(['pass1', 'pass2', 'password_1', 'password_2']))
     708                ) {
     709                    $self->isChangeAttemptedOnPassword = true;
     710
     711                    // If sync fails, exit current flow to avoid the change being executed in Wordpress (a falsy return on this action won't halt execution)
     712                    if (!$self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword])) {
     713                        \wp_die($self->fetchTranslations('dialogue_error_occurred'));
     714                    }
     715                }
     716
     717            }, 10, 2);
     718
     719            // "send_email_change_email": Fires near the end of \wp_update_user(), which may be used by other plugins to update user email/password
     720            \add_action('send_email_change_email', function ($send, $user = null, $userdata = null) use ($self) {
     721
     722                $wordpressUserId = $self->assembleCallbackWordpressUserId($user);
     723
     724                if (
     725                    !$self->isChangeAttemptedOnEmail &&
     726                    $wordpressUserId &&
     727                    // account_email is used by plugins such as WooCommerce
     728                    ($newEmail = $self->assembleSubmittedRequestProperty(['email', 'account_email']))
     729                ) {
     730                    $self->isChangeAttemptedOnEmail = true;
     731
     732                    // If sync fails, exit current flow to avoid the change being executed in Wordpress (a falsy return on this action won't halt execution)
     733                    if (!$self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['email' => $newEmail])) {
     734                        \wp_die($self->fetchTranslations('dialogue_email_address_exists_conflict'));
     735                    }
     736                }
     737
     738            }, 10, 2);
    670739        }
    671740    }
     
    865934    }
    866935
     936    protected function assembleCallbackWordpressUserId($user)
     937    {
     938        if ($user && is_object($user) && ($user->ID ?? null)) {
     939
     940            return $user->ID;
     941
     942        } elseif (is_array($user) && ($user['ID'] ?? null)) {
     943
     944            return $user['ID'];
     945        }
     946
     947        return null;
     948    }
     949
     950    protected function assembleSubmittedRequestProperty(array $restrictKeys = [])
     951    {
     952        $ret = null;
     953
     954        foreach ($restrictKeys as $key) {
     955            if (is_null($ret)) {
     956                $ret = $_REQUEST[$key] ?? null;
     957            } else {
     958                break;
     959            }
     960        }
     961
     962        return trim(strval($ret));
     963    }
     964
    867965    /**
    868966     * @return bool
  • audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php

    r2596153 r2697320  
    544544            ];
    545545
    546             if ($user->user_email !== $email && !\wp_update_user(['ID' => $user->ID, 'email' => $email])) {
     546            // Update user e-mail address if necessary
     547            if (
     548                $user->user_email !== $email &&
     549                ($this->isChangeAttemptedOnEmail = true) &&
     550                !($retUpdateUser = \wp_update_user(['ID' => $user->ID, 'user_email' => $email]))
     551            ) {
    547552
    548553                // Log exception
     
    551556                    'resource.user-sync.sync-audienceplayer-user-to-wordpress.db-insert-new-user-error',
    552557                    'Error updating Wordpress user e-mail "' . $user->user_email . '" => "' . $email . '"',
    553                     $logArgs
     558                    array_merge($logArgs, ['wp_update_user_result' => $retUpdateUser])
    554559                );
    555560
     
    557562            }
    558563
     564            // Delete existing user
    559565            if ($isDeleteUser) {
    560 
    561                 // delete existing user
    562566
    563567                $logId = $user->ID;
     
    583587            } else {
    584588
     589                if ($args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass'])) {
     590                    $this->isChangeAttemptedOnPassword = true;
     591                }
     592
    585593                $ret = $this->syncAudiencePlayerUserAuthentication($user->ID, $userArgs, false, true, Constants::USER_METADATA_SYNC_DIRECTION_A2WP);
    586                 $args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass']);
    587594
    588595                // metadata already handled in syncAudiencePlayerUserAuthentication, but password may also have been changed
    589                 if ($ret && $args) {
    590                     $ret = $this->updateWordpressUser($user->ID, $args);
     596                if ($ret) {
     597                    if ($args) {
     598                        ($this->isChangeAttemptedOnPassword = true) &&
     599
     600                        $ret = $this->updateWordpressUser($user->ID, $args);
     601                    } else {
     602                        $this->writeLog(
     603                            Constants::LOG_LEVEL_SYSTEM_ERROR,
     604                            'resource.user-sync.sync-audienceplayer-user-to-wordpress.update-wordpress-user',
     605                            'Error updating wordpress user after successful audienceplayer user authentication synchronisation',
     606                            $logArgs
     607                        );
     608                    }
     609                } else {
     610                    $this->writeLog(
     611                        Constants::LOG_LEVEL_SYSTEM_ERROR,
     612                        'resource.user-sync.sync-audienceplayer-user-to-wordpress.sync-user-authentication',
     613                        'Error synchronising audienceplayer user authentication',
     614                        $logArgs
     615                    );
    591616                }
    592617            }
  • audienceplayer/tags/3.3.3/static/html/admin_help_release_notes.html

    r2694680 r2697320  
    11<h3>Release notes</h3>
     2
     3<div class="audienceplayer-release-note">
     4    <h5>v3.3.3</h5>
     5    <p class="date">2022-03-21</p>
     6    <p class="content">
     7        Expanded user synchronisation of e-mail/password to cover calls to cover wp_set_password() and wp_update_user(), in order to improve compatibility with third party plugins (such as WooCommerce).
     8    </p>
     9</div>
    210
    311<div class="audienceplayer-release-note">
  • audienceplayer/trunk/audienceplayer.php

    r2694680 r2697320  
    99Description: AudiencePlayer integration
    1010Author: AudiencePlayer
    11 Version: 3.3.2
     11Version: 3.3.3
    1212Author URI: https://www.audienceplayer.com
    1313Text Domain: audienceplayer
  • audienceplayer/trunk/languages/audienceplayer-wordpress-plugin.pot

    r2694680 r2697320  
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: 3.3.2\n"
     5"Project-Id-Version: 3.3.3\n"
    66"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/audienceplayer\n"
    77"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  • audienceplayer/trunk/readme.txt

    r2694680 r2697320  
    11=== AudiencePlayer ===
    22Contributors: audienceplayer
    3 Stable tag: 3.3.2
     3Stable tag: 3.3.3
    44Tested up to: 5.9
    55Requires at least: 5.5
  • audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php

    r2694680 r2697320  
    3939
    4040        // Main plugin version number here and in main plugin file header are automatically overwritten in gulp-build script
    41         PLUGIN_VERSION = '3.3.2',
     41        PLUGIN_VERSION = '3.3.3',
    4242
    4343        // DB migration version number is maintained here
  • audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php

    r2694680 r2697320  
    6262    private $isNewUserAuthenticationRequest = false;
    6363    private $isNewUserAuthenticationSyncRequest = false;
     64    private $isChangeAttemptedOnPassword = false;
     65    private $isChangeAttemptedOnEmail = false;
    6466    private $validatedOrders = [];
    6567
     
    373375
    374376                        // Retrieve id from WP_User (if there was an error, $userResult is instance of WP_Error
    375                         $wordpressUserId = ($userResult->ID ?? null);
     377                        $wordpressUserId = $self->assembleCallbackWordpressUserId($userResult);
    376378                        // Fetch user password
    377                         $userPassword = $userPassword ?: ($_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '');
     379                        $userPassword = $userPassword ?: $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password']);
    378380                        // login-property is an e-mail address and its related user does not yet exist locally
    379                         $userLogin = $userLogin ?: ($_REQUEST['log'] ?? $_REQUEST['login'] ?? $_REQUEST['email'] ?? '');
     381                        $userLogin = $userLogin ?: $self->assembleSubmittedRequestProperty(['log', 'login', 'email']);
    380382
    381383                        if (
     
    441443                    $self->isNewUserAuthenticationRequest &&
    442444                    $self->isNewUserAuthenticationSyncRequest &&
    443                     $user && is_object($user) && is_a($user, 'WP_User')
     445                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user))
    444446                ) {
    445447                    $userArgs = [];
    446                     if ($password = $_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '') {
     448                    if ($password = $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password'])) {
    447449                        $userArgs['password'] = $password;
     450                        $self->isChangeAttemptedOnPassword = true;
    448451                    }
    449452                    // user was just successfully authenticated and logged in Wordpress and must now be forcefully synched with AudiencePlayer
    450                     $self->syncAudiencePlayerUserAuthentication($user->ID, $userArgs, true, true, Constants::USER_METADATA_SYNC_DIRECTION_WP2A);
     453                    $self->syncAudiencePlayerUserAuthentication($wordpressUserId, $userArgs, true, true, Constants::USER_METADATA_SYNC_DIRECTION_WP2A);
    451454                }
    452455
     
    454457
    455458            }, 10, 3);
    456 
    457             // "login_form_lostpassword"/"login_form_retrievepassword": Runs immediately before given action "lostpassword" or "retrievepassword" is processed.
    458             // Ensures local user is first created, if it exists remotely.
    459             $lostPasswordCallback = function () use ($self) {
    460 
    461                 if (
    462                     isset($_REQUEST['wp-submit']) &&
    463                     ($userLogin = $_REQUEST['user_login'] ?? $_REQUEST['log'] ?? $_REQUEST['login'] ?? $_REQUEST['email'] ?? '') &&
    464                     filter_var($userLogin, FILTER_VALIDATE_EMAIL) &&
    465                     (false === (username_exists($userLogin) || email_exists($userLogin))) &&
    466                     ($remoteUser = $self->fetchRemoteAudiencePlayerUser(0, $userLogin))
    467                 ) {
    468 
    469                     $userArgs = [
    470                         'user_login' => $userLogin,
    471                         'user_pass' => \wp_generate_password(),
    472                         'user_nicename' => $remoteUser->name,
    473                         'display_name' => $remoteUser->name,
    474                     ];
    475 
    476                     return $self->syncAudiencePlayerUserToWordpress($remoteUser->id, $userLogin, $userArgs, false);
    477                 }
    478             };
    479             \add_action('login_form_lostpassword', $lostPasswordCallback);
    480             \add_action('login_form_retrievepassword', $lostPasswordCallback);
    481 
    482             // "after_password_reset": Runs immediately upon completion of function \reset_password.
    483             // Update the password for given user
    484             \add_action('after_password_reset', function ($user = null, $newPassword = '') use ($self) {
    485                 if (
    486                     $user &&
    487                     ($user->ID ?? null) &&
    488                     ($newPassword = trim($newPassword) ?: trim($_REQUEST['pass1'] ?? $_REQUEST['pass2'] ?? ''))
    489                 ) {
    490                     $self->syncWordpressUserToAudiencePlayer($user->ID, ['password' => $newPassword]);
    491                 }
    492 
    493                 return true;
    494             });
    495459        }
    496460    }
     
    522486                    $userArgs['name'] = $name;
    523487                }
    524                 if ($password = $self->fetchDetectedNewUserRegistrationPassword(trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {
     488                if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) {
    525489                    $userArgs['password'] = $password;
    526490                }
    527                 if ($newUserEmail = $newUserEmail ?: ($_REQUEST['user_email'] ?? null)) {
     491                if ($newUserEmail = $newUserEmail ?: $self->assembleSubmittedRequestProperty(['user_email'])) {
    528492                    $self->syncWordpressUserRegisterAction($newUserEmail, $userArgs, $wpError);
    529493                }
     
    542506                    $self->isNewUserRegistrationRequest = true;
    543507
    544                     if (isset($_REQUEST['pass2'])) {
    545                         $self->newUserRegistrationPassword = $_REQUEST['pass2'];
     508                    if ($password = $self->assembleSubmittedRequestProperty(['pass2'])) {
     509                        $self->newUserRegistrationPassword = $password;
    546510                    }
    547511                }
     
    562526                if ($self->isNewUserRegistrationRequest) {
    563527
    564                     if (trim($_REQUEST['email'] ?? '')) {
    565                         $userArgs['email'] = trim(\sanitize_email($_REQUEST['email'] ?? ''));
    566                     }
    567                     if ($password = $self->fetchDetectedNewUserRegistrationPassword(trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {
     528                    if ($email = $self->assembleSubmittedRequestProperty(['email'])) {
     529                        $userArgs['email'] = trim(\sanitize_email($email));
     530                    }
     531                    if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) {
    568532                        $userArgs['password'] = $password;
    569533                    }
     
    595559                    // Parse properties eligible for AudiencePlayer sync
    596560                    $userArgs = [];
    597                     if (trim($_REQUEST['email'] ?? '')) {
    598                         $userArgs['email'] = trim($_REQUEST['email'] ?? '');
    599                     }
    600                     if (trim($_REQUEST['pass2'] ?? '')) {
    601                         $userArgs['password'] = trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? '');
     561                    if ($email = $self->assembleSubmittedRequestProperty(['email'])) {
     562                        $userArgs['email'] = \sanitize_email($email);
     563                        $self->isChangeAttemptedOnEmail = true;
     564                    }
     565                    if ($password = $self->assembleSubmittedRequestProperty(['pass2', 'user_pass'])) {
     566                        $userArgs['password'] = $password;
     567                        $self->isChangeAttemptedOnPassword = true;
    602568                    }
    603569                    if ($name = $self->helper->parseUserFullNameFromUserData($_REQUEST)) {
     
    611577                        $wpError
    612578                    );
     579
    613580                    if ($result) {
    614581                        // change-validation e-mail is sent early on in "admin-filters.php": \add_action('personal_options_update', 'send_confirmation_on_profile_email');
     
    625592            // if user has entered confirm-change-email-flow by clicking on link e-mail "email_change_email"
    626593            // "get_user_metadata": Runs very shortly after user has clicked on the " profile.php?newuseremail" link an
    627             // in e-mail to confirm change of e-mail address, and has antered the "newuseremail"-flow in user-edit.php
     594            // in e-mail to confirm change of e-mail address, and has entered the "newuseremail"-flow in user-edit.php
    628595            // Before the applicable metakey (containing the new e-mail address) is parsed, we inject an AudiencePlayer
    629596            // check.
     
    634601                // recreated evaluation logic contained in user-edit.php to obtain the new e-mail address
    635602                if (
     603                    !$self->isChangeAttemptedOnEmail &&
    636604                    defined('IS_PROFILE_PAGE') &&
    637605                    IS_PROFILE_PAGE &&
     
    646614                    if ($new_email && ($new_email['newemail'] ?? null) && hash_equals($new_email['hash'], $_REQUEST['newuseremail'])) {
    647615
     616                        $self->isChangeAttemptedOnEmail = true;
     617
    648618                        $userArgs = ['email' => trim($new_email['newemail'] ?? '')];
    649619
     
    657627                        if (false === $result) {
    658628                            // @TODO: consider creating the missing Wordpress user
    659                             //$this->createWordpressUser($currentUserData);
     629                            //$self->createWordpressUser($currentUserData);
    660630                            \delete_user_meta($wordpressUserId, '_new_email');
    661                             \wp_die($this->fetchTranslations('dialogue_email_address_exists_conflict'));
     631                            \wp_die($self->fetchTranslations('dialogue_email_address_exists_conflict'));
    662632                            return false;
    663633                        }
     
    668638
    669639            }, 10, 5);
     640
     641            // "login_form_lostpassword"/"login_form_retrievepassword": Runs immediately before given action "lostpassword" or "retrievepassword" is processed.
     642            // Ensures local user is first created, if it exists remotely.
     643            $lostPasswordCallback = function ($args = null) use ($self) {
     644
     645                if (
     646                    isset($_REQUEST['wp-submit']) &&
     647                    ($userLogin = $self->assembleSubmittedRequestProperty(['user_login', 'log', 'login', 'email'])) &&
     648                    filter_var($userLogin, FILTER_VALIDATE_EMAIL) &&
     649                    (false === (username_exists($userLogin) || email_exists($userLogin))) &&
     650                    ($remoteUser = $self->fetchRemoteAudiencePlayerUser(0, $userLogin))
     651                ) {
     652
     653                    $userArgs = [
     654                        'user_login' => $userLogin,
     655                        'user_pass' => \wp_generate_password(),
     656                        'user_nicename' => $remoteUser->name,
     657                        'display_name' => $remoteUser->name,
     658                    ];
     659
     660                    $self->isChangeAttemptedOnPassword = true;
     661
     662                    return $self->syncAudiencePlayerUserToWordpress($remoteUser->id, $userLogin, $userArgs, false);
     663                }
     664
     665                return $args;
     666            };
     667            \add_action('login_form_lostpassword', $lostPasswordCallback);
     668            \add_action('login_form_retrievepassword', $lostPasswordCallback);
     669
     670            // "after_password_reset": Runs immediately upon completion of function \reset_password (e.g. when wp_set_password() is used).
     671            // Update the password for given user
     672            \add_action('after_password_reset', function ($user = null, $newPassword = '') use ($self) {
     673                if (
     674                    !$self->isChangeAttemptedOnPassword &&
     675                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) &&
     676                    ($newPassword = trim($newPassword) ?: $self->assembleSubmittedRequestProperty(['pass1', 'pass2']))
     677                ) {
     678                    $self->isChangeAttemptedOnPassword = true;
     679                    $self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword]);
     680                }
     681
     682                return true;
     683            }, 10, 2);
     684
     685            \add_action('password_reset', function ($user = null, $newPassword = null) use ($self) {
     686                if (
     687                    !$self->isChangeAttemptedOnPassword &&
     688                    ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) &&
     689                    ($newPassword = trim($newPassword) ?: $self->assembleSubmittedRequestProperty(['pass1', 'pass2', 'password_1', 'password_2']))
     690                ) {
     691                    $self->isChangeAttemptedOnPassword = true;
     692                    $self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword]);
     693                }
     694
     695                return true;
     696            });
     697
     698            // "send_password_change_email": Fires near the end of \wp_update_user(), which may be used by other plugins to update user email/password
     699            \add_action('send_password_change_email', function ($send, $user = null, $userdata = null) use ($self) {
     700
     701                $wordpressUserId = $self->assembleCallbackWordpressUserId($user);
     702
     703                if (
     704                    !$self->isChangeAttemptedOnPassword &&
     705                    $wordpressUserId &&
     706                    // password_1, password_2 are used by plugins such as WooCommerce
     707                    ($newPassword = $self->assembleSubmittedRequestProperty(['pass1', 'pass2', 'password_1', 'password_2']))
     708                ) {
     709                    $self->isChangeAttemptedOnPassword = true;
     710
     711                    // If sync fails, exit current flow to avoid the change being executed in Wordpress (a falsy return on this action won't halt execution)
     712                    if (!$self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['password' => $newPassword])) {
     713                        \wp_die($self->fetchTranslations('dialogue_error_occurred'));
     714                    }
     715                }
     716
     717            }, 10, 2);
     718
     719            // "send_email_change_email": Fires near the end of \wp_update_user(), which may be used by other plugins to update user email/password
     720            \add_action('send_email_change_email', function ($send, $user = null, $userdata = null) use ($self) {
     721
     722                $wordpressUserId = $self->assembleCallbackWordpressUserId($user);
     723
     724                if (
     725                    !$self->isChangeAttemptedOnEmail &&
     726                    $wordpressUserId &&
     727                    // account_email is used by plugins such as WooCommerce
     728                    ($newEmail = $self->assembleSubmittedRequestProperty(['email', 'account_email']))
     729                ) {
     730                    $self->isChangeAttemptedOnEmail = true;
     731
     732                    // If sync fails, exit current flow to avoid the change being executed in Wordpress (a falsy return on this action won't halt execution)
     733                    if (!$self->syncWordpressUserToAudiencePlayer($wordpressUserId, ['email' => $newEmail])) {
     734                        \wp_die($self->fetchTranslations('dialogue_email_address_exists_conflict'));
     735                    }
     736                }
     737
     738            }, 10, 2);
    670739        }
    671740    }
     
    865934    }
    866935
     936    protected function assembleCallbackWordpressUserId($user)
     937    {
     938        if ($user && is_object($user) && ($user->ID ?? null)) {
     939
     940            return $user->ID;
     941
     942        } elseif (is_array($user) && ($user['ID'] ?? null)) {
     943
     944            return $user['ID'];
     945        }
     946
     947        return null;
     948    }
     949
     950    protected function assembleSubmittedRequestProperty(array $restrictKeys = [])
     951    {
     952        $ret = null;
     953
     954        foreach ($restrictKeys as $key) {
     955            if (is_null($ret)) {
     956                $ret = $_REQUEST[$key] ?? null;
     957            } else {
     958                break;
     959            }
     960        }
     961
     962        return trim(strval($ret));
     963    }
     964
    867965    /**
    868966     * @return bool
  • audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php

    r2596153 r2697320  
    544544            ];
    545545
    546             if ($user->user_email !== $email && !\wp_update_user(['ID' => $user->ID, 'email' => $email])) {
     546            // Update user e-mail address if necessary
     547            if (
     548                $user->user_email !== $email &&
     549                ($this->isChangeAttemptedOnEmail = true) &&
     550                !($retUpdateUser = \wp_update_user(['ID' => $user->ID, 'user_email' => $email]))
     551            ) {
    547552
    548553                // Log exception
     
    551556                    'resource.user-sync.sync-audienceplayer-user-to-wordpress.db-insert-new-user-error',
    552557                    'Error updating Wordpress user e-mail "' . $user->user_email . '" => "' . $email . '"',
    553                     $logArgs
     558                    array_merge($logArgs, ['wp_update_user_result' => $retUpdateUser])
    554559                );
    555560
     
    557562            }
    558563
     564            // Delete existing user
    559565            if ($isDeleteUser) {
    560 
    561                 // delete existing user
    562566
    563567                $logId = $user->ID;
     
    583587            } else {
    584588
     589                if ($args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass'])) {
     590                    $this->isChangeAttemptedOnPassword = true;
     591                }
     592
    585593                $ret = $this->syncAudiencePlayerUserAuthentication($user->ID, $userArgs, false, true, Constants::USER_METADATA_SYNC_DIRECTION_A2WP);
    586                 $args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass']);
    587594
    588595                // metadata already handled in syncAudiencePlayerUserAuthentication, but password may also have been changed
    589                 if ($ret && $args) {
    590                     $ret = $this->updateWordpressUser($user->ID, $args);
     596                if ($ret) {
     597                    if ($args) {
     598                        ($this->isChangeAttemptedOnPassword = true) &&
     599
     600                        $ret = $this->updateWordpressUser($user->ID, $args);
     601                    } else {
     602                        $this->writeLog(
     603                            Constants::LOG_LEVEL_SYSTEM_ERROR,
     604                            'resource.user-sync.sync-audienceplayer-user-to-wordpress.update-wordpress-user',
     605                            'Error updating wordpress user after successful audienceplayer user authentication synchronisation',
     606                            $logArgs
     607                        );
     608                    }
     609                } else {
     610                    $this->writeLog(
     611                        Constants::LOG_LEVEL_SYSTEM_ERROR,
     612                        'resource.user-sync.sync-audienceplayer-user-to-wordpress.sync-user-authentication',
     613                        'Error synchronising audienceplayer user authentication',
     614                        $logArgs
     615                    );
    591616                }
    592617            }
  • audienceplayer/trunk/static/html/admin_help_release_notes.html

    r2694680 r2697320  
    11<h3>Release notes</h3>
     2
     3<div class="audienceplayer-release-note">
     4    <h5>v3.3.3</h5>
     5    <p class="date">2022-03-21</p>
     6    <p class="content">
     7        Expanded user synchronisation of e-mail/password to cover calls to cover wp_set_password() and wp_update_user(), in order to improve compatibility with third party plugins (such as WooCommerce).
     8    </p>
     9</div>
    210
    311<div class="audienceplayer-release-note">
Note: See TracChangeset for help on using the changeset viewer.