ItemController   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 162
c 0
b 0
f 0
dl 0
loc 282
rs 9.2
wmc 40

4 Methods

Rating   Name   Duplication   Size   Complexity  
B inFoldersAction() 0 81 9
B createAction() 0 71 7
C getAction() 0 62 12
C checkNewItemData() 0 35 12

How to fix   Complexity   

Complex Class

Complex classes like ItemController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ItemController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Teampass - a collaborative passwords manager.
4
 * ---
5
 * This library is distributed in the hope that it will be useful,
6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8
 * ---
9
 *
10
 * @project   Teampass
11
 * @version    API
12
 *
13
 * @file      ItemControler.php
14
 * ---
15
 *
16
 * @author    Nils Laumaillé ([email protected])
17
 *
18
 * @copyright 2009-2025 Teampass.net
19
 *
20
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
21
 * ---
22
 *
23
 * @see       https://www.teampass.net
24
 */
25
26
use Symfony\Component\HttpFoundation\Request AS symfonyRequest;
27
28
class ItemController extends BaseController
29
{
30
31
32
    /**
33
     * Manage case inFolder - get items inside an array of folders
34
     *
35
     * @param array $userData
36
     */
37
    public function inFoldersAction(array $userData): void
38
    {
39
        $request = symfonyRequest::createFromGlobals();
40
        $requestMethod = $request->getMethod();
41
        $strErrorDesc = $responseData = $strErrorHeader = '';
42
43
        // get parameters
44
        $arrQueryStringParams = $this->getQueryStringParams();
45
46
        if (strtoupper($requestMethod) === 'GET') {
47
            // define WHERE clause
48
            $sqlExtra = '';
49
            if (empty($userData['folders_list']) === false) {
50
                $userData['folders_list'] = explode(',', $userData['folders_list']);
51
            } else {
52
                $userData['folders_list'] = [];
53
            }
54
55
            // SQL where clause with folders list
56
            if (isset($arrQueryStringParams['folders']) === true) {
57
                // convert the folders to an array
58
                $arrQueryStringParams['folders'] = explode(',', str_replace( array('[',']') , ''  , $arrQueryStringParams['folders']));
59
60
                // ensure to only use the intersection
61
                $foldersList = implode(',', array_intersect($arrQueryStringParams['folders'], $userData['folders_list']));
62
63
                // build sql where clause
64
                if (!empty($foldersList)) {
65
                    // build sql where clause
66
                    $sqlExtra = ' WHERE id_tree IN ('.$foldersList.')';
67
                } else {
68
                    // Send error
69
                    $this->sendOutput(
70
                        json_encode(['error' => 'Folders are mandatory']),
71
                        ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
72
                    );
73
                }
74
            } else {
75
                // Send error
76
                $this->sendOutput(
77
                    json_encode(['error' => 'Folders are mandatory']),
78
                    ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
79
                );
80
            }
81
82
            // SQL LIMIT
83
            $intLimit = 0;
84
            if (isset($arrQueryStringParams['limit']) === true) {
85
                $intLimit = $arrQueryStringParams['limit'];
86
            }
87
88
            // send query
89
            try {
90
                $itemModel = new ItemModel();
91
92
                $arrItems = $itemModel->getItems($sqlExtra, $intLimit, $userData['private_key'], $userData['id']);
93
                if (!empty($arrItems)) {
94
                    $responseData = json_encode($arrItems);
95
                } else {
96
                    $strErrorDesc = 'No content for this label';
97
                    $strErrorHeader = 'HTTP/1.1 204 No Content';
98
                }
99
            } catch (Error $e) {
100
                $strErrorDesc = $e->getMessage().'. Something went wrong! Please contact support.4';
101
                $strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
102
            }
103
        } else {
104
            $strErrorDesc = 'Method not supported';
105
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
106
        }
107
108
        // send output
109
        if (empty($strErrorDesc) === true) {
110
            $this->sendOutput(
111
                $responseData,
112
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
113
            );
114
        } else {
115
            $this->sendOutput(
116
                json_encode(['error' => $strErrorDesc]), 
117
                ['Content-Type: application/json', $strErrorHeader]
118
            );
119
        }
120
    }
121
    //end InFoldersAction()
122
123
    private function checkNewItemData(array $arrQueryStringParams, array $userData): array
124
    {
125
        if (isset($arrQueryStringParams['label']) === true
126
            && isset($arrQueryStringParams['folder_id']) === true
127
            && isset($arrQueryStringParams['password']) === true
128
            && isset($arrQueryStringParams['login']) === true
129
            && isset($arrQueryStringParams['email']) === true
130
            && isset($arrQueryStringParams['url']) === true
131
            && isset($arrQueryStringParams['tags']) === true
132
            && isset($arrQueryStringParams['anyone_can_modify']) === true
133
        ) {
134
            //
135
            if (in_array($arrQueryStringParams['folder_id'], $userData['folders_list']) === false && $userData['user_can_create_root_folder'] === 0) {
136
                return [
137
                    'error' => true,
138
                    'strErrorDesc' => 'User is not allowed in this folder',
139
                    'strErrorHeader' => 'HTTP/1.1 401 Unauthorized',
140
                ];
141
            } else if (empty($arrQueryStringParams['label']) === true) {
142
                return [
143
                    'error' => true,
144
                    'strErrorDesc' => 'Label is mandatory',
145
                    'strErrorHeader' => 'HTTP/1.1 401 Expected parameters not provided',
146
                ];
147
            } else {
148
                return [
149
                    'error' => false,
150
                ];
151
            }
152
        }
153
154
        return [
155
            'error' => true,
156
            'strErrorDesc' => 'All fields have to be provided even if empty (refer to documentation).',
157
            'strErrorHeader' => 'HTTP/1.1 401 Expected parameters not provided',
158
        ];
159
    }
160
161
    /**
162
     * Manage case Add
163
     *
164
     * @param array $userData
165
     */
166
    public function createAction(array $userData)
167
    {
168
        $request = symfonyRequest::createFromGlobals();
169
        $requestMethod = $request->getMethod();
170
        $strErrorDesc = $strErrorHeader = $responseData = '';
171
172
        if (strtoupper($requestMethod) === 'POST') {
173
            // Is user allowed to create a folder
174
            // We check if allowed_to_create
175
            if ((int) $userData['allowed_to_create'] !== 1) {
176
                $strErrorDesc = 'User is not allowed to create an item';
177
                $strErrorHeader = 'HTTP/1.1 401 Unauthorized';
178
            } else {
179
                if (empty($userData['folders_list']) === false) {
180
                    $userData['folders_list'] = explode(',', $userData['folders_list']);
181
                } else {
182
                    $userData['folders_list'] = [];
183
                }
184
185
                // get parameters
186
                $arrQueryStringParams = $this->getQueryStringParams();
187
188
                // Check that the parameters are indeed an array before using them
189
                if (is_array($arrQueryStringParams)) {
190
                    // check parameters
191
                    $arrCheck = $this->checkNewItemData($arrQueryStringParams, $userData);
192
193
                    if ($arrCheck['error'] === true) {
194
                        $strErrorDesc = $arrCheck['strErrorDesc'];
195
                        $strErrorHeader = $arrCheck['strErrorHeader'];
196
                    } else {
197
                        // launch
198
                        $itemModel = new ItemModel();
199
                        $ret = $itemModel->addItem(
200
                            (int) $arrQueryStringParams['folder_id'],
201
                            (string) $arrQueryStringParams['label'],
202
                            (string) $arrQueryStringParams['password'],
203
                            (string) $arrQueryStringParams['description'],
204
                            (string) $arrQueryStringParams['login'],
205
                            (string) $arrQueryStringParams['email'],
206
                            (string) $arrQueryStringParams['url'],
207
                            (string) $arrQueryStringParams['tags'],
208
                            (string) $arrQueryStringParams['anyone_can_modify'],
209
                            (string) $arrQueryStringParams['icon'],
210
                            (int) $userData['id'],
211
                            (string) $userData['username'],
212
                        );
213
                        $responseData = json_encode($ret);
214
                    }
215
                
216
                } else {
217
                    // Gérer le cas où les paramètres ne sont pas un tableau
218
                    $strErrorDesc = 'Data not consistent';
219
                    $strErrorHeader = 'Expected array, received ' . gettype($arrQueryStringParams);
220
                }
221
            }
222
        } else {
223
            $strErrorDesc = 'Method not supported';
224
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
225
        }
226
227
        // send output
228
        if (empty($strErrorDesc) === true) {
229
            $this->sendOutput(
230
                $responseData,
231
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
232
            );
233
        } else {
234
            $this->sendOutput(
235
                json_encode(['error' => $strErrorDesc]),
236
                ['Content-Type: application/json', $strErrorHeader]
237
            );
238
        }
239
    }
240
    //end addAction()
241
242
243
    /**
244
     * Manage case get - get an item
245
     *
246
     * @param array $userData
247
     */
248
    public function getAction(array $userData): void
249
    {
250
        
251
        $request = symfonyRequest::createFromGlobals();
252
        $requestMethod = $request->getMethod();
253
        $strErrorDesc = '';
254
        $sqlExtra = '';
255
        $responseData = '';
256
        $strErrorHeader = '';
257
        $sql_constraint = ' AND (i.id_tree IN ('.$userData['folders_list'].')';
258
        if (!empty($userData['restricted_items_list'])) {
259
            $sql_constraint .= 'OR i.id IN ('.$userData['restricted_items_list'].')';
260
        }
261
        $sql_constraint .= ')';
262
263
        // get parameters
264
        $arrQueryStringParams = $this->getQueryStringParams();
265
266
        if (strtoupper($requestMethod) === 'GET') {
267
            // SQL where clause with item id
268
            if (isset($arrQueryStringParams['id']) === true) {
269
                // build sql where clause by ID
270
                $sqlExtra = ' WHERE i.id = '.$arrQueryStringParams['id'] . $sql_constraint;
271
            } else if (isset($arrQueryStringParams['label']) === true) {
272
                // build sql where clause by LABEL
273
                $sqlExtra = ' WHERE i.label '.(isset($arrQueryStringParams['like']) === true && (int) $arrQueryStringParams['like'] === 1 ? ' LIKE '.$arrQueryStringParams['label'] : ' = '.$arrQueryStringParams['label']) . $sql_constraint;
274
            } else if (isset($arrQueryStringParams['description']) === true) {
275
                // build sql where clause by LABEL
276
                $sqlExtra = ' WHERE i.description '.(isset($arrQueryStringParams['like']) === true && (int) $arrQueryStringParams['like'] === 1 ? ' LIKE '.$arrQueryStringParams['description'] : ' = '.$arrQueryStringParams['description']).$sql_constraint;
277
            } else {
278
                // Send error
279
                $this->sendOutput(
280
                    json_encode(['error' => 'Item id, label or description is mandatory']),
281
                    ['Content-Type: application/json', 'HTTP/1.1 401 Expected parameters not provided']
282
                );
283
            }
284
285
            // send query
286
            try {
287
                $itemModel = new ItemModel();
288
289
                $arrItems = $itemModel->getItems($sqlExtra, 0, $userData['private_key'], $userData['id']);
290
                $responseData = json_encode($arrItems);
291
            } catch (Error $e) {
292
                $strErrorDesc = $e->getMessage().'. Something went wrong! Please contact support.6';
293
                $strErrorHeader = 'HTTP/1.1 500 Internal Server Error';
294
            }
295
        } else {
296
            $strErrorDesc = 'Method not supported';
297
            $strErrorHeader = 'HTTP/1.1 422 Unprocessable Entity';
298
        }
299
300
        // send output
301
        if (empty($strErrorDesc) === true) {
302
            $this->sendOutput(
303
                $responseData,
304
                ['Content-Type: application/json', 'HTTP/1.1 200 OK']
305
            );
306
        } else {
307
            $this->sendOutput(
308
                json_encode(['error' => $strErrorDesc]), 
309
                ['Content-Type: application/json', $strErrorHeader]
310
            );
311
        }
312
    }
313
    //end getAction() 
314
}
315