Passed
Pull Request — master (#47)
by Rafael
04:41
created

FileManagementTrait   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Test Coverage

Coverage 77.78%

Importance

Changes 0
Metric Value
eloc 74
dl 0
loc 185
ccs 56
cts 72
cp 0.7778
rs 10
c 0
b 0
f 0
wmc 16

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getById() 0 13 2
A create() 0 7 2
A validation() 0 24 1
A edit() 0 28 4
B processFiles() 0 62 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gewaer\Traits;
6
7
use Phalcon\Http\Response;
8
use Phalcon\Validation;
9
use Phalcon\Validation\Validator\File as FileValidator;
10
use Gewaer\Exception\UnprocessableEntityHttpException;
11
use Gewaer\Models\FileSystem;
12
use Gewaer\Filesystem\Helper;
13
14
/**
15
 * Trait ResponseTrait
16
 *
17
 * @package Gewaer\Traits
18
 *
19
 * @property Users $user
20
 * @property AppsPlans $appPlan
21
 * @property CompanyBranches $branches
22
 * @property Companies $company
23
 * @property UserCompanyApps $app
24
 * @property \Phalcon\Di $di
25
 *
26
 */
27
trait FileManagementTrait
28
{
29
    /**
30
     * Get item.
31
     *
32
     * @method GET
33
     * url /v1/filesystem/{id}
34
     *
35
     * @param mixed $id
36
     *
37
     * @return \Phalcon\Http\Response
38
     * @throws Exception
39
     */
40
    public function getById($id) : Response
41
    {
42
        //find the info
43
        $records = $this->model->findFirst([
44
            'conditions' => 'entity_id = ?0 and companies_id = ?1 and apps_id = ?2',
45
            'bind' => [$id, $this->userData->currentCompanyId(), $this->app->getId()]
46
        ]);
47
48
        if (!is_object($records)) {
49
            throw new UnprocessableEntityHttpException('Records not found');
50
        }
51
52
        return $this->response($records);
53
    }
54
55
    /**
56
     * Add a new item.
57
     *
58
     * @method POST
59
     * url /v1/filesystem
60
     *
61
     * @return \Phalcon\Http\Response
62
     * @throws Exception
63
     */
64 1
    public function create() : Response
65
    {
66 1
        if (!$this->request->hasFiles()) {
67
            //@todo handle base64 images
68
        }
69
70 1
        return $this->response($this->processFiles());
71
    }
72
73
    /**
74
     * Update an item.
75
     *
76
     * @method PUT
77
     * url /v1/filesystem/{id}
78
     *
79
     * @param mixed $id
80
     *
81
     * @return \Phalcon\Http\Response
82
     * @throws Exception
83
     */
84 1
    public function edit($id) : Response
85
    {
86 1
        $file = $this->model->findFirst([
87 1
                'conditions' => 'id = ?0 and companies_id = ?1 and apps_id = ?2',
88 1
                'bind' => [$id, $this->userData->currentCompanyId(), $this->app->getId()]
89
            ]);
90
91 1
        if (!is_object($file)) {
92
            throw new UnprocessableEntityHttpException('Record not found');
93
        }
94
95 1
        $request = $this->request->getPut();
96
97 1
        if (empty($request)) {
98
            $request = $this->request->getJsonRawBody(true);
99
        }
100
101 1
        $systemModule = $request['system_modules_id'] ?? 0;
102 1
        $entityId = $request['entity_id'] ?? 0;
103
104 1
        $file->system_modules_id = $systemModule;
105 1
        $file->entity_id = $entityId;
106
107 1
        if (!$file->update()) {
108
            throw new UnprocessableEntityHttpException((string)current($file->getMessages()));
109
        }
110
111 1
        return $this->response($file);
112
    }
113
114
    /**
115
     * Set the validation for the files
116
     *
117
     * @return Validation
118
     */
119 1
    protected function validation(): Validation
120
    {
121 1
        $validator = new Validation();
122
123
        /**
124
         * @todo add validation for other file types, but we need to
125
         * look for a scalable way
126
         */
127
        $uploadConfig = [
128 1
            'maxSize' => '10M',
129
            'messageSize' => ':field exceeds the max filesize (:max)',
130
            'allowedTypes' => [
131
                'image/jpeg',
132
                'image/png',
133
            ],
134
            'messageType' => 'Allowed file types are :types',
135
        ];
136
137 1
        $validator->add(
138 1
            'file',
139 1
            new FileValidator($uploadConfig)
140
        );
141
142 1
        return $validator;
143
    }
144
145
    /**
146
     * Upload the document and save them to the filesystem
147
     *
148
     * @return array
149
     */
150 1
    protected function processFiles(): array
151
    {
152
        //@todo validate entity id
153 1
        $systemModule = $this->request->getPost('system_modules_id', 'int', '0');
154 1
        $entityId = $this->request->getPost('entity_id', 'int', '0');
155
156 1
        $validator = $this->validation();
157
158 1
        $files = [];
159 1
        foreach ($this->request->getUploadedFiles() as $file) {
160
            //validate this current file
161 1
            $errors = $validator->validate(['file' => [
162 1
                'name' => $file->getName(),
163 1
                'type' => $file->getType(),
164 1
                'tmp_name' => $file->getTempName(),
165 1
                'error' => $file->getError(),
166 1
                'size' => $file->getSize(),
167
            ]]);
168
169 1
            if (!defined('API_TESTS')) {
170
                if (count($errors)) {
171
                    foreach ($errors as $error) {
172
                        throw new UnprocessableEntityHttpException((string)$error);
173
                    }
174
                }
175
            }
176
177 1
            $filePath = Helper::generateUniqueName($file, $this->config->filesystem->local->path);
178 1
            $compleFilePath = $this->config->filesystem->local->path . $filePath;
179
180 1
            $this->di->get('filesystem', 'local')->writeStream($filePath, fopen($file->getTempName(), 'r'));
181
182
            // if user already had an image upload, detach said image from the user first before. Find image depending on system_module_id
183 1
            $existingImage = FileSystem::findFirst([
184 1
                'conditions' => 'system_modules_id = ?0 and apps_id = ?1 and companies_id = ?2 and users_id = ?3 and is_deleted = 0',
185 1
                'bind' => [$systemModule, $this->app->getId(), $this->userData->currentCompanyId(), $this->userData->getId()]
186
            ]);
187
188 1
            if (is_object($existingImage)) {
189
                $existingImage->users_id = 0;
190
                $existingImage->update();
191
            }
192
193 1
            $fileSystem = new FileSystem();
194 1
            $fileSystem->name = $file->getName();
195 1
            $fileSystem->system_modules_id = $systemModule;
196 1
            $fileSystem->entity_id = $entityId;
197 1
            $fileSystem->companies_id = $this->userData->currentCompanyId();
198 1
            $fileSystem->apps_id = $this->app->getId();
199 1
            $fileSystem->users_id = $this->userData->getId();
200 1
            $fileSystem->path = $compleFilePath;
201 1
            $fileSystem->url = $compleFilePath;
202 1
            $fileSystem->size = $file->getSize();
203
204 1
            if (!$fileSystem->save()) {
205
                throw new UnprocessableEntityHttpException((string)current($fileSystem->getMessages()));
206
            }
207
208 1
            $files[] = $fileSystem;
209
        }
210
211 1
        return $files;
212
    }
213
}
214