Passed
Push — master ( 49242a...606e42 )
by Derek Stephen
03:08
created

BoneUserApiController::uploadAvatarAction()   B

Complexity

Conditions 5
Paths 35

Size

Total Lines 59
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 59
ccs 37
cts 37
cp 1
rs 8.9848
cc 5
nc 35
nop 1
crap 5

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 8
    }
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);
79
80 1
        return new JsonResponse([
81 1
            'result' => 'success',
82 1
            'message' => 'Avatar is now set to ' . $avatar . '.',
83 1
            'avatar' => $avatar,
84
        ]);
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);
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
                ]);
140 1
            } catch (Exception $e) {
141 1
                return new JsonResponse([
142 1
                    'result' => 'danger',
143 1
                    'message' => $e->getMessage(),
144
                ]);
145
            }
146
        }
147
148 1
        return new JsonResponse([
149 1
            'result' => 'danger',
150
            'message' => 'There was a problem with your upload.',
151
        ]);
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