BoneUserApiController   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 195
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 12
eloc 88
c 4
b 0
f 0
dl 0
loc 195
ccs 90
cts 90
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getFilename() 0 30 2
A avatar() 0 19 2
A chooseAvatarAction() 0 17 1
A __construct() 0 7 1
A getMimeType() 0 7 1
B uploadAvatarAction() 0 59 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Bone\User\Controller;
6
7
use Bone\Http\Response;
8
use Bone\Http\Response\HtmlResponse;
9
use Bone\I18n\I18nAwareInterface;
10
use Bone\I18n\Traits\HasTranslatorTrait;
11
use Bone\Mail\EmailMessage;
12
use Bone\Server\SiteConfig;
13
use Bone\User\Form\RegistrationForm;
14
use DateTime;
15
use Del\Entity\Country;
16
use Del\Exception\UserException;
17
use Del\Factory\CountryFactory;
18
use Del\Form\Form;
19
use Exception;
20
use Bone\Controller\Controller;
21
use Bone\Mail\Service\MailService;
22
use Bone\User\Form\PersonForm;
23
use Del\Entity\User;
24
use Del\Form\Field\FileUpload;
25
use Del\Image;
26
use Del\Service\UserService;
27
use Laminas\Diactoros\Stream;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
use Laminas\Diactoros\Response\JsonResponse;
31
32
class BoneUserApiController extends Controller
33
{
34
    /** @var UserService $userService */
35
    private $userService;
36
37
    /** @var string $uploadsDirectory */
38
    private $uploadsDirectory;
39
40
    /** @var string $tempDirectory */
41
    private $tempDirectory;
42
43
    /** @var string $imgDirectory */
44
    private $imgDirectory;
45
46
    /** @var MailService $mailService */
47
    private $mailService;
48
49
    /**
50
     * BoneUserController constructor.
51
     * @param UserService $userService
52
     */
53 8
    public function __construct(UserService $userService, string $uploadsDirectory, string $imgSubDir, string $tempDirectory, MailService $mailService)
54
    {
55 8
        $this->userService = $userService;
56 8
        $this->uploadsDirectory = $uploadsDirectory;
57 8
        $this->tempDirectory = $tempDirectory;
58 8
        $this->imgDirectory = $imgSubDir;
59 8
        $this->mailService = $mailService;
60
    }
61
62
    /**
63
     * @param ServerRequestInterface $request
64
     * @param array $args
65
     * @return ResponseInterface
66
     */
67 1
    public function chooseAvatarAction(ServerRequestInterface $request): ResponseInterface
68
    {
69 1
        $avatar = $request->getParsedBody()['avatar'];
70
        /** @var User $user */
71 1
        $user = $request->getAttribute('user');
72 1
        $person = $user->getPerson();
73 1
        $image = new Image('public' . $avatar);
74 1
        $avatar = str_replace('/bone-user/img/avatars/', '', $avatar);
75 1
        $file = $this->imgDirectory . $this->getFilename($avatar);
76 1
        $image->save($this->uploadsDirectory . $file);
77 1
        $person->setImage($file);
78 1
        $this->userService->getPersonSvc()->savePerson($person);
0 ignored issues
show
Deprecated Code introduced by
The function Del\Service\UserService::getPersonSvc() has been deprecated: use getPersonService() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

78
        /** @scrutinizer ignore-deprecated */ $this->userService->getPersonSvc()->savePerson($person);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
79
80 1
        return new JsonResponse([
81 1
            'result' => 'success',
82 1
            'message' => 'Avatar is now set to ' . $avatar . '.',
83 1
            'avatar' => $avatar,
84 1
        ]);
85
    }
86
87
    /**
88
     * @param ServerRequestInterface $request
89
     * @param array $args
90
     * @return ResponseInterface
91
     */
92 5
    public function uploadAvatarAction(ServerRequestInterface $request): ResponseInterface
93
    {
94 5
        $data = $request->getParsedBody();
95 5
        $form = new Form('upload');
96 5
        $file = new FileUpload('avatar');
97 5
        $file->setUploadDirectory($this->tempDirectory);
98 5
        $file->setRequired(true);
99 5
        $form->addField($file);
100
101 5
        if ($form->isValid($data)) {
0 ignored issues
show
Unused Code introduced by
The call to Del\Form\AbstractForm::isValid() has too many arguments starting with $data. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

101
        if ($form->/** @scrutinizer ignore-call */ isValid($data)) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
102
103
            try {
104 4
                $data = $form->getValues();
105 4
                $file = $data['avatar'];
106 4
                $sourceFileName = $this->tempDirectory . $file;
107 4
                $newFileName = $this->imgDirectory . $this->getFilename($file);
108 4
                $destinationFileName = $this->uploadsDirectory . $newFileName;
109 4
                $image = new Image($sourceFileName);
110
111 4
                if ($image->getHeight() > $image->getWidth()) { //portrait
112
113 1
                    $image->resizeToWidth(100);
114 1
                    $image->crop(100, 100);
115
116 3
                } elseif ($image->getHeight() < $image->getWidth()) { //landscape
117
118 1
                    $image->resizeToHeight(100);
119 1
                    $image->crop(100, 100);
120
121
                } else { //square
122
123 2
                    $image->resize(100, 100);
124
125
                }
126 4
                $image->save($destinationFileName, 0775);
127 4
                unlink($sourceFileName);
128
129
                /** @var User $user */
130 4
                $user = $request->getAttribute('user');
131 4
                $person = $user->getPerson();
132 4
                $person->setImage($newFileName);
133 3
                $this->userService->getPersonSvc()->savePerson($person);
0 ignored issues
show
Deprecated Code introduced by
The function Del\Service\UserService::getPersonSvc() has been deprecated: use getPersonService() instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

133
                /** @scrutinizer ignore-deprecated */ $this->userService->getPersonSvc()->savePerson($person);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
134
135 3
                return new JsonResponse([
136 3
                    'result' => 'success',
137 3
                    'message' => 'Avatar now set to ' . $person->getImage(),
138 3
                    'avatar' => $person->getImage(),
139 3
                ]);
140 1
            } catch (Exception $e) {
141 1
                return new JsonResponse([
142 1
                    'result' => 'danger',
143 1
                    'message' => $e->getMessage(),
144 1
                ]);
145
            }
146
        }
147
148 1
        return new JsonResponse([
149 1
            'result' => 'danger',
150 1
            'message' => 'There was a problem with your upload.',
151 1
        ]);
152
    }
153
154
    /**
155
     * @param string $fileNameAsUploaded
156
     * @return string
157
     */
158 5
    private function getFilename(string $fileNameAsUploaded)
159
    {
160
        // break the filename up on dots
161 5
        $filenameParts = explode('.', $fileNameAsUploaded);
162
163
        // Create an array of encoded parts
164 5
        $encoded = [];
165
166
        // Loop through each part
167 5
        foreach ($filenameParts as $filenamePart) {
168
            // Url encode the filename part
169 5
            $encoded[] = urlencode($filenamePart);
170
        }
171
172
        // Create a little uniqueness, in case they upload a file with the same name
173 5
        $unique = dechex(time());
174
175
        // Pop off the last part (file extension)
176 5
        $ext = array_pop($encoded);
177
178
        // Push on the unique part
179 5
        $encoded[] = $unique;
180
181
        // Piece the encoded filename together
182 5
        $filenameOnDisk = implode('_', $encoded);
183
184
        // Add the extension
185 5
        $filenameOnDisk .= '.' . $ext;
186
187 5
        return $filenameOnDisk;
188
    }
189
190
    /**
191
     * @param ServerRequestInterface $request
192
     * @return ResponseInterface
193
     * @throws ControllerException
194
     */
195 1
    public function avatar(ServerRequestInterface $request): ResponseInterface
196
    {
197 1
        $response = new Response();
198
        /** @var User $user */
199 1
        $user = $request->getAttribute('user');
200
201 1
        if ($img = $user->getPerson()->getImage()) {
202 1
            $path = $this->uploadsDirectory . $img;
203 1
            $mimeType = $this->getMimeType($path);
204
        }
205
206
207 1
        $contents = file_get_contents($path);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $path does not seem to be defined for all execution paths leading up to this point.
Loading history...
208 1
        $stream = new Stream('php://memory', 'r+');
209 1
        $stream->write($contents);
210 1
        $response = $response->withBody($stream);
211 1
        $response = $response->withHeader('Content-Type', $mimeType);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mimeType does not seem to be defined for all execution paths leading up to this point.
Loading history...
212
213 1
        return $response;
214
    }
215
216
    /**
217
     * @param string $path
218
     * @return string
219
     */
220 1
    private function getMimeType(string $path): string
221
    {
222 1
        $finfo = finfo_open(FILEINFO_MIME); // return mime type
223 1
        $mimeType = finfo_file($finfo, $path);
224 1
        finfo_close($finfo);
225
226 1
        return $mimeType;
227
    }
228
229
}
230