Avoid potential race condition when saving profile visitors
authorMarcel Werk <burntime@woltlab.com>
Fri, 24 Apr 2020 15:02:40 +0000 (17:02 +0200)
committerMarcel Werk <burntime@woltlab.com>
Fri, 24 Apr 2020 15:02:40 +0000 (17:02 +0200)
wcfsetup/install/files/lib/data/user/profile/visitor/UserProfileVisitorAction.class.php
wcfsetup/install/files/lib/page/UserPage.class.php

index dbdf785ad08addbff65fdaa1f6dcf99f8622a622..2f7f6d4f124a352ddd0aea2681511882b6d960b5 100644 (file)
@@ -82,4 +82,21 @@ class UserProfileVisitorAction extends AbstractDatabaseObjectAction implements I
                        'template' => WCF::getTPL()->fetch('groupedUserList')
                ];
        }
+       
+       /**
+        * Inserts a new visitor if it does not already exist, or updates it if it does.
+        * @since       5.2
+        */
+       public function registerVisitor() {
+               $sql = "INSERT INTO             wcf".WCF_N."_user_profile_visitor
+                                               (ownerID, userID, time)
+                       VALUES                  (?, ?, ?)
+                       ON DUPLICATE KEY UPDATE time = VALUES(time)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute([
+                       $this->parameters['data']['ownerID'],
+                       $this->parameters['data']['userID'],
+                       $this->parameters['data']['time'] ?? TIME_NOW,
+               ]);
+       }
 }
index 96c7c6574ae86575def522f48cd29743d7bdb2fc..072232effe430070d70743348a59a5af03ac4974 100644 (file)
@@ -6,8 +6,7 @@ use wcf\data\user\cover\photo\UserCoverPhoto;
 use wcf\data\user\follow\UserFollowerList;
 use wcf\data\user\follow\UserFollowingList;
 use wcf\data\user\group\UserGroup;
-use wcf\data\user\profile\visitor\UserProfileVisitor;
-use wcf\data\user\profile\visitor\UserProfileVisitorEditor;
+use wcf\data\user\profile\visitor\UserProfileVisitorAction;
 use wcf\data\user\profile\visitor\UserProfileVisitorList;
 use wcf\data\user\UserEditor;
 use wcf\data\user\UserProfile;
@@ -180,17 +179,12 @@ class UserPage extends AbstractPage {
                        // save visitor
                        /** @noinspection PhpUndefinedFieldInspection */
                        if (PROFILE_ENABLE_VISITORS && WCF::getUser()->userID && !WCF::getUser()->canViewOnlineStatus) {
-                               if (($visitor = UserProfileVisitor::getObject($this->user->userID, WCF::getUser()->userID)) !== null) {
-                                       $editor = new UserProfileVisitorEditor($visitor);
-                                       $editor->update(['time' => TIME_NOW]);
-                               }
-                               else {
-                                       UserProfileVisitorEditor::create([
+                               (new UserProfileVisitorAction([], 'registerVisitor', [
+                                       'data' => [
                                                'ownerID' => $this->user->userID,
                                                'userID' => WCF::getUser()->userID,
-                                               'time' => TIME_NOW
-                                       ]);
-                               }
+                                       ]
+                               ]))->executeAction();
                        }
                }