Support `File` in `AvatarDecorator` as avatar object
authorCyperghost <olaf_schmitz_1@t-online.de>
Thu, 7 Nov 2024 11:40:39 +0000 (12:40 +0100)
committerCyperghost <olaf_schmitz_1@t-online.de>
Thu, 7 Nov 2024 11:40:39 +0000 (12:40 +0100)
wcfsetup/install/files/lib/data/user/UserProfile.class.php
wcfsetup/install/files/lib/data/user/UserProfileList.class.php
wcfsetup/install/files/lib/data/user/avatar/AvatarDecorator.class.php

index 9f25aa0a5254003e4e6b136fae4d7ba3e85e6387..6fa145aaae1410dfb6aeb9b84411d0f2ae8257db 100644 (file)
@@ -3,6 +3,8 @@
 namespace wcf\data\user;
 
 use wcf\data\DatabaseObjectDecorator;
+use wcf\data\file\File;
+use wcf\data\file\thumbnail\FileThumbnailList;
 use wcf\data\ITitledLinkObject;
 use wcf\data\trophy\Trophy;
 use wcf\data\trophy\TrophyCache;
@@ -345,10 +347,31 @@ class UserProfile extends DatabaseObjectDecorator implements ITitledLinkObject
      */
     public function getAvatar()
     {
+        // TODO simplify this function?
         if ($this->avatar === null) {
             if (!$this->disableAvatar) {
                 if ($this->canSeeAvatar()) {
-                    if ($this->avatarID) {
+                    if ($this->avatarFileID !== null) {
+                        $data = UserStorageHandler::getInstance()->getField('avatar', $this->userID);
+                        if ($data === null) {
+                            $this->avatar = new File($this->avatarFileID);
+
+                            $thumbnailList = new FileThumbnailList();
+                            $thumbnailList->getConditionBuilder()->add("fileID = ?", [$this->avatarFileID]);
+                            $thumbnailList->readObjects();
+                            foreach ($thumbnailList as $thumbnail) {
+                                $this->avatar->addThumbnail($thumbnail);
+                            }
+
+                            UserStorageHandler::getInstance()->update(
+                                $this->userID,
+                                'avatar',
+                                \serialize($this->avatar)
+                            );
+                        } else {
+                            $this->avatar = \unserialize($data);
+                        }
+                    } elseif ($this->avatarID) {
                         if (!$this->fileHash) {
                             $data = UserStorageHandler::getInstance()->getField('avatar', $this->userID);
                             if ($data === null) {
@@ -393,6 +416,11 @@ class UserProfile extends DatabaseObjectDecorator implements ITitledLinkObject
         return $this->avatar;
     }
 
+    public function setFileAvatar(File $file): void
+    {
+        $this->avatar = new AvatarDecorator($file);
+    }
+
     /**
      * Returns true if the active user can view the avatar of this user.
      *
index ebe37f6b37f1267a81157149d4076f57e71b42ff..4c42f438523601f8d28bdc24b765e5b16db00484 100644 (file)
@@ -2,6 +2,9 @@
 
 namespace wcf\data\user;
 
+use wcf\data\file\FileList;
+use wcf\data\file\thumbnail\FileThumbnailList;
+
 /**
  * Represents a list of user profiles.
  *
@@ -27,6 +30,8 @@ class UserProfileList extends UserList
      */
     public $decoratorClassName = UserProfile::class;
 
+    public bool $loadAvatarFiles = true;
+
     /**
      * @inheritDoc
      */
@@ -37,13 +42,9 @@ class UserProfileList extends UserList
         if (!empty($this->sqlSelects)) {
             $this->sqlSelects .= ',';
         }
-        $this->sqlSelects .= "user_avatar.*";
-        $this->sqlJoins .= "
-            LEFT JOIN   wcf1_user_avatar user_avatar
-            ON          user_avatar.avatarID = user_table.avatarID";
 
         // get current location
-        $this->sqlSelects .= "session.pageID, session.pageObjectID, session.lastActivityTime AS sessionLastActivityTime";
+        $this->sqlSelects .= "session.pageID, session.pageObjectID, session.lastActivityTime AS sessionLastActivityTime";
         $this->sqlJoins .= "
             LEFT JOIN   wcf1_session session
             ON          session.userID = user_table.userID";
@@ -59,5 +60,42 @@ class UserProfileList extends UserList
         }
 
         parent::readObjects();
+
+        $this->loadAvatarFiles();
+    }
+
+    protected function loadAvatarFiles(): void
+    {
+        if (!$this->loadAvatarFiles) {
+            return;
+        }
+
+        $avatarFileIDs = [];
+        foreach ($this->objects as $user) {
+            if ($user->avatarFileID !== null) {
+                $avatarFileIDs[] = $user->avatarFileID;
+            }
+        }
+        if ($avatarFileIDs === []) {
+            return;
+        }
+
+        $fileList = new FileList();
+        $fileList->setObjectIDs($avatarFileIDs);
+        $fileList->readObjects();
+        $files = $fileList->getObjects();
+
+        $thumbnailList = new FileThumbnailList();
+        $thumbnailList->getConditionBuilder()->add("fileID IN (?)", [$avatarFileIDs]);
+        $thumbnailList->readObjects();
+        foreach ($thumbnailList as $thumbnail) {
+            $files[$thumbnail->fileID]->addThumbnail($thumbnail);
+        }
+
+        foreach ($this->objects as $user) {
+            if ($user->avatarFileID !== null) {
+                $user->setFileAvatar($files[$user->avatarFileID]);
+            }
+        }
     }
 }
index 1dcefff7177c18b422cdf981165f4b8393e12b6c..163c8c47eb95290098bc20e72a104d7250f17069 100644 (file)
@@ -2,6 +2,9 @@
 
 namespace wcf\data\user\avatar;
 
+use wcf\data\file\File;
+use wcf\util\StringUtil;
+
 /**
  * Wraps avatars to provide compatibility layers.
  *
@@ -11,12 +14,9 @@ namespace wcf\data\user\avatar;
  */
 final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
 {
-    /**
-     * @var IUserAvatar
-     */
-    private $avatar;
+    private IUserAvatar | File $avatar;
 
-    public function __construct(IUserAvatar $avatar)
+    public function __construct(IUserAvatar | File $avatar)
     {
         $this->avatar = $avatar;
     }
@@ -26,7 +26,9 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getSafeURL(?int $size = null): string
     {
-        if ($this->avatar instanceof ISafeFormatAvatar) {
+        if ($this->avatar instanceof File) {
+            return $this->getURL($size);
+        } elseif ($this->avatar instanceof ISafeFormatAvatar) {
             return $this->avatar->getSafeURL($size);
         }
 
@@ -38,7 +40,9 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getSafeImageTag(?int $size = null): string
     {
-        if ($this->avatar instanceof ISafeFormatAvatar) {
+        if ($this->avatar instanceof File) {
+            return $this->getImageTag($size);
+        } elseif ($this->avatar instanceof ISafeFormatAvatar) {
             return $this->avatar->getSafeImageTag($size);
         }
 
@@ -50,7 +54,16 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getURL($size = null)
     {
-        return $this->avatar->getURL();
+        if ($this->avatar instanceof File) {
+            $thumbnail = $this->avatar->getThumbnail($size ?? '');
+            if ($thumbnail !== null) {
+                return $thumbnail->getLink();
+            }
+
+            return $this->avatar->getLink();
+        } else {
+            return $this->avatar->getURL();
+        }
     }
 
     /**
@@ -58,7 +71,17 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getImageTag($size = null, bool $lazyLoading = true)
     {
-        return $this->avatar->getImageTag($size, $lazyLoading);
+        if ($this->avatar instanceof File) {
+            return \sprintf(
+                '<img src="%s" width="%d" height="%d" alt="" class="userAvatarImage" loading="%s">',
+                StringUtil::encodeHTML($this->getSafeURL($size)),
+                $size,
+                $size,
+                $lazyLoading ? 'lazy' : 'eager'
+            );
+        } else {
+            return $this->avatar->getImageTag($size, $lazyLoading);
+        }
     }
 
     /**
@@ -66,7 +89,11 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getWidth()
     {
-        return $this->avatar->getWidth();
+        if ($this->avatar instanceof File) {
+            return $this->avatar->width;
+        } else {
+            return $this->avatar->getWidth();
+        }
     }
 
     /**
@@ -74,6 +101,10 @@ final class AvatarDecorator implements IUserAvatar, ISafeFormatAvatar
      */
     public function getHeight()
     {
-        return $this->avatar->getHeight();
+        if ($this->avatar instanceof File) {
+            return $this->avatar->height;
+        } else {
+            return $this->avatar->getHeight();
+        }
     }
 }