Completed
Pull Request — master (#6)
by
unknown
02:04
created

MakeUser::handle()   F

Complexity

Conditions 17
Paths 1434

Size

Total Lines 75
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 17

Importance

Changes 0
Metric Value
dl 0
loc 75
ccs 44
cts 44
cp 1
rs 2.309
c 0
b 0
f 0
cc 17
eloc 46
nc 1434
nop 0
crap 17

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
namespace Dyrynda\Artisan\Console\Commands;
4
5
use Exception;
6
use SplFileInfo;
7
use Illuminate\Console\Command;
8
use Illuminate\Support\Facades\Password;
9
use Dyrynda\Artisan\Exceptions\MakeUserException;
10
use Dyrynda\Artisan\Exceptions\ImportFileException;
11
use Dyrynda\Artisan\BulkImport\BulkImportFileHandler;
12
13
class MakeUser extends Command
14
{
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'make:user
21
                                {--email=       : Set the email for the new user}
22
                                {--name=        : Set the name for the new user}
23
                                {--password=    : The password to set for the new user}
24
                                {--send-reset   : Send a password reset email for the new user}
25
                                {--fields=      : Additional database fields to set on the user}
26
                                {--force        : Create the user model circumventing guarded fields}
27
                                {--import-file= : Relative path and filename for a file to import users from. File name MUST contain the extension representing the type of file (Ex: ./path/to/file.csv)}
28
    ';
29
30
    /**
31
     * The console command description.
32
     *
33
     * @var string
34
     */
35
    protected $description = 'Create new application users';
36
37
    /**
38
     * Execute the console command.
39
     *
40
     * Handle creation of the new application user.
41
     *
42
     * @return void
43
     */
44 27
    public function handle()
45
    {
46 27
        $dataToProcess = [];
47
48
        try {
49 27
            $bulkImportFile = is_string($this->option('import-file')) ? $this->fileHandlerFactory($this->option('import-file')) : null;
50
51 21
            $modelCommand = $this->option('force') ? 'forceCreate' : 'create';
52
53 21
            if (! is_null($bulkImportFile)) {
54 12
                $dataToProcess = $bulkImportFile->getData();
55
56 12
                $sendReset = false;
57
58 12
                if (! in_array('password', array_keys($dataToProcess[0])) || $this->option('send-reset')) {
59 4
                    $sendReset = true;
60
                }
61 12
                $dataToProcess = $this->setPasswords($dataToProcess);
62
            } else {
63 9
                $email = $this->option('email');
64 9
                $name = $this->option('name') ?: '';
65 9
                $password = bcrypt($this->option('password') ?: str_random(32));
66 9
                $sendReset = ! $this->option('password') || $this->option('send-reset');
67
68 9
                $dataToProcess[0] = [
69 9
                    'email' => $email,
70 9
                    'name' => $name,
71 9
                    'password' => $password,
72
                ];
73
            }
74
75 21
            foreach ($dataToProcess as $dataRow) {
76 21
                $email = $dataRow['email'] ?? null;
77
78 21
                app('db')->beginTransaction();
79
80 21
                $this->validateEmail($email);
81
82 17
                app(config('auth.providers.users.model'))->{$modelCommand}(array_merge(
83 17
                    $dataRow,
84 17
                    $bulkImportFile ? [] : $this->additionalFields()
85
                ));
86
87 17
                if ($sendReset) {
88 7
                    Password::sendResetLink(compact('email'));
89
                }
90
91 17
                app('db')->commit();
92
            }
93
94 17
            if (count($dataToProcess)) {
95 17
                $createdMessage = $bulkImportFile
96 10
                    ? 'Created '.count($dataToProcess).' user(s).'
97 17
                    : "Created new user for email {$email}.";
0 ignored issues
show
Bug introduced by
The variable $email does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
98
99 17
                $passwordResetMessage = $bulkImportFile
100 10
                    ? 'Sent password reset emails.'
101 17
                    : "Sent password reset email to {$email}.";
102
103 17
                $this->info($createdMessage);
104
105 17
                if ($sendReset) {
106 17
                    $this->info($passwordResetMessage);
107
                }
108
            } else {
109 17
                $this->error('The user(s) were not created');
110
            }
111 10
        } catch (Exception $e) {
112 10
            $this->error($e->getMessage());
113
114 10
            $this->error('The user(s) were not created');
115
116 10
            app('db')->rollBack();
117
        }
118 27
    }
119
120
    /**
121
     * Determine if the given email address already exists.
122
     *
123
     * @param  string  $email
124
     * @return void
125
     *
126
     * @throws \Dyrynda\Artisan\Exceptions\MakeUserException
127
     */
128 21
    private function validateEmail($email)
129
    {
130 21
        if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
131 3
            throw MakeUserException::invalidEmail($email);
132
        }
133
134 18
        if (app(config('auth.providers.users.model'))->where('email', $email)->exists()) {
135 1
            throw MakeUserException::emailExists($email);
136
        }
137 17
    }
138
139
    /**
140
     * Return any additional database fields passed by the --fields option.
141
     *
142
     * @return array
143
     */
144 7
    private function additionalFields()
145
    {
146 7
        if (! $this->option('fields')) {
147 4
            return [];
148
        }
149
150 3
        return collect(explode(',', $this->option('fields')))->mapWithKeys(function ($field) {
151 3
            list($column, $value) = explode(':', $field);
152
153 3
            return [trim($column) => $this->normaliseValue($value)];
154 3
        })->toArray();
155
    }
156
157
    /**
158
     * Normalise the given (database) field input value.
159
     *
160
     * @param  mixed  $value
161
     * @return mixed
162
     */
163 3
    private function normaliseValue($value)
164
    {
165 3
        if ($value == 'null') {
166 1
            return;
167
        }
168
169 2 View Code Duplication
        if (in_array($value, [1, 'true', true], true)) {
170 1
            return true;
171
        }
172
173 1 View Code Duplication
        if (in_array($value, [0, 'false', false], true)) {
174 1
            return false;
175
        }
176
177 1
        return trim($value);
178
    }
179
180
    /**
181
     * Create file handler objects.
182
     *
183
     * @param string  $path
184
     * @return BulkImportFileHandler
185
     *
186
     * @throws \Dyrynda\Artisan\Exceptions\ImportFileException
187
     */
188 18
    private function fileHandlerFactory($path) : BulkImportFileHandler
189
    {
190 18
        if (! strpos($path, '.')) {
191 1
            throw ImportFileException::noExtension();
192
        }
193
194 17
        $file = new SplFileInfo($path);
195
196 17
        if (! class_exists($class = '\\Dyrynda\\Artisan\\BulkImport\\Handlers\\'.studly_case($file->getExtension()))) {
197 1
            throw ImportFileException::unsupported($file->getExtension());
198
        }
199
200 16
        return new $class($file);
201
    }
202
203
    /**
204
     * Add default password to data.
205
     *
206
     * @param array  $data
207
     * @return array
208
     */
209
    private function setPasswords($data)
210
    {
211 12
        return collect($data)->map(function ($row) {
212 12
            return array_merge(
213 12
                $row,
214 12
                ! isset($row['password']) ? ['password' => str_random(32)] : ['password' => bcrypt($row['password'])]
215
            );
216 12
        })->all();
217
    }
218
}
219