]> BookStack Code Mirror - bookstack/blob - app/Uploads/UserAvatars.php
Filtered scripts in custom HTML head for exports
[bookstack] / app / Uploads / UserAvatars.php
1 <?php namespace BookStack\Uploads;
2
3 use BookStack\Auth\User;
4 use BookStack\Exceptions\HttpFetchException;
5 use Exception;
6 use Illuminate\Support\Facades\Log;
7
8 class UserAvatars
9 {
10     protected $imageService;
11     protected $http;
12
13     public function __construct(ImageService $imageService, HttpFetcher $http)
14     {
15         $this->imageService = $imageService;
16         $this->http = $http;
17     }
18
19     /**
20      * Fetch and assign an avatar image to the given user.
21      */
22     public function fetchAndAssignToUser(User $user): void
23     {
24         if (!$this->avatarFetchEnabled()) {
25             return;
26         }
27
28         try {
29             $avatar = $this->saveAvatarImage($user);
30             $user->avatar()->associate($avatar);
31             $user->save();
32         } catch (Exception $e) {
33             Log::error('Failed to save user avatar image');
34         }
35     }
36
37     /**
38      * Save an avatar image from an external service.
39      * @throws Exception
40      */
41     protected function saveAvatarImage(User $user, int $size = 500): Image
42     {
43         $avatarUrl = $this->getAvatarUrl();
44         $email = strtolower(trim($user->email));
45
46         $replacements = [
47             '${hash}' => md5($email),
48             '${size}' => $size,
49             '${email}' => urlencode($email),
50         ];
51
52         $userAvatarUrl = strtr($avatarUrl, $replacements);
53         $imageName = str_replace(' ', '-', $user->id . '-avatar.png');
54         $imageData = $this->getAvatarImageData($userAvatarUrl);
55
56         $image = $this->imageService->saveNew($imageName, $imageData, 'user', $user->id);
57         $image->created_by = $user->id;
58         $image->updated_by = $user->id;
59         $image->save();
60
61         return $image;
62     }
63
64     /**
65      * Gets an image from url and returns it as a string of image data.
66      * @throws Exception
67      */
68     protected function getAvatarImageData(string $url): string
69     {
70         try {
71             $imageData = $this->http->fetch($url);
72         } catch (HttpFetchException $exception) {
73             throw new Exception(trans('errors.cannot_get_image_from_url', ['url' => $url]));
74         }
75         return $imageData;
76     }
77
78     /**
79      * Check if fetching external avatars is enabled.
80      */
81     protected function avatarFetchEnabled(): bool
82     {
83         $fetchUrl = $this->getAvatarUrl();
84         return is_string($fetchUrl) && strpos($fetchUrl, 'http') === 0;
85     }
86
87     /**
88      * Get the URL to fetch avatars from.
89      */
90     protected function getAvatarUrl(): string
91     {
92         $url = trim(config('services.avatar_url'));
93
94         if (empty($url) && !config('services.disable_services')) {
95             $url = 'https://www.gravatar.com/avatar/${hash}?s=${size}&d=identicon';
96         }
97
98         return $url;
99     }
100 }