Issues (257)

src/Services/UserSystem/UserAvatarHelper.php (3 issues)

1
<?php
2
/*
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4
 *
5
 *  Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 *  This program is free software: you can redistribute it and/or modify
8
 *  it under the terms of the GNU Affero General Public License as published
9
 *  by the Free Software Foundation, either version 3 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU Affero General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU Affero General Public License
18
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace App\Services\UserSystem;
22
23
use App\Entity\Attachments\Attachment;
24
use App\Entity\Attachments\AttachmentType;
25
use App\Entity\Attachments\UserAttachment;
26
use App\Entity\UserSystem\User;
27
use App\Services\Attachments\AttachmentSubmitHandler;
28
use App\Services\Attachments\AttachmentURLGenerator;
29
use Doctrine\ORM\EntityManagerInterface;
30
use Liip\ImagineBundle\Service\FilterService;
31
use Symfony\Component\Asset\Packages;
32
use Symfony\Component\HttpFoundation\File\UploadedFile;
33
34
class UserAvatarHelper
35
{
36
    private bool $use_gravatar;
37
    private Packages $packages;
38
    private AttachmentURLGenerator $attachmentURLGenerator;
39
    private FilterService $filterService;
40
    private EntityManagerInterface $entityManager;
41
    private AttachmentSubmitHandler $submitHandler;
42
43
    public function __construct(bool $use_gravatar, Packages $packages, AttachmentURLGenerator $attachmentURLGenerator,
44
        FilterService $filterService, EntityManagerInterface $entityManager, AttachmentSubmitHandler $attachmentSubmitHandler)
45
    {
46
        $this->use_gravatar = $use_gravatar;
47
        $this->packages = $packages;
48
        $this->attachmentURLGenerator = $attachmentURLGenerator;
49
        $this->filterService = $filterService;
50
        $this->entityManager = $entityManager;
51
        $this->submitHandler = $attachmentSubmitHandler;
52
    }
53
54
55
    /**
56
     * Returns the URL to the profile picture of the given user (in big size)
57
     * @param  User  $user
58
     * @return string
59
     */
60
    public function getAvatarURL(User $user): string
61
    {
62
        //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture)
63
        if ($user->getMasterPictureAttachment() !== null) {
64
            return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_md');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->attachment...ment(), 'thumbnail_md') could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
65
        }
66
67
        //If not check if gravatar is enabled (then use gravatar URL)
68
        if ($this->use_gravatar) {
69
            return $this->getGravatar($user, 200); //200px wide picture
70
        }
71
72
        //Fallback to the default avatar picture
73
        return $this->packages->getUrl('/img/default_avatar.png');
74
    }
75
76
    public function getAvatarSmURL(User $user): string
77
    {
78
        //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture)
79
        if ($user->getMasterPictureAttachment() !== null) {
80
            return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_xs');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->attachment...ment(), 'thumbnail_xs') could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
81
        }
82
83
        //If not check if gravatar is enabled (then use gravatar URL)
84
        if ($this->use_gravatar) {
85
            return $this->getGravatar($user, 50); //50px wide picture
86
        }
87
88
        try {
89
            //Otherwise we can serve the relative path via Asset component
90
            return $this->filterService->getUrlOfFilteredImage('/img/default_avatar.png', 'thumbnail_xs');
91
        } catch (\Imagine\Exception\RuntimeException $e) {
92
            //If the filter fails, we can not serve the thumbnail and fall back to the original image and log an warning
93
            return $this->packages->getUrl('/img/default_avatar.png');
94
        }
95
    }
96
97
    public function getAvatarMdURL(User $user): string
98
    {
99
        //Check if the user has a master attachment defined (meaning he has explicitly defined a profile picture)
100
        if ($user->getMasterPictureAttachment() !== null) {
101
            return $this->attachmentURLGenerator->getThumbnailURL($user->getMasterPictureAttachment(), 'thumbnail_sm');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->attachment...ment(), 'thumbnail_sm') could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
102
        }
103
104
        //If not check if gravatar is enabled (then use gravatar URL)
105
        if ($this->use_gravatar) {
106
            return $this->getGravatar($user, 150);
107
        }
108
109
        try {
110
            //Otherwise we can serve the relative path via Asset component
111
            return $this->filterService->getUrlOfFilteredImage('/img/default_avatar.png', 'thumbnail_xs');
112
        } catch (\Imagine\Exception\RuntimeException $e) {
113
            //If the filter fails, we can not serve the thumbnail and fall back to the original image and log an warning
114
            return $this->packages->getUrl('/img/default_avatar.png');
115
        }
116
    }
117
118
119
    /**
120
     * Get either a Gravatar URL or complete image tag for a specified email address.
121
     *
122
     * @param  User $user The user for which the gravator should be generated
123
     * @param  int  $s  Size in pixels, defaults to 80px [ 1 - 2048 ]
124
     * @param  string  $d  Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
125
     * @param  string  $r  Maximum rating (inclusive) [ g | pg | r | x ]
126
     *
127
     * @return string containing either just a URL or a complete image tag
128
     * @source https://gravatar.com/site/implement/images/php/
129
     */
130
    private function getGravatar(User $user, int $s = 80, string $d = 'identicon', string $r = 'g'): string
131
    {
132
        $email = $user->getEmail();
133
        if (empty($email)) {
134
            $email = 'Part-DB';
135
        }
136
137
        $url = 'https://www.gravatar.com/avatar/';
138
        $url .= md5(strtolower(trim($email)));
139
        $url .= "?s=${s}&d=${d}&r=${r}";
140
141
        return $url;
142
    }
143
144
    /**
145
     * Handles the upload of the user avatar.
146
     * @param  User  $user
147
     * @param  UploadedFile  $file
148
     * @return Attachment
149
     */
150
    public function handleAvatarUpload(User $user, UploadedFile $file): Attachment
151
    {
152
        //Determine which attachment to user
153
        //If the user already has a master attachment, we use this one
154
        if ($user->getMasterPictureAttachment()) {
155
            $attachment = $user->getMasterPictureAttachment();
156
        } else { //Otherwise we have to create one
157
            $attachment = new UserAttachment();
158
            $user->addAttachment($attachment);
159
            $user->setMasterPictureAttachment($attachment);
160
            $attachment->setName('Avatar');
161
162
            //Retrieve or create the avatar attachment type
163
            $attachment_type = $this->entityManager->getRepository(AttachmentType::class)->findOneBy(['name' => 'Avatars']);
164
            if ($attachment_type === null) {
165
                $attachment_type = new AttachmentType();
166
                $attachment_type->setName('Avatars');
167
                $attachment_type->setFiletypeFilter('image/*');
168
                $this->entityManager->persist($attachment_type);
169
            }
170
171
            $attachment->setAttachmentType($attachment_type);
172
            //$user->setMasterPictureAttachment($attachment);
173
        }
174
175
        //Handle the upload
176
        $this->submitHandler->handleFormSubmit($attachment, $file);
177
178
        //Set attachment as master picture
179
        $user->setMasterPictureAttachment($attachment);
180
181
        return $attachment;
182
    }
183
}