Passed
Push — dev5 ( 23c1c8...570ed9 )
by Ron
08:28
created

databaseCheck::verifyFilesExist()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 7
nop 0
dl 0
loc 32
ccs 0
cts 18
cp 0
crap 56
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace App\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\Log;
7
use Illuminate\Support\Facades\File;
8
use Illuminate\Support\Facades\Storage;
9
10
use App\User;
11
use App\Files;
12
use App\TechTipFiles;
13
use App\UserSettings;
14
use App\CustomerFiles;
15
use App\FileLinkFiles;
16
use App\Domains\Maintenance\DatabaseCheck as MaintenanceDatabaseCheck;
17
18
class databaseCheck extends Command
19
{
20
    protected $signature = 'tb-dbcheck {--fix : Automatically fix any errors that arrise}';
21
    protected $fix = false;
22
    protected $description = 'Verify database and file structure has no errors';
23
24 2
    public function __construct()
25
    {
26 2
        parent::__construct();
27
28 2
    }
29
30
    public function handle()
31
    {
32
        //  Determine if fix option is enabled
33
        if($this->option('fix'))
34
        {
35
            $this->fix = true;
36
        }
37
        //  Extend the amount of time the script is allowed to run
38
        ini_set('max_execution_time', 600);  //  600 seconds = 10 minutes
39
40
        //  Begin check
41
        $fixStr = $this->fix ? 'on' : 'off';
42
        $this->line('');
43
        $this->info('Running Database Check...');
44
        $this->line('');
45
        Log::alert('The database check has been initiated.  Fix option is set to '.$fixStr);
46
47
        $this->checkUsers();
48
        $this->checkForeignKeys();
49
        $this->verifyFilesExist();
50
        $this->checkForStraglerFiles();
51
        $this->checkForEmptyFolders();
52
53
        $this->line('');
54
        $this->info('Database Check Completed');
55
    }
56
57
    //  User check will count users and administrators and verify each user has a proper settings table
58
    protected function checkUsers()
59
    {
60
        $activeUsers   = User::all()->count();
61
        $inactiveUsers = User::onlyTrashed()->count();
62
63
        //  All users allowed to login
64
        $str = 'Current Active Users........................... '.$activeUsers;
65
        $this->line($str);
66
        Log::notice($str);
67
68
        //  All users that have been disabled
69
        $str = 'Current Inactive Users......................... '.$inactiveUsers;
70
        $this->line($str);
71
        Log::notice($str);
72
73
        //  All Active Installers
74
        $instArr    = [];
75
        $installers = User::where('role_id', 1)->get();
76
        foreach($installers as $ins)
77
        {
78
            $instArr[] = [
79
                'user_id'   => $ins->user_id,
80
                'username'  => $ins->username,
81
                'full_name' => $ins->full_name,
82
            ];
83
        }
84
        $this->line('');
85
        $this->line('Active Installers:');
86
        $this->table(['User ID', 'Username', 'Full Name'], $instArr);
87
        Log::notice('Current Active Installers - ', $instArr);
88
89
        //  All Active Administrators
90
        $adminArr    = [];
91
        $administrators = User::where('role_id', 2)->get();
92
        foreach($administrators as $adm)
93
        {
94
            $adminArr[] = [
95
                'user_id'   => $adm->user_id,
96
                'username'  => $adm->username,
97
                'full_name' => $adm->full_name,
98
            ];
99
        }
100
        $this->line('');
101
        $this->line('Active Administrators:');
102
        $this->table(['User ID', 'Username', 'Full Name'], $adminArr);
103
        Log::notice('Current Active Administrators - ', $adminArr);
104
105
        //  Validate that each user has a user_settings entry
106
        $this->line('');
107
        $this->line('Validating User Settings');
108
        $userList   = User::all();
109
        foreach($userList as $user)
110
        {
111
            $row = UserSettings::where('user_id', $user->user_id)->count();
112
            if($row != 1)
113
            {
114
                $str = 'User '.$user->full_name.' missing Settings Table';
115
                $this->error($str);
116
                Log::error($str);
117
118
                if($this->fix)
119
                {
120
                    UserSettings::create([
121
                        'user_id' => $user->user_id,
122
                    ]);
123
                }
124
            }
125
        }
126
    }
127
128
    //  Verify that all foreign keys point to valid database entries
129
    protected function checkForeignKeys()
130
    {
131
        $tableList = [
132
            'users',
133
            'user_role_permissions',
134
            'user_logins',
135
            'tech_tips',
136
            'tech_tip_systems',
137
            'tech_tip_files',
138
            'tech_tip_favs',
139
            'tech_tip_comments',
140
            'system_types',
141
            'system_data_fields',
142
            'file_links',
143
            'file_link_files',
144
            'customer_systems',
145
            'customer_system_data',
146
            'customer_notes',
147
            'customer_files',
148
            'customer_favs',
149
            'customer_contacts',
150
            'customer_contact_phones',
151
        ];
152
153
        $dbObj = new MaintenanceDatabaseCheck($this->fix);
154
        $this->line('Running Foreign Key Check');
155
156
        foreach($tableList as $table)
157
        {
158
            $valid = $dbObj->execute($table);
159
            if(!$valid)
160
            {
161
                $str = 'Foreign Key Check for '.$table.' failed';
162
                $this->error($str);
163
                Log::error($str);
164
            }
165
        }
166
    }
167
168
    //  Verify that all files listed in the files table actually exist
169
    protected function verifyFilesExist()
170
    {
171
        $this->line('Checking to see if all files are present');
172
        $fileList = Files::all();
173
174
        foreach($fileList as $file)
175
        {
176
            if(!Storage::exists($file->file_link.$file->file_name))
177
            {
178
                $str = 'File '.$file->file_link.$file->file_name.' missing';
179
                $this->error($str);
180
                Log::error($str);
181
182
                if($this->fix)
183
                {
184
                    $fileData = Files::where('file_id', $file->file_id)->with(['CustomerFiles', 'FileLinkFiles', 'TechTipFiles'])->first();
185
                    Log::notice('Deleted file ID '.$file->file_id.' from database as it does not exist.  File Data - ', array($fileData));
186
187
                    if(isset($fileData->CustomerFiles->cust_file_id))
188
                    {
189
                        CustomerFiles::find($fileData->CustomerFiles->cust_file_id)->delete();
190
                    }
191
                    else if(isset($fileData->FileLinkFiles->link_file_id))
192
                    {
193
                        FileLinkFiles::find($fileData->FileLinkFiles->link_file_id)->delete();
194
                    }
195
                    else if(isset($fileData->TechTipFiles->tip_file_id))
196
                    {
197
                        TechTipFiles::find($fileData->TechTipFiles->tip_file_id)->delete();
198
                    }
199
200
                    $fileData->delete();
201
                }
202
            }
203
        }
204
    }
205
206
    //  Check for files that exist, but are not listed in the database
207
    protected function checkForStraglerFiles()
208
    {
209
        //  Pull a list of all files in the local disk
210
        $fileList = Storage::allFiles();
211
        foreach($fileList as $file)
212
        {
213
            $parts = pathinfo($file);
214
            if($parts['dirname'] != 'chunks')
215
            {
216
                $dbData = Files::where('file_name', $parts['basename'])->first();
217
                if(!$dbData)
218
                {
219
                    $str = 'File '.$file.' does not have a matching database record';
220
                    Log::notice($str);
221
                    $this->error($str);
222
                    if($this->fix)
223
                    {
224
                        Storage::delete($file);
225
                        Log::alert('Deleted file - '.$file);
226
                    }
227
                }
228
            }
229
        }
230
    }
231
232
    //  Check the local disk to see if any of the folders are empty and can be deleted
233
    protected function checkForEmptyFolders()
234
    {
235
        $this->line('Checking for empty directories');
236
        $directories = Storage::allDirectories();
237
238
        foreach($directories as $dir)
239
        {
240
            $fileCount = count(Storage::allFiles($dir));
241
242
            // dd($fileCount);
243
            if($fileCount == 0)
244
            {
245
                $str = 'Directory '.$dir.' is empty and can be deleted';
246
                $this->error($str);
247
                Log::notice($str);
248
                if($this->fix)
249
                {
250
                    Storage::deleteDirectory($dir);
251
                    Log::notice('Deleted Directory '.$dir);
252
                }
253
            }
254
        }
255
    }
256
}
257