1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Epesi\Core\System; |
4
|
|
|
|
5
|
|
|
use Epesi\Core\System\Seeds\Form; |
6
|
|
|
use atk4\ui\jsExpression; |
7
|
|
|
use atk4\ui\Wizard; |
8
|
|
|
use Illuminate\Support\Facades\Artisan; |
9
|
|
|
use Epesi\Core\System\Integration\Modules\Concerns\HasAdminMode; |
10
|
|
|
use Illuminate\Support\Facades\App; |
11
|
|
|
use Epesi\Core\System\Integration\Modules\ModuleManager; |
12
|
|
|
use Epesi\Base\User\Database\Models\User; |
|
|
|
|
13
|
|
|
use Illuminate\Support\Facades\Hash; |
14
|
|
|
|
15
|
|
|
class SystemInstallWizard extends Wizard |
16
|
|
|
{ |
17
|
|
|
use HasAdminMode; |
18
|
|
|
|
19
|
|
|
public function init() |
20
|
|
|
{ |
21
|
|
|
parent::init(); |
22
|
|
|
|
23
|
|
|
$this->setAdminMode()->performInstallationSteps(); |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
public function performInstallationSteps() |
27
|
|
|
{ |
28
|
|
|
$this->addStep(__('Welcome'), [__CLASS__, 'stepWelcome']); |
29
|
|
|
|
30
|
|
|
$this->addStep([__('License'), 'icon'=>'id card', 'description'=>__('Accept license conditions')], [__CLASS__, 'stepLicense']); |
31
|
|
|
|
32
|
|
|
$this->addStep([__('Database'), 'icon'=>'database', 'description'=>__('Database connection settings')], [__CLASS__, 'stepDatabase']); |
33
|
|
|
|
34
|
|
|
$this->addStep([__('Environment'), 'icon'=>'configure', 'description'=>__('Check environment')], [__CLASS__, 'stepEnvironment']); |
35
|
|
|
|
36
|
|
|
$this->addStep([__('Super Admin'), 'icon'=>'user', 'description'=>__('Create first user')], [__CLASS__, 'stepUser']); |
37
|
|
|
|
38
|
|
|
$this->addStep([__('Complete'), 'icon'=>'check', 'description'=>__('Complete installation')], [__CLASS__, 'stepInstallationCompleted']); |
39
|
|
|
|
40
|
|
|
// below step is skipped because of redirecting to 'login' path once system installed |
41
|
|
|
// see Epesi\Core\Controllers\SystemController::install |
42
|
|
|
$this->addFinish([__CLASS__, 'stepInstallationCompleted']); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
public function addRequiredNote() |
46
|
|
|
{ |
47
|
|
|
$this->add(['View', __('denotes required field'), 'class' => ['required-note']])->setStyle(['float' => 'right']); |
48
|
|
|
|
49
|
|
|
eval_css(' |
50
|
|
|
.required-note::before { |
51
|
|
|
margin: 0 .2em 0 0; |
52
|
|
|
content: \'*\'; |
53
|
|
|
color: #db2828; |
54
|
|
|
} |
55
|
|
|
'); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
public function setForm($form) |
59
|
|
|
{ |
60
|
|
|
$this->buttonNext->on('click', $form->js()->submit()); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public static function stepWelcome($wizard) |
64
|
|
|
{ |
65
|
|
|
$columns = $wizard->add('Columns'); |
66
|
|
|
|
67
|
|
|
$column = $columns->addColumn(); |
68
|
|
|
$column->add(['Message', __('Thank you for downloading EPESI!')])->text |
69
|
|
|
->addParagraph(__('This wizard will guide you though the process of setting up your new CRM / ERP installation')) |
70
|
|
|
->addParagraph(__('Select the installation language and click NEXT button to proceed to next step')); |
71
|
|
|
|
72
|
|
|
$column = $columns->addColumn(); |
73
|
|
|
|
74
|
|
|
if (! function_exists('locale_get_display_language')) { |
75
|
|
|
$column->addClass('middle aligned'); |
76
|
|
|
$column->add(['Label', __('Install php-intl extension to enable language selection!'), 'class' => ['red']]); |
77
|
|
|
|
78
|
|
|
return; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
$systemLanguages = app()->make(\JoeDixon\Translation\Drivers\Translation::class)->allLanguages()->toArray(); |
82
|
|
|
|
83
|
|
|
$values = array_intersect_key(self::getDisplayLanguages(), $systemLanguages); |
84
|
|
|
|
85
|
|
|
$form = $column->add(new Form()); |
86
|
|
|
|
87
|
|
|
$form->addField('language', ['DropDown', 'values' => $values, 'caption' => __('Select Language'), 'iconLeft' => 'globe'], ['required'=>true])->set($wizard->recall('language', 'en')); |
88
|
|
|
|
89
|
|
|
$form->onSubmit(function ($form) use ($wizard) { |
90
|
|
|
$wizard->memorize('language', $form->model['language']); |
91
|
|
|
|
92
|
|
|
App::setLocale($form->model['language']); |
93
|
|
|
|
94
|
|
|
return $wizard->jsNext(); |
95
|
|
|
}); |
96
|
|
|
|
97
|
|
|
$wizard->setForm($form); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public static function stepLicense($wizard) |
101
|
|
|
{ |
102
|
|
|
$columns = $wizard->add('Columns'); |
103
|
|
|
$column = $columns->addColumn(); |
104
|
|
|
|
105
|
|
|
$license = $column->add(['View', 'defaultTemplate' => 'license.html'])->setStyle(['max-height' => '500px', 'overflow' => 'auto', 'padding' => '5px']); |
106
|
|
|
|
107
|
|
|
$license->js(true)->niceScroll(); |
108
|
|
|
|
109
|
|
|
$license->template->setHTML('epesi', config('epesi.app.title')); |
110
|
|
|
|
111
|
|
|
$license->template->setHTML('copyright', config('epesi.app.copyright')); |
112
|
|
|
|
113
|
|
|
$column = $columns->addColumn(); |
114
|
|
|
|
115
|
|
|
$form = $column->add(new Form()); |
116
|
|
|
$form->addField('copyright', ['Checkbox', 'caption' => __('I will not remove the Copyright notice as required by the MIT license.')], ['required'=>true]); |
117
|
|
|
$form->addField('logo', ['Checkbox', 'caption' => __('I will not remove ":epesi powered" logo and the link from the application login screen or the toolbar.', ['epesi' => config('epesi.app.title')])], ['required'=>true]); |
118
|
|
|
$form->addField('support', ['Checkbox', 'caption' => __('I will not remove "Support -> About" credit page from the application menu.')], ['required'=>true]); |
119
|
|
|
$form->addField('store', ['Checkbox', 'caption' => __('I will not remove or rename ":epesi Store" links from the application.', ['epesi' => config('epesi.app.title')])], ['required'=>true]); |
120
|
|
|
|
121
|
|
|
$form->onSubmit(function ($form) use ($wizard) { |
|
|
|
|
122
|
|
|
return $wizard->jsNext(); |
123
|
|
|
}); |
124
|
|
|
|
125
|
|
|
$wizard->setForm($form); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public static function stepDatabase($wizard) |
129
|
|
|
{ |
130
|
|
|
$wizard->addRequiredNote(); |
131
|
|
|
|
132
|
|
|
$form = $wizard->add('Form'); |
133
|
|
|
|
134
|
|
|
$form->addField('host', __('Database Host'), ['required'=>true])->placeholder = __('e.g. localhost'); |
135
|
|
|
$form->addField('port', __('Database Port')); |
136
|
|
|
|
137
|
|
|
$form->addField('driver', ['DropDown', 'values' => [ |
138
|
|
|
'mysql' => 'MySQL', |
139
|
|
|
'postgre' => 'PostgeSQL', |
140
|
|
|
], 'caption' => __('Database Engine')], ['required'=>true]); |
141
|
|
|
|
142
|
|
|
$form->addField('database', __('Database Name')); |
143
|
|
|
$form->addField('username', __('Database Server User'), ['required'=>true]); |
144
|
|
|
$form->addField('password', ['Password', 'caption' => __('Database Server Password')], ['required'=>true]); |
145
|
|
|
|
146
|
|
|
$form->addField('create', ['Checkbox', 'caption' => __('Create New Database')])->on('change', new jsExpression('if ($(event.target).is(":checked")) alert([])', [__('WARNING: Make sure you have CREATE access level to do this!')])); |
147
|
|
|
|
148
|
|
|
foreach ($wizard->recall('connection', []) as $name => $value) { |
149
|
|
|
if (! $field = $form->fields[$name]?? null) continue; |
150
|
|
|
|
151
|
|
|
$field->set($value); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
$form->onSubmit(function ($form) use ($wizard) { |
155
|
|
|
$connection = $form->model->get(); |
156
|
|
|
|
157
|
|
|
$wizard->memorize('connection', $connection); |
158
|
|
|
|
159
|
|
|
Artisan::call('epesi:database-connection', ['--connection' => $connection]); |
160
|
|
|
|
161
|
|
|
if ($connection['create']) { |
162
|
|
|
Artisan::call('epesi:database-create', ['name' => $connection['database'], '--connection' => $connection]); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
ModuleManager::clearCache(); |
166
|
|
|
|
167
|
|
|
Artisan::call('config:clear'); |
168
|
|
|
Artisan::call('cache:clear'); |
169
|
|
|
|
170
|
|
|
return $wizard->jsNext(); |
171
|
|
|
}); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
public static function stepEnvironment($wizard) |
175
|
|
|
{ |
176
|
|
|
Artisan::call('migrate'); |
177
|
|
|
|
178
|
|
|
ob_start(); |
179
|
|
|
ModuleManager::install('system'); |
180
|
|
|
ob_end_clean(); |
181
|
|
|
|
182
|
|
|
$wizard->add(new SystemEnvironmentOverview()); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
public static function stepUser($wizard) |
186
|
|
|
{ |
187
|
|
|
$wizard->addRequiredNote(); |
188
|
|
|
|
189
|
|
|
$form = $wizard->add([new Form, 'buttonSave' => 'Button']); |
190
|
|
|
|
191
|
|
|
$form->addField('name', __('Name'), ['required'=>true])->placeholder = __('e.g. John Doe'); |
192
|
|
|
$form->addField('email', __('Email'), ['required'=>true])->placeholder = __('e.g. [email protected]'); |
193
|
|
|
$form->addField('password', ['Password', 'caption' => __('Password')], ['required'=>true]); |
194
|
|
|
$form->addField('password_verify', ['Password', 'caption' => __('Verify Password')], ['required'=>true]); |
195
|
|
|
|
196
|
|
|
$form->addFieldRules('email', [[ |
197
|
|
|
'type' => 'email', |
198
|
|
|
'prompt' => __('Invalid email address') |
199
|
|
|
]]); |
200
|
|
|
|
201
|
|
|
$form->addFieldRules('password_verify', [[ |
202
|
|
|
'type' => 'match[password]', |
203
|
|
|
'prompt' => __('Password mismatch') |
204
|
|
|
]]); |
205
|
|
|
|
206
|
|
|
$form->validate(function ($form) use ($wizard) { |
207
|
|
|
$user = $form->model->get(); |
208
|
|
|
|
209
|
|
|
User::create([ |
210
|
|
|
'name' => $user['name'], |
211
|
|
|
'email' => $user['email'], |
212
|
|
|
'password' => Hash::make($user['password']), |
213
|
|
|
])->assignRole('Super Admin'); |
214
|
|
|
|
215
|
|
|
return $wizard->jsNext(); |
216
|
|
|
}); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
public static function stepInstallationCompleted($wizard) |
220
|
|
|
{ |
221
|
|
|
$wizard->add(['Header', __(':epesi was successfully installed!', ['epesi' => config('epesi.app.title')]), 'huge centered']); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
public static function getDisplayLanguages() { |
225
|
|
|
return [ |
226
|
|
|
'aa' => __('Afar'), |
227
|
|
|
'ab' => __('Abkhazian'), |
228
|
|
|
'ae' => __('Avestan'), |
229
|
|
|
'af' => __('Afrikaans'), |
230
|
|
|
'ak' => __('Akan'), |
231
|
|
|
'am' => __('Amharic'), |
232
|
|
|
'an' => __('Aragonese'), |
233
|
|
|
'ar' => __('Arabic'), |
234
|
|
|
'as' => __('Assamese'), |
235
|
|
|
'av' => __('Avaric'), |
236
|
|
|
'ay' => __('Aymara'), |
237
|
|
|
'az' => __('Azerbaijani'), |
238
|
|
|
'ba' => __('Bashkir'), |
239
|
|
|
'be' => __('Belarusian'), |
240
|
|
|
'bg' => __('Bulgarian'), |
241
|
|
|
'bh' => __('Bihari'), |
242
|
|
|
'bi' => __('Bislama'), |
243
|
|
|
'bm' => __('Bambara'), |
244
|
|
|
'bn' => __('Bengali'), |
245
|
|
|
'bo' => __('Tibetan'), |
246
|
|
|
'br' => __('Breton'), |
247
|
|
|
'bs' => __('Bosnian'), |
248
|
|
|
'ca' => __('Catalan'), |
249
|
|
|
'ce' => __('Chechen'), |
250
|
|
|
'ch' => __('Chamorro'), |
251
|
|
|
'co' => __('Corsican'), |
252
|
|
|
'cr' => __('Cree'), |
253
|
|
|
'cs' => __('Czech'), |
254
|
|
|
'cu' => __('Church Slavic'), |
255
|
|
|
'cv' => __('Chuvash'), |
256
|
|
|
'cy' => __('Welsh'), |
257
|
|
|
'da' => __('Danish'), |
258
|
|
|
'de' => __('German'), |
259
|
|
|
'dv' => __('Divehi'), |
260
|
|
|
'dz' => __('Dzongkha'), |
261
|
|
|
'ee' => __('Ewe'), |
262
|
|
|
'el' => __('Greek'), |
263
|
|
|
'en' => __('English'), |
264
|
|
|
'eo' => __('Esperanto'), |
265
|
|
|
'es' => __('Spanish'), |
266
|
|
|
'et' => __('Estonian'), |
267
|
|
|
'eu' => __('Basque'), |
268
|
|
|
'fa' => __('Persian'), |
269
|
|
|
'ff' => __('Fulah'), |
270
|
|
|
'fi' => __('Finnish'), |
271
|
|
|
'fj' => __('Fijian'), |
272
|
|
|
'fo' => __('Faroese'), |
273
|
|
|
'fr' => __('French'), |
274
|
|
|
'fy' => __('Western Frisian'), |
275
|
|
|
'ga' => __('Irish'), |
276
|
|
|
'gd' => __('Scottish Gaelic'), |
277
|
|
|
'gl' => __('Galician'), |
278
|
|
|
'gn' => __('Guarani'), |
279
|
|
|
'gu' => __('Gujarati'), |
280
|
|
|
'gv' => __('Manx'), |
281
|
|
|
'ha' => __('Hausa'), |
282
|
|
|
'he' => __('Hebrew'), |
283
|
|
|
'hi' => __('Hindi'), |
284
|
|
|
'ho' => __('Hiri Motu'), |
285
|
|
|
'hr' => __('Croatian'), |
286
|
|
|
'ht' => __('Haitian'), |
287
|
|
|
'hu' => __('Hungarian'), |
288
|
|
|
'hy' => __('Armenian'), |
289
|
|
|
'hz' => __('Herero'), |
290
|
|
|
'ia' => __('Interlingua (International Auxiliary Language Association)'), |
291
|
|
|
'id' => __('Indonesian'), |
292
|
|
|
'ie' => __('Interlingue'), |
293
|
|
|
'ig' => __('Igbo'), |
294
|
|
|
'ii' => __('Sichuan Yi'), |
295
|
|
|
'ik' => __('Inupiaq'), |
296
|
|
|
'io' => __('Ido'), |
297
|
|
|
'is' => __('Icelandic'), |
298
|
|
|
'it' => __('Italian'), |
299
|
|
|
'iu' => __('Inuktitut'), |
300
|
|
|
'ja' => __('Japanese'), |
301
|
|
|
'jv' => __('Javanese'), |
302
|
|
|
'ka' => __('Georgian'), |
303
|
|
|
'kg' => __('Kongo'), |
304
|
|
|
'ki' => __('Kikuyu'), |
305
|
|
|
'kj' => __('Kwanyama'), |
306
|
|
|
'kk' => __('Kazakh'), |
307
|
|
|
'kl' => __('Kalaallisut'), |
308
|
|
|
'km' => __('Khmer'), |
309
|
|
|
'kn' => __('Kannada'), |
310
|
|
|
'ko' => __('Korean'), |
311
|
|
|
'kr' => __('Kanuri'), |
312
|
|
|
'ks' => __('Kashmiri'), |
313
|
|
|
'ku' => __('Kurdish'), |
314
|
|
|
'kv' => __('Komi'), |
315
|
|
|
'kw' => __('Cornish'), |
316
|
|
|
'ky' => __('Kirghiz'), |
317
|
|
|
'la' => __('Latin'), |
318
|
|
|
'lb' => __('Luxembourgish'), |
319
|
|
|
'lg' => __('Ganda'), |
320
|
|
|
'li' => __('Limburgish'), |
321
|
|
|
'ln' => __('Lingala'), |
322
|
|
|
'lo' => __('Lao'), |
323
|
|
|
'lt' => __('Lithuanian'), |
324
|
|
|
'lu' => __('Luba-Katanga'), |
325
|
|
|
'lv' => __('Latvian'), |
326
|
|
|
'mg' => __('Malagasy'), |
327
|
|
|
'mh' => __('Marshallese'), |
328
|
|
|
'mi' => __('Maori'), |
329
|
|
|
'mk' => __('Macedonian'), |
330
|
|
|
'ml' => __('Malayalam'), |
331
|
|
|
'mn' => __('Mongolian'), |
332
|
|
|
'mr' => __('Marathi'), |
333
|
|
|
'ms' => __('Malay'), |
334
|
|
|
'mt' => __('Maltese'), |
335
|
|
|
'my' => __('Burmese'), |
336
|
|
|
'na' => __('Nauru'), |
337
|
|
|
'nb' => __('Norwegian Bokmal'), |
338
|
|
|
'nd' => __('North Ndebele'), |
339
|
|
|
'ne' => __('Nepali'), |
340
|
|
|
'ng' => __('Ndonga'), |
341
|
|
|
'nl' => __('Dutch'), |
342
|
|
|
'nn' => __('Norwegian Nynorsk'), |
343
|
|
|
'no' => __('Norwegian'), |
344
|
|
|
'nr' => __('South Ndebele'), |
345
|
|
|
'nv' => __('Navajo'), |
346
|
|
|
'ny' => __('Chichewa'), |
347
|
|
|
'oc' => __('Occitan'), |
348
|
|
|
'oj' => __('Ojibwa'), |
349
|
|
|
'om' => __('Oromo'), |
350
|
|
|
'or' => __('Oriya'), |
351
|
|
|
'os' => __('Ossetian'), |
352
|
|
|
'pa' => __('Panjabi'), |
353
|
|
|
'pi' => __('Pali'), |
354
|
|
|
'pl' => __('Polish'), |
355
|
|
|
'ps' => __('Pashto'), |
356
|
|
|
'pt' => __('Portuguese'), |
357
|
|
|
'qu' => __('Quechua'), |
358
|
|
|
'rm' => __('Raeto-Romance'), |
359
|
|
|
'rn' => __('Kirundi'), |
360
|
|
|
'ro' => __('Romanian'), |
361
|
|
|
'ru' => __('Russian'), |
362
|
|
|
'rw' => __('Kinyarwanda'), |
363
|
|
|
'sa' => __('Sanskrit'), |
364
|
|
|
'sc' => __('Sardinian'), |
365
|
|
|
'sd' => __('Sindhi'), |
366
|
|
|
'se' => __('Northern Sami'), |
367
|
|
|
'sg' => __('Sango'), |
368
|
|
|
'si' => __('Sinhala'), |
369
|
|
|
'sk' => __('Slovak'), |
370
|
|
|
'sl' => __('Slovenian'), |
371
|
|
|
'sm' => __('Samoan'), |
372
|
|
|
'sn' => __('Shona'), |
373
|
|
|
'so' => __('Somali'), |
374
|
|
|
'sq' => __('Albanian'), |
375
|
|
|
'sr' => __('Serbian'), |
376
|
|
|
'ss' => __('Swati'), |
377
|
|
|
'st' => __('Southern Sotho'), |
378
|
|
|
'su' => __('Sundanese'), |
379
|
|
|
'sv' => __('Swedish'), |
380
|
|
|
'sw' => __('Swahili'), |
381
|
|
|
'ta' => __('Tamil'), |
382
|
|
|
'te' => __('Telugu'), |
383
|
|
|
'tg' => __('Tajik'), |
384
|
|
|
'th' => __('Thai'), |
385
|
|
|
'ti' => __('Tigrinya'), |
386
|
|
|
'tk' => __('Turkmen'), |
387
|
|
|
'tl' => __('Tagalog'), |
388
|
|
|
'tn' => __('Tswana'), |
389
|
|
|
'to' => __('Tonga'), |
390
|
|
|
'tr' => __('Turkish'), |
391
|
|
|
'ts' => __('Tsonga'), |
392
|
|
|
'tt' => __('Tatar'), |
393
|
|
|
'tw' => __('Twi'), |
394
|
|
|
'ty' => __('Tahitian'), |
395
|
|
|
'ug' => __('Uighur'), |
396
|
|
|
'uk' => __('Ukrainian'), |
397
|
|
|
'ur' => __('Urdu'), |
398
|
|
|
'uz' => __('Uzbek'), |
399
|
|
|
've' => __('Venda'), |
400
|
|
|
'vi' => __('Vietnamese'), |
401
|
|
|
'vo' => __('Volapuk'), |
402
|
|
|
'wa' => __('Walloon'), |
403
|
|
|
'wo' => __('Wolof'), |
404
|
|
|
'xh' => __('Xhosa'), |
405
|
|
|
'yi' => __('Yiddish'), |
406
|
|
|
'yo' => __('Yoruba'), |
407
|
|
|
'za' => __('Zhuang'), |
408
|
|
|
'zh' => __('Chinese'), |
409
|
|
|
'zu' => __('Zulu') |
410
|
|
|
]; |
411
|
|
|
} |
412
|
|
|
} |
413
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths