Passed
Push — master ( 166e8a...d3e685 )
by Nils
06:04
created

handleTaskStep()   C

Complexity

Conditions 13
Paths 10

Size

Total Lines 52
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 28
c 1
b 0
f 0
nc 10
nop 3
dl 0
loc 52
rs 6.6166

How to fix   Long Method    Complexity   

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
 * 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   
12
 * @file      background_tasks___items_handler.php
13
 * ---
14
 *
15
 * @author    Nils Laumaillé ([email protected])
16
 *
17
 * @copyright 2009-2024 Teampass.net
18
 *
19
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
20
 * ---
21
 *
22
 * @see       https://www.teampass.net
23
 */
24
25
use voku\helper\AntiXSS;
26
use TeampassClasses\NestedTree\NestedTree;
27
use TeampassClasses\SessionManager\SessionManager;
28
use Symfony\Component\HttpFoundation\Request;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Request. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
29
use TeampassClasses\Language\Language;
30
use EZimuel\PHPSecureSession;
31
use TeampassClasses\PerformChecks\PerformChecks;
32
33
34
// Load functions
35
require_once __DIR__.'/../sources/main.functions.php';
36
37
// init
38
loadClasses('DB');
39
$session = SessionManager::getSession();
40
$request = Request::createFromGlobals();
41
$lang = new Language();
42
43
// Load config if $SETTINGS not defined
44
try {
45
    include_once __DIR__.'/../includes/config/tp.config.php';
46
} catch (Exception $e) {
47
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
48
}
49
50
// Define Timezone
51
date_default_timezone_set(isset($SETTINGS['timezone']) === true ? $SETTINGS['timezone'] : 'UTC');
52
53
// Set header properties
54
header('Content-type: text/html; charset=utf-8');
55
header('Cache-Control: no-cache, no-store, must-revalidate');
56
error_reporting(E_ERROR);
57
// increase the maximum amount of time a script is allowed to run
58
set_time_limit($SETTINGS['task_maximum_run_time']);
59
60
// --------------------------------- //
61
62
require_once __DIR__.'/background_tasks___functions.php';
63
64
$tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
65
66
// Get PHP binary
67
$phpBinaryPath = getPHPBinary();
68
69
// log start
70
$logID = doLog('start', 'item_keys', (isset($SETTINGS['enable_tasks_log']) === true ? (int) $SETTINGS['enable_tasks_log'] : 0));
71
72
73
// Manage the tasks in queue.
74
// Task to treat selection is:
75
// 1- take first is_in_progress === 1
76
// 2- take first is_in_progress === 0 and finished_at === null
77
DB::debugmode(false);
78
$process_to_perform = DB::queryfirstrow(
79
    'SELECT *
80
    FROM ' . prefixTable('processes') . '
81
    WHERE is_in_progress = %i AND process_type IN ("item_copy", "new_item", "update_item", "item_update_create_keys")
82
    ORDER BY increment_id ASC',
83
    1
84
);
85
86
if (DB::count() > 0) {
87
    // handle tasks inside this process
88
    handleTask(
89
        $process_to_perform['increment_id'],
90
        json_decode($process_to_perform['arguments'], true),
91
        $SETTINGS,
92
    );
93
} else {
94
    // search for next process to handle
95
    $process_to_perform = DB::queryfirstrow(
96
        'SELECT *
97
        FROM ' . prefixTable('processes') . '
98
        WHERE is_in_progress = %i AND finished_at = "" AND process_type IN ("item_copy", "new_item", "update_item", "item_update_create_keys")
99
        ORDER BY increment_id ASC',
100
        0
101
    );
102
    //print_r($process_to_perform);
103
    if (DB::count() > 0) {
104
        // update DB - started_at
105
        DB::update(
106
            prefixTable('processes'),
107
            array(
108
                'started_at' => time(),
109
            ),
110
            'increment_id = %i',
111
            $process_to_perform['increment_id']
112
        );
113
114
        provideLog('[PROCESS][#'. $process_to_perform['increment_id'].'][START]', $SETTINGS);
115
        handleTask(
116
            $process_to_perform['increment_id'],
117
            json_decode($process_to_perform['arguments'], true),
118
            $SETTINGS,
119
            $process_to_perform['item_id']
120
        );
121
    } else {
122
123
    }
124
}
125
126
// log end
127
doLog('end', '', (isset($SETTINGS['enable_tasks_log']) === true ? (int) $SETTINGS['enable_tasks_log'] : 0), $logID);
128
129
// launch a new iterative process
130
$process_to_perform = DB::queryfirstrow(
131
    'SELECT *
132
    FROM ' . prefixTable('processes') . '
133
    WHERE is_in_progress = %i AND process_type IN ("item_copy", "new_item", "update_item", "item_update_create_keys")
134
    ORDER BY increment_id DESC',
135
    1
136
);
137
if (DB::count() > 0) {
138
    $process = new Symfony\Component\Process\Process([$phpBinaryPath, __FILE__]);
139
    $process->start();
140
    $process->wait();
141
}
142
143
/**
144
 * Handle the task
145
 *
146
 * @param int   $processId
147
 * @param array $ProcessArguments
148
 * @param array $SETTINGS
149
 *
150
 * @return bool
151
 */
152
function handleTask(int $processId, array $ProcessArguments, array $SETTINGS, int $itemId = null): bool
153
{
154
    provideLog('[PROCESS][#'. $processId.'][START]', $SETTINGS);
155
    $task_to_perform = DB::queryfirstrow(
156
        'SELECT *
157
        FROM ' . prefixTable('processes_tasks') . '
158
        WHERE process_id = %i AND finished_at IS NULL
159
        ORDER BY increment_id ASC',
160
        $processId
161
    );
162
163
    // get the process object
164
    //$processObject = json_decode($ProcessArguments['object_key'], true);
165
    
166
    if (DB::count() > 0) {
167
        // check if a linux process is not currently on going
168
        // if sub_task_in_progress === 1 then exit
169
        if ((int) $task_to_perform['sub_task_in_progress'] === 0) {
170
            // handle next task
171
            $args = json_decode($task_to_perform['task'], true);
172
            provideLog('[TASK][#'. $task_to_perform['increment_id'].'][START]Task '.$args['step'], $SETTINGS);
173
174
            // flag as in progress
175
            DB::update(
176
                prefixTable('processes'),
177
                array(
178
                    'updated_at' => time(),
179
                    'is_in_progress' => 1,
180
                ),
181
                'increment_id = %i',
182
                $processId
183
            );
184
185
            // flag task as on going
186
            if ((int) $args['index'] === 0) {
187
                DB::update(
188
                    prefixTable('processes_tasks'),
189
                    array(
190
                        'is_in_progress' => 1,
191
                    ),
192
                    'increment_id = %i',
193
                    $task_to_perform['increment_id']
194
                );
195
            }
196
197
            // flag sub task in progress as on going
198
            DB::update(
199
                prefixTable('processes_tasks'),
200
                array(
201
                    'sub_task_in_progress' => 1,
202
                ),
203
                'increment_id = %i',
204
                $task_to_perform['increment_id']
205
            );
206
207
            // handle the task step
208
            handleTaskStep($args, $ProcessArguments, $SETTINGS);
209
210
            // update the task status
211
            DB::update(
212
                prefixTable('processes_tasks'),
213
                array(
214
                    'sub_task_in_progress' => 0,    // flag sub task is no more in prgoress
215
                    'task' => json_encode(["status" => "Done"]),
216
                    'is_in_progress' => -1,
217
                    'finished_at' => time(),
218
                    'updated_at' => time(),
219
                ),
220
                'increment_id = %i',
221
                $task_to_perform['increment_id']
222
            );
223
224
            provideLog('[TASK]['.$args['step'].'] starting at '.$args['index'].' is done.', $SETTINGS);
225
226
            // are all tasks done?
227
            DB::query(
228
                'SELECT *
229
                FROM ' . prefixTable('processes_tasks') . '
230
                WHERE process_id = %i AND finished_at IS NULL',
231
                $processId
232
            );
233
            if (DB::count() === 0) {
234
                // all tasks are done
235
                provideLog('[PROCESS]['.$processId.'][FINISHED]', $SETTINGS);
236
                DB::debugmode(false);
237
                DB::update(
238
                    prefixTable('processes'),
239
                    array(
240
                        'finished_at' => time(),
241
                        'is_in_progress' => -1,
242
                        'arguments' => json_encode([
243
                            'new_user_id' => isset($ProcessArguments['new_user_id']) === true ? $ProcessArguments['new_user_id'] : '',
244
                        ])
245
                    ),
246
                    'increment_id = %i',
247
                    $processId
248
                );
249
250
                // if item was being updated then remove the edition lock
251
                if (is_null($itemId) === false) {
252
                    DB::delete(prefixTable('items_edition'), 'item_id = %i', $itemId);
253
                }
254
            }
255
            return false;
256
257
        } else {
258
            // Task is currently being in progress by another server process
259
            provideLog('[TASK][#'. $task_to_perform['increment_id'].'][WARNING] Similar task already being processes', $SETTINGS);
260
            return false;
261
        }
262
    } else {
263
        // no more task to perform
264
        provideLog('[PROCESS]['.$processId.'][FINISHED]', $SETTINGS);
265
        DB::update(
266
            prefixTable('processes'),
267
            array(
268
                'finished_at' => time(),
269
                'is_in_progress' => -1,
270
                'arguments' => json_encode([
271
                    'item_id' => isset($ProcessArguments['item_id']) === true ? $ProcessArguments['item_id'] : '',
272
                ])
273
            ),
274
            'increment_id = %i',
275
            $processId
276
        );
277
278
        // if item was being updated then remove the edition lock
279
        if (is_null($itemId) === false) {
280
            DB::delete(prefixTable('items_edition'), 'item_id = %i', $itemId);
281
        }
282
    }
283
    return false;
284
}
285
286
/**
287
 * Handle the task step
288
 *
289
 * @param array $args
290
 * @param array $ProcessArguments
291
 * @param array $SETTINGS
292
 *
293
 * @return void
294
 */
295
function handleTaskStep(
296
    array $args,
297
    array $ProcessArguments,
298
    array $SETTINGS
299
)
300
{
301
    // perform the task step "create_users_files_key"
302
    if ($args['step'] === 'create_users_files_key') {
303
        // Loop on all files for this item
304
        // and encrypt them for each user
305
        if (WIP === true) provideLog('[DEBUG] '.print_r($args['files_keys'], true), $SETTINGS);
306
        foreach($args['files_keys'] as $file) {
307
            storeUsersShareKey(
308
                prefixTable('sharekeys_items'),
309
                0,
310
                -1,
311
                (int) $file['object_id'],
312
                (string) $file['object_key'],
313
                false,
314
                false,
315
                [],
316
                array_key_exists('all_users_except_id', $ProcessArguments) === true ? $ProcessArguments['all_users_except_id'] : -1,
317
            );
318
        }
319
    } elseif ($args['step'] === 'create_users_fields_key') {
320
        // Loop on all encrypted fields for this item
321
        // and encrypt them for each user
322
        if (WIP === true) provideLog('[DEBUG] '.print_r($args, true), $SETTINGS);
323
        foreach($args['fields_keys'] as $field) {
324
            storeUsersShareKey(
325
                prefixTable('sharekeys_fields'),
326
                0,
327
                -1,
328
                (int) $field['object_id'],
329
                (string) $field['object_key'],
330
                false,
331
                false,
332
                [],
333
                array_key_exists('all_users_except_id', $ProcessArguments) === true ? $ProcessArguments['all_users_except_id'] : -1,
334
            );
335
        }
336
    } elseif ($args['step'] === 'create_users_pwd_key') {
337
        storeUsersShareKey(
338
            prefixTable('sharekeys_items'),
339
            0,
340
            -1,
341
            (int) $ProcessArguments['item_id'],
342
            (string) array_key_exists('pwd', $ProcessArguments) === true ? $ProcessArguments['pwd'] : (array_key_exists('object_key', $ProcessArguments) === true ? $ProcessArguments['object_key'] : ''),
0 ignored issues
show
introduced by
The condition (string)array_key_exists...cessArguments) === true is always false.
Loading history...
343
            false,
344
            false,
345
            [],
346
            array_key_exists('all_users_except_id', $ProcessArguments) === true ? $ProcessArguments['all_users_except_id'] : -1
347
        );
348
    }
349
}