diff --git a/app/Http/Controllers/App/Maintenance.php b/app/Http/Controllers/App/Maintenance.php index 44b28421..ecbc6c4a 100644 --- a/app/Http/Controllers/App/Maintenance.php +++ b/app/Http/Controllers/App/Maintenance.php @@ -3,17 +3,34 @@ namespace App\Http\Controllers\App; use App\Http\Controllers\Controller; +use App\Models\Language; +use App\Models\LanguageTranslation; +use App\Services\LanguageService; use Artisan; +use DB; +use Gate; +use Illuminate\Contracts\Foundation\Application; +use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Schema; class Maintenance extends Controller { + /** + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function __construct() + { + // Check admin permission + Gate::authorize('maintenance'); + } /** * Start maintenance mode */ - public function up() { + public function up() + { $command = Artisan::call('up'); if ($command === 0) { @@ -24,7 +41,8 @@ class Maintenance extends Controller /** * End maintenance mode */ - public function down() { + public function down() + { $command = Artisan::call('down'); if ($command === 0) { @@ -33,17 +51,23 @@ class Maintenance extends Controller } /** - * Upgrade database + * Get new language translations from default translations + * and insert it into database + * + * @return Application|ResponseFactory|Response */ - public function upgrade() + public function upgrade_translations() { - $this->upgrade_database(); + resolve(LanguageService::class) + ->upgrade_language_translations(); + + return response('Done.', 201); } /** * @return int|mixed */ - private function upgrade_database() + public function upgrade_database() { $command = Artisan::call('migrate', [ '--force' => true diff --git a/app/Models/Language.php b/app/Models/Language.php index ade8035b..daf50ef3 100644 --- a/app/Models/Language.php +++ b/app/Models/Language.php @@ -2,7 +2,7 @@ namespace App\Models; -use App\Services\HelperService; +use App\Services\LanguageService; use Illuminate\Support\Str; use Illuminate\Support\Facades\DB; use Illuminate\Database\Eloquent\Model; @@ -41,7 +41,7 @@ class Language extends Model static::creating(function ($language) { $language->id = Str::uuid(); - resolve(HelperService::class) + resolve(LanguageService::class) ->create_default_language_translations( get_setting('license') ?? 'extended', $language->locale ); diff --git a/app/Models/LanguageTranslation.php b/app/Models/LanguageTranslation.php index c6fe28b4..bb7b7a67 100644 --- a/app/Models/LanguageTranslation.php +++ b/app/Models/LanguageTranslation.php @@ -4,6 +4,9 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +/** + * @method static whereLang(string $string) + */ class LanguageTranslation extends Model { public $timestamps = false; diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 11bcf1d6..2a547782 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -26,8 +26,8 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // Define admin settings gate - Gate::define('admin-settings', function ($user) { + // Define admin maintenance gate + Gate::define('maintenance', function ($user) { return $user->role === 'admin'; }); } diff --git a/app/Services/HelperService.php b/app/Services/HelperService.php index cbfac7e8..6ca24d30 100644 --- a/app/Services/HelperService.php +++ b/app/Services/HelperService.php @@ -8,7 +8,6 @@ use App\Models\Share; use Aws\Exception\MultipartUploadException; use Aws\S3\MultipartUploader; use DB; -use Illuminate\Http\Request; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; @@ -323,35 +322,4 @@ class HelperService } } } - - /** - * @param $license - * @param $locale - */ - function create_default_language_translations($license, $locale) - { - $translations = [ - 'extended' => collect([ - config("language-translations.extended"), - config("language-translations.regular"), - config("custom-language-translations") - ])->collapse(), - 'regular' => collect([ - config("language-translations.regular"), - config("custom-language-translations") - ])->collapse(), - ]; - - $translations = $translations[strtolower($license)] - ->map(function ($value, $key) use ($locale) { - return [ - 'lang' => $locale, - 'value' => $value, - 'key' => $key, - ]; - })->toArray(); - - DB::table('language_translations') - ->insert($translations); - } } \ No newline at end of file diff --git a/app/Services/LanguageService.php b/app/Services/LanguageService.php new file mode 100644 index 00000000..2bf192ff --- /dev/null +++ b/app/Services/LanguageService.php @@ -0,0 +1,93 @@ + collect([ + config("language-translations.extended"), + config("language-translations.regular"), + config("custom-language-translations") + ])->collapse(), + 'regular' => collect([ + config("language-translations.regular"), + config("custom-language-translations") + ])->collapse(), + ]; + + $translations = $translations[strtolower($license)] + ->map(function ($value, $key) use ($locale) { + return [ + 'lang' => $locale, + 'value' => $value, + 'key' => $key, + ]; + })->toArray(); + + DB::table('language_translations') + ->insert($translations); + } + + /** + * Find newly added translations in default language + * translations file and insert it into database + */ + function upgrade_language_translations() + { + // Get all app locales + $locales = Language::all() + ->pluck('locale'); + + // Get default translations + $translations = LanguageTranslation::whereLang('en') + ->get(); + + $default_translations = [ + 'extended' => collect([ + config("language-translations.extended"), + config("language-translations.regular"), + config("custom-language-translations") + ])->collapse(), + 'regular' => collect([ + config("language-translations.regular"), + config("custom-language-translations") + ])->collapse(), + ]; + + $license = strtolower(get_setting('license')); + + // Find new translations in default translations + $newbies = $default_translations[$license] + ->diff(map_language_translations($translations)); + + // Store new translations for every language + $locales->each(function ($locale) use ($newbies) { + + $translations = $newbies + ->map(function ($value, $key) use ($locale) { + return [ + 'lang' => $locale, + 'value' => $value, + 'key' => $key, + ]; + })->toArray(); + + // Store translations into database + DB::table('language_translations') + ->insert($translations); + }); + } +} \ No newline at end of file diff --git a/public/mix-manifest.json b/public/mix-manifest.json index e445b0e6..91ce28ab 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -17,7 +17,7 @@ "/chunks/app-email.js": "/chunks/app-email.js?id=c578a85112c6a4b1ed0e", "/chunks/app-index.js": "/chunks/app-index.js?id=7f07dceace5c9c8255bb", "/chunks/app-language.js": "/chunks/app-language.js?id=e97b8b4e0a0f5ac93c97", - "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=91d6a4649c9277a7bb29", + "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=e4abf38870f961cb6979", "/chunks/app-others.js": "/chunks/app-others.js?id=9156adba3b1697a8bf3e", "/chunks/app-payments.js": "/chunks/app-payments.js?id=7e1a982c90174f568fb2", "/chunks/app-settings.js": "/chunks/app-settings.js?id=bbf2a2e436d939f7fc07", @@ -59,7 +59,7 @@ "/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=d448806bfefc6cc43f0d", "/chunks/purchase-code.js": "/chunks/purchase-code.js?id=e00ee12cde704060e15b", "/chunks/settings.js": "/chunks/settings.js?id=2637c005a9c8b01cfc9b", - "/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=c12436dc2933527ce1f5", + "/chunks/settings-create-payment-methods.js": "/chunks/settings-create-payment-methods.js?id=88849e6ddce9226d49a5", "/chunks/settings-invoices.js": "/chunks/settings-invoices.js?id=444b9bbc310647ddd297", "/chunks/settings-password.js": "/chunks/settings-password.js?id=d24053a92c2594439d04", "/chunks/settings-payment-methods.js": "/chunks/settings-payment-methods.js?id=3bc709a228c0849a6f62", @@ -76,7 +76,7 @@ "/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js?id=1acdec3a157c8943a88d", "/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=a843f8cf90ff1e3168e8", "/chunks/subscription-service.js": "/chunks/subscription-service.js?id=90c1aa9431689a89eb3d", - "/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js?id=d76e4522f424ce996e8f", + "/chunks/upgrade-billing.js": "/chunks/upgrade-billing.js?id=b06efc03a40bcba2bdad", "/chunks/upgrade-billing~chunks/upgrade-plan.js": "/chunks/upgrade-billing~chunks/upgrade-plan.js?id=e1658ebec711765f67fc", "/chunks/upgrade-plan.js": "/chunks/upgrade-plan.js?id=35179531a8241da128e9", "/chunks/user.js": "/chunks/user.js?id=6e9af0d22327a4cc82e9", @@ -90,46 +90,5 @@ "/chunks/users.js": "/chunks/users.js?id=f1057be5cf73ebc32c14", "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js?id=a9facd8e57a0dd054f8c", "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js?id=6d6e7e4191c9e2705c8a", - "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3", - "/chunks/app-language.5e86b6c8aedb968aabd1.hot-update.js": "/chunks/app-language.5e86b6c8aedb968aabd1.hot-update.js", - "/chunks/app-language.3e137679fcd212ecdb43.hot-update.js": "/chunks/app-language.3e137679fcd212ecdb43.hot-update.js", - "/chunks/app-language.8069ae5a36cc4868d1d3.hot-update.js": "/chunks/app-language.8069ae5a36cc4868d1d3.hot-update.js", - "/chunks/app-language.d4c9d87012f92cbb3694.hot-update.js": "/chunks/app-language.d4c9d87012f92cbb3694.hot-update.js", - "/chunks/app-language.c0acc236afe078713927.hot-update.js": "/chunks/app-language.c0acc236afe078713927.hot-update.js", - "/chunks/app-language.42b3b09042f97ffb073a.hot-update.js": "/chunks/app-language.42b3b09042f97ffb073a.hot-update.js", - "/chunks/app-language.7478a2ac686bc8208aac.hot-update.js": "/chunks/app-language.7478a2ac686bc8208aac.hot-update.js", - "/chunks/app-language.695a92293d8dc92d833b.hot-update.js": "/chunks/app-language.695a92293d8dc92d833b.hot-update.js", - "/chunks/app-language.25fa944544b002f36615.hot-update.js": "/chunks/app-language.25fa944544b002f36615.hot-update.js", - "/chunks/app-language.aee54dee7bdbae4a4dad.hot-update.js": "/chunks/app-language.aee54dee7bdbae4a4dad.hot-update.js", - "/chunks/app-language.62fa61e8408e9fd42b23.hot-update.js": "/chunks/app-language.62fa61e8408e9fd42b23.hot-update.js", - "/js/main.21d047cff85c2cc93f65.hot-update.js": "/js/main.21d047cff85c2cc93f65.hot-update.js", - "/chunks/app-language.13a02b269488a9ed8054.hot-update.js": "/chunks/app-language.13a02b269488a9ed8054.hot-update.js", - "/chunks/app-language.ff6a3c1bce44294e69aa.hot-update.js": "/chunks/app-language.ff6a3c1bce44294e69aa.hot-update.js", - "/chunks/app-language.0aff16e91050419f056f.hot-update.js": "/chunks/app-language.0aff16e91050419f056f.hot-update.js", - "/chunks/admin.00d9afd473b8b4521765.hot-update.js": "/chunks/admin.00d9afd473b8b4521765.hot-update.js", - "/chunks/admin.b85158f2cba3bfbbf404.hot-update.js": "/chunks/admin.b85158f2cba3bfbbf404.hot-update.js", - "/chunks/admin.bf53021a67ae75f1b0ee.hot-update.js": "/chunks/admin.bf53021a67ae75f1b0ee.hot-update.js", - "/chunks/admin.bda5e8845d2e437ffe7c.hot-update.js": "/chunks/admin.bda5e8845d2e437ffe7c.hot-update.js", - "/chunks/admin.a97d84e1d8754867cef5.hot-update.js": "/chunks/admin.a97d84e1d8754867cef5.hot-update.js", - "/chunks/app-language.8ca3efeede3cedbd37e0.hot-update.js": "/chunks/app-language.8ca3efeede3cedbd37e0.hot-update.js", - "/chunks/app-language.23f838b7be45ce10476b.hot-update.js": "/chunks/app-language.23f838b7be45ce10476b.hot-update.js", - "/chunks/app-language.fd910667c3258a91322b.hot-update.js": "/chunks/app-language.fd910667c3258a91322b.hot-update.js", - "/chunks/app-language.6a163294803727b4d501.hot-update.js": "/chunks/app-language.6a163294803727b4d501.hot-update.js", - "/chunks/platform.085176bd0065608cb370.hot-update.js": "/chunks/platform.085176bd0065608cb370.hot-update.js", - "/chunks/dashboard.f475c4f86956a8e5419b.hot-update.js": "/chunks/dashboard.f475c4f86956a8e5419b.hot-update.js", - "/chunks/app-language.1dd1423a8af00cb8c9bd.hot-update.js": "/chunks/app-language.1dd1423a8af00cb8c9bd.hot-update.js", - "/chunks/app-language.040639168a8e73d40dec.hot-update.js": "/chunks/app-language.040639168a8e73d40dec.hot-update.js", - "/chunks/app-language.72377b182d4f8ae86208.hot-update.js": "/chunks/app-language.72377b182d4f8ae86208.hot-update.js", - "/chunks/app-language.d82931f09bfdd6dbc955.hot-update.js": "/chunks/app-language.d82931f09bfdd6dbc955.hot-update.js", - "/chunks/app-language.2193825771658065f586.hot-update.js": "/chunks/app-language.2193825771658065f586.hot-update.js", - "/chunks/app-language.cab91ceba0b383f64680.hot-update.js": "/chunks/app-language.cab91ceba0b383f64680.hot-update.js", - "/chunks/app-language.a42ea53577d7e0f0a5fb.hot-update.js": "/chunks/app-language.a42ea53577d7e0f0a5fb.hot-update.js", - "/chunks/app-language.09d631da1a2172e96bce.hot-update.js": "/chunks/app-language.09d631da1a2172e96bce.hot-update.js", - "/chunks/app-appearance.690e1a1f6d721bca8cdf.hot-update.js": "/chunks/app-appearance.690e1a1f6d721bca8cdf.hot-update.js", - "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.51e62febff164672078a.hot-update.js": "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.51e62febff164672078a.hot-update.js", - "/chunks/app-language.439fa6fafc54298cdf2b.hot-update.js": "/chunks/app-language.439fa6fafc54298cdf2b.hot-update.js", - "/chunks/app-language.9ee4a795d26a6e44820c.hot-update.js": "/chunks/app-language.9ee4a795d26a6e44820c.hot-update.js", - "/js/main.8517a680822ffe9748c9.hot-update.js": "/js/main.8517a680822ffe9748c9.hot-update.js", - "/chunks/admin.9396f79fef53ad7070fe.hot-update.js": "/chunks/admin.9396f79fef53ad7070fe.hot-update.js", - "/chunks/platform.9396f79fef53ad7070fe.hot-update.js": "/chunks/platform.9396f79fef53ad7070fe.hot-update.js" + "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3" } diff --git a/routes/maintenance.php b/routes/maintenance.php index d4d477e5..5365d07c 100644 --- a/routes/maintenance.php +++ b/routes/maintenance.php @@ -2,6 +2,14 @@ use App\Http\Controllers\App\Maintenance; -Route::post('/upgrade', [Maintenance::class, 'upgrade']); -Route::get('/down', [Maintenance::class, 'down']); -Route::get('/up', [Maintenance::class, 'up']); \ No newline at end of file +Route::group(['middleware' => ['auth:sanctum']], function () { + + Route::get('/down', [Maintenance::class, 'down']); + Route::get('/up', [Maintenance::class, 'up']); + + Route::group(['prefix' => 'upgrade'], function () { + Route::get('/translations', [Maintenance::class, 'upgrade_translations']); + Route::get('/database', [Maintenance::class, 'upgrade_database']); + }); +}); + diff --git a/tests/Feature/App/AppUpgradeTest.php b/tests/Feature/App/AppUpgradeTest.php new file mode 100644 index 00000000..385d7217 --- /dev/null +++ b/tests/Feature/App/AppUpgradeTest.php @@ -0,0 +1,86 @@ +setup = app()->make(SetupService::class); + } + + /** + * @test + */ + public function it_upgrade_default_language_translations() + { + $this->setup->seed_default_settings('Extended'); + + Setting::create([ + 'name' => 'setup_wizard_success', + 'value' => 'setup-done', + ]); + + Setting::create([ + 'name' => 'license', + 'value' => 'Extended', + ]); + + collect(['en', 'sk']) + ->map(function ($locale) { + + DB::table('languages')->insert([ + 'id' => Str::uuid(), + 'name' => 'English', + 'locale' => $locale + ]); + + DB::table('language_translations')->insert([ + [ + 'key' => 'activation.stripe.button', + 'value' => 'Set up your Stripe account', + 'lang' => $locale + ], [ + 'key' => 'activation.stripe.description', + 'value' => 'To charge your users, please set up your Stripe account credentials.', + 'lang' => $locale + ] + ]); + }); + + Setting::create([ + 'name' => 'language', + 'value' => 'en', + ]); + + $user = User::factory(User::class) + ->create(['role' => 'admin']); + + Sanctum::actingAs($user); + + $this->get('/upgrade/translations') + ->assertStatus(201); + + collect(['en', 'sk']) + ->map(function ($locale) { + + $this->assertDatabaseHas('language_translations', [ + 'key' => 'activation.stripe.title', + 'value' => 'Your Stripe account is not set', + 'lang' => $locale, + ]); + }); + } +}