3 namespace BookStack\Uploads;
5 use BookStack\Auth\Access\LdapService;
6 use BookStack\Auth\User;
7 use BookStack\Exceptions\HttpFetchException;
9 use Illuminate\Support\Facades\Log;
13 protected $imageService;
16 public function __construct(ImageService $imageService, HttpFetcher $http)
18 $this->imageService = $imageService;
20 $ldapService = app()->make(LdapService::class);
24 * Fetch and assign an avatar image to the given user.
26 public function fetchAndAssignToUser(User $user): void
28 if (!$this->avatarFetchEnabled()) {
33 $this->destroyAllForUser($user);
34 $avatar = $this->saveAvatarImage($user);
35 $user->avatar()->associate($avatar);
37 } catch (Exception $e) {
38 Log::error('Failed to save user avatar image');
43 * Assign a new avatar image to the given user using the given image data.
45 public function assignToUserFromExistingData(User $user, string $imageData, string $extension): void
48 $this->destroyAllForUser($user);
49 $avatar = $this->createAvatarImageFromData($user, $imageData, $extension);
50 $user->avatar()->associate($avatar);
52 } catch (Exception $e) {
53 Log::error('Failed to save user avatar image');
58 * Destroy all user avatars uploaded to the given user.
60 public function destroyAllForUser(User $user)
62 $profileImages = Image::query()->where('type', '=', 'user')
63 ->where('uploaded_to', '=', $user->id)
66 foreach ($profileImages as $image) {
67 $this->imageService->destroy($image);
72 * Save an avatar image from an external service.
76 protected function saveAvatarImage(User $user, int $size = 500): Image
78 $avatarUrl = $this->getAvatarUrl();
79 $email = strtolower(trim($user->email));
82 '${hash}' => md5($email),
84 '${email}' => urlencode($email),
87 $userAvatarUrl = strtr($avatarUrl, $replacements);
88 $imageData = $this->getAvatarImageData($userAvatarUrl);
90 return $this->createAvatarImageFromData($user, $imageData, 'png');
94 * Creates a new image instance and saves it in the system as a new user avatar image.
96 protected function createAvatarImageFromData(User $user, string $imageData, string $extension): Image
98 $imageName = str_replace(' ', '-', $user->id . '-avatar.' . $extension);
100 $image = $this->imageService->saveNew($imageName, $imageData, 'user', $user->id);
101 $image->created_by = $user->id;
102 $image->updated_by = $user->id;
109 * Gets an image from url and returns it as a string of image data.
113 protected function getAvatarImageData(string $url): string
116 $imageData = $this->http->fetch($url);
117 } catch (HttpFetchException $exception) {
118 throw new Exception(trans('errors.cannot_get_image_from_url', ['url' => $url]));
125 * Check if fetching external avatars is enabled.
127 protected function avatarFetchEnabled(): bool
129 $fetchUrl = $this->getAvatarUrl();
131 return is_string($fetchUrl) && strpos($fetchUrl, 'http') === 0;
135 * Get the URL to fetch avatars from.
137 protected function getAvatarUrl(): string
139 $url = trim(config('services.avatar_url'));
141 if (empty($url) && !config('services.disable_services')) {
142 $url = 'https://www.gravatar.com/avatar/${hash}?s=${size}&d=identicon';