Changeset 2697320
- Timestamp:
- 03/21/2022 08:56:27 PM (4 years ago)
- Location:
- audienceplayer
- Files:
-
- 14 edited
- 1 copied
-
tags/3.3.3 (copied) (copied from audienceplayer/trunk)
-
tags/3.3.3/audienceplayer.php (modified) (1 diff)
-
tags/3.3.3/languages/audienceplayer-wordpress-plugin.pot (modified) (1 diff)
-
tags/3.3.3/readme.txt (modified) (1 diff)
-
tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php (modified) (1 diff)
-
tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php (modified) (15 diffs)
-
tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php (modified) (4 diffs)
-
tags/3.3.3/static/html/admin_help_release_notes.html (modified) (1 diff)
-
trunk/audienceplayer.php (modified) (1 diff)
-
trunk/languages/audienceplayer-wordpress-plugin.pot (modified) (1 diff)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php (modified) (1 diff)
-
trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php (modified) (15 diffs)
-
trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php (modified) (4 diffs)
-
trunk/static/html/admin_help_release_notes.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
audienceplayer/tags/3.3.3/audienceplayer.php
r2694680 r2697320 9 9 Description: AudiencePlayer integration 10 10 Author: AudiencePlayer 11 Version: 3.3. 211 Version: 3.3.3 12 12 Author URI: https://www.audienceplayer.com 13 13 Text Domain: audienceplayer -
audienceplayer/tags/3.3.3/languages/audienceplayer-wordpress-plugin.pot
r2694680 r2697320 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: 3.3. 2\n"5 "Project-Id-Version: 3.3.3\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/audienceplayer\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -
audienceplayer/tags/3.3.3/readme.txt
r2694680 r2697320 1 1 === AudiencePlayer === 2 2 Contributors: audienceplayer 3 Stable tag: 3.3. 23 Stable tag: 3.3.3 4 4 Tested up to: 5.9 5 5 Requires at least: 5.5 -
audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php
r2694680 r2697320 39 39 40 40 // 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', 42 42 43 43 // DB migration version number is maintained here -
audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php
r2694680 r2697320 62 62 private $isNewUserAuthenticationRequest = false; 63 63 private $isNewUserAuthenticationSyncRequest = false; 64 private $isChangeAttemptedOnPassword = false; 65 private $isChangeAttemptedOnEmail = false; 64 66 private $validatedOrders = []; 65 67 … … 373 375 374 376 // 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); 376 378 // Fetch user password 377 $userPassword = $userPassword ?: ($_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '');379 $userPassword = $userPassword ?: $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password']); 378 380 // 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']); 380 382 381 383 if ( … … 441 443 $self->isNewUserAuthenticationRequest && 442 444 $self->isNewUserAuthenticationSyncRequest && 443 $user && is_object($user) && is_a($user, 'WP_User')445 ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) 444 446 ) { 445 447 $userArgs = []; 446 if ($password = $ _REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '') {448 if ($password = $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password'])) { 447 449 $userArgs['password'] = $password; 450 $self->isChangeAttemptedOnPassword = true; 448 451 } 449 452 // 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); 451 454 } 452 455 … … 454 457 455 458 }, 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 user484 \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 });495 459 } 496 460 } … … 522 486 $userArgs['name'] = $name; 523 487 } 524 if ($password = $self->fetchDetectedNewUserRegistrationPassword( trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {488 if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) { 525 489 $userArgs['password'] = $password; 526 490 } 527 if ($newUserEmail = $newUserEmail ?: ($_REQUEST['user_email'] ?? null)) {491 if ($newUserEmail = $newUserEmail ?: $self->assembleSubmittedRequestProperty(['user_email'])) { 528 492 $self->syncWordpressUserRegisterAction($newUserEmail, $userArgs, $wpError); 529 493 } … … 542 506 $self->isNewUserRegistrationRequest = true; 543 507 544 if ( isset($_REQUEST['pass2'])) {545 $self->newUserRegistrationPassword = $ _REQUEST['pass2'];508 if ($password = $self->assembleSubmittedRequestProperty(['pass2'])) { 509 $self->newUserRegistrationPassword = $password; 546 510 } 547 511 } … … 562 526 if ($self->isNewUserRegistrationRequest) { 563 527 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']))) { 568 532 $userArgs['password'] = $password; 569 533 } … … 595 559 // Parse properties eligible for AudiencePlayer sync 596 560 $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; 602 568 } 603 569 if ($name = $self->helper->parseUserFullNameFromUserData($_REQUEST)) { … … 611 577 $wpError 612 578 ); 579 613 580 if ($result) { 614 581 // change-validation e-mail is sent early on in "admin-filters.php": \add_action('personal_options_update', 'send_confirmation_on_profile_email'); … … 625 592 // if user has entered confirm-change-email-flow by clicking on link e-mail "email_change_email" 626 593 // "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.php594 // in e-mail to confirm change of e-mail address, and has entered the "newuseremail"-flow in user-edit.php 628 595 // Before the applicable metakey (containing the new e-mail address) is parsed, we inject an AudiencePlayer 629 596 // check. … … 634 601 // recreated evaluation logic contained in user-edit.php to obtain the new e-mail address 635 602 if ( 603 !$self->isChangeAttemptedOnEmail && 636 604 defined('IS_PROFILE_PAGE') && 637 605 IS_PROFILE_PAGE && … … 646 614 if ($new_email && ($new_email['newemail'] ?? null) && hash_equals($new_email['hash'], $_REQUEST['newuseremail'])) { 647 615 616 $self->isChangeAttemptedOnEmail = true; 617 648 618 $userArgs = ['email' => trim($new_email['newemail'] ?? '')]; 649 619 … … 657 627 if (false === $result) { 658 628 // @TODO: consider creating the missing Wordpress user 659 //$ this->createWordpressUser($currentUserData);629 //$self->createWordpressUser($currentUserData); 660 630 \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')); 662 632 return false; 663 633 } … … 668 638 669 639 }, 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); 670 739 } 671 740 } … … 865 934 } 866 935 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 867 965 /** 868 966 * @return bool -
audienceplayer/tags/3.3.3/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php
r2596153 r2697320 544 544 ]; 545 545 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 ) { 547 552 548 553 // Log exception … … 551 556 'resource.user-sync.sync-audienceplayer-user-to-wordpress.db-insert-new-user-error', 552 557 'Error updating Wordpress user e-mail "' . $user->user_email . '" => "' . $email . '"', 553 $logArgs558 array_merge($logArgs, ['wp_update_user_result' => $retUpdateUser]) 554 559 ); 555 560 … … 557 562 } 558 563 564 // Delete existing user 559 565 if ($isDeleteUser) { 560 561 // delete existing user562 566 563 567 $logId = $user->ID; … … 583 587 } else { 584 588 589 if ($args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass'])) { 590 $this->isChangeAttemptedOnPassword = true; 591 } 592 585 593 $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']);587 594 588 595 // 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 ); 591 616 } 592 617 } -
audienceplayer/tags/3.3.3/static/html/admin_help_release_notes.html
r2694680 r2697320 1 1 <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> 2 10 3 11 <div class="audienceplayer-release-note"> -
audienceplayer/trunk/audienceplayer.php
r2694680 r2697320 9 9 Description: AudiencePlayer integration 10 10 Author: AudiencePlayer 11 Version: 3.3. 211 Version: 3.3.3 12 12 Author URI: https://www.audienceplayer.com 13 13 Text Domain: audienceplayer -
audienceplayer/trunk/languages/audienceplayer-wordpress-plugin.pot
r2694680 r2697320 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: 3.3. 2\n"5 "Project-Id-Version: 3.3.3\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/audienceplayer\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -
audienceplayer/trunk/readme.txt
r2694680 r2697320 1 1 === AudiencePlayer === 2 2 Contributors: audienceplayer 3 Stable tag: 3.3. 23 Stable tag: 3.3.3 4 4 Tested up to: 5.9 5 5 Requires at least: 5.5 -
audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Config/Constants.php
r2694680 r2697320 39 39 40 40 // 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', 42 42 43 43 // DB migration version number is maintained here -
audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/BootstrapTrait.php
r2694680 r2697320 62 62 private $isNewUserAuthenticationRequest = false; 63 63 private $isNewUserAuthenticationSyncRequest = false; 64 private $isChangeAttemptedOnPassword = false; 65 private $isChangeAttemptedOnEmail = false; 64 66 private $validatedOrders = []; 65 67 … … 373 375 374 376 // 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); 376 378 // Fetch user password 377 $userPassword = $userPassword ?: ($_REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '');379 $userPassword = $userPassword ?: $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password']); 378 380 // 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']); 380 382 381 383 if ( … … 441 443 $self->isNewUserAuthenticationRequest && 442 444 $self->isNewUserAuthenticationSyncRequest && 443 $user && is_object($user) && is_a($user, 'WP_User')445 ($wordpressUserId = $self->assembleCallbackWordpressUserId($user)) 444 446 ) { 445 447 $userArgs = []; 446 if ($password = $ _REQUEST['pwd'] ?? $_REQUEST['user_pass'] ?? $_REQUEST['password'] ?? '') {448 if ($password = $self->assembleSubmittedRequestProperty(['pwd', 'user_pass', 'password'])) { 447 449 $userArgs['password'] = $password; 450 $self->isChangeAttemptedOnPassword = true; 448 451 } 449 452 // 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); 451 454 } 452 455 … … 454 457 455 458 }, 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 user484 \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 });495 459 } 496 460 } … … 522 486 $userArgs['name'] = $name; 523 487 } 524 if ($password = $self->fetchDetectedNewUserRegistrationPassword( trim($_REQUEST['pass2'] ?? $_REQUEST['user_pass'] ?? ''))) {488 if ($password = $self->fetchDetectedNewUserRegistrationPassword($self->assembleSubmittedRequestProperty(['pass2', 'user_pass']))) { 525 489 $userArgs['password'] = $password; 526 490 } 527 if ($newUserEmail = $newUserEmail ?: ($_REQUEST['user_email'] ?? null)) {491 if ($newUserEmail = $newUserEmail ?: $self->assembleSubmittedRequestProperty(['user_email'])) { 528 492 $self->syncWordpressUserRegisterAction($newUserEmail, $userArgs, $wpError); 529 493 } … … 542 506 $self->isNewUserRegistrationRequest = true; 543 507 544 if ( isset($_REQUEST['pass2'])) {545 $self->newUserRegistrationPassword = $ _REQUEST['pass2'];508 if ($password = $self->assembleSubmittedRequestProperty(['pass2'])) { 509 $self->newUserRegistrationPassword = $password; 546 510 } 547 511 } … … 562 526 if ($self->isNewUserRegistrationRequest) { 563 527 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']))) { 568 532 $userArgs['password'] = $password; 569 533 } … … 595 559 // Parse properties eligible for AudiencePlayer sync 596 560 $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; 602 568 } 603 569 if ($name = $self->helper->parseUserFullNameFromUserData($_REQUEST)) { … … 611 577 $wpError 612 578 ); 579 613 580 if ($result) { 614 581 // change-validation e-mail is sent early on in "admin-filters.php": \add_action('personal_options_update', 'send_confirmation_on_profile_email'); … … 625 592 // if user has entered confirm-change-email-flow by clicking on link e-mail "email_change_email" 626 593 // "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.php594 // in e-mail to confirm change of e-mail address, and has entered the "newuseremail"-flow in user-edit.php 628 595 // Before the applicable metakey (containing the new e-mail address) is parsed, we inject an AudiencePlayer 629 596 // check. … … 634 601 // recreated evaluation logic contained in user-edit.php to obtain the new e-mail address 635 602 if ( 603 !$self->isChangeAttemptedOnEmail && 636 604 defined('IS_PROFILE_PAGE') && 637 605 IS_PROFILE_PAGE && … … 646 614 if ($new_email && ($new_email['newemail'] ?? null) && hash_equals($new_email['hash'], $_REQUEST['newuseremail'])) { 647 615 616 $self->isChangeAttemptedOnEmail = true; 617 648 618 $userArgs = ['email' => trim($new_email['newemail'] ?? '')]; 649 619 … … 657 627 if (false === $result) { 658 628 // @TODO: consider creating the missing Wordpress user 659 //$ this->createWordpressUser($currentUserData);629 //$self->createWordpressUser($currentUserData); 660 630 \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')); 662 632 return false; 663 633 } … … 668 638 669 639 }, 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); 670 739 } 671 740 } … … 865 934 } 866 935 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 867 965 /** 868 966 * @return bool -
audienceplayer/trunk/src/AudiencePlayer/AudiencePlayerWordpressPlugin/Resources/UserSyncTrait.php
r2596153 r2697320 544 544 ]; 545 545 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 ) { 547 552 548 553 // Log exception … … 551 556 'resource.user-sync.sync-audienceplayer-user-to-wordpress.db-insert-new-user-error', 552 557 'Error updating Wordpress user e-mail "' . $user->user_email . '" => "' . $email . '"', 553 $logArgs558 array_merge($logArgs, ['wp_update_user_result' => $retUpdateUser]) 554 559 ); 555 560 … … 557 562 } 558 563 564 // Delete existing user 559 565 if ($isDeleteUser) { 560 561 // delete existing user562 566 563 567 $logId = $user->ID; … … 583 587 } else { 584 588 589 if ($args = $this->helper->arrayOnly($this->helper->parseWordpressUserArgs($userArgs), ['user_pass'])) { 590 $this->isChangeAttemptedOnPassword = true; 591 } 592 585 593 $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']);587 594 588 595 // 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 ); 591 616 } 592 617 } -
audienceplayer/trunk/static/html/admin_help_release_notes.html
r2694680 r2697320 1 1 <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> 2 10 3 11 <div class="audienceplayer-release-note">
Note: See TracChangeset
for help on using the changeset viewer.