Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/Config/GeneralConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -6081,10 +6081,8 @@ public function tempAssetUploadFs(?string $value): self
}

/**
* Configures Craft to send all system emails to either a single email address or an array of email addresses
* for testing purposes.
*
* The timezone of the site. If set, it will take precedence over the Timezone setting in Settings → General.
* The timezone of the site. If set, it will take precedence over the Timezone setting in Settings → General
* (stored in project config).
*
* This can be set to one of PHP’s [supported timezones](https://php.net/manual/en/timezones.php).
*
Expand Down
23 changes: 23 additions & 0 deletions src/Console/Commands/Install/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
use CraftCms\Cms\Cms;
use CraftCms\Cms\Config\GeneralConfig;
use CraftCms\Cms\Console\CraftCommand;
use CraftCms\Cms\Cp\SelectOptions;
use CraftCms\Cms\Database\Migrations\Install;
use CraftCms\Cms\Database\Migrator;
use CraftCms\Cms\Site\Concerns\SiteDefaults;
use CraftCms\Cms\Site\Data\Site;
use CraftCms\Cms\Support\Env;
use CraftCms\Cms\Translation\I18N;
use CraftCms\Cms\Validation\Rules\EnvValueRule;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;
use Laravel\Prompts\Support\Logger;
use Override;
Expand Down Expand Up @@ -43,6 +46,7 @@ class InstallCommand extends Command
{--siteName= : The default site name for the first site to create during install.}
{--siteUrl= : The default site URL for the first site to create during install.}
{--language= : The default language for the first site to create during install.}
{--timezone= : The app’s default timezone, typically configured in Settings → General.}
';

#[Override]
Expand Down Expand Up @@ -139,6 +143,23 @@ public function handle(
return null;
}
), 'language')
->addIf(! $this->option('timezone'), function () {
$timezoneBaseOptions = array_column(SelectOptions::getTimeZoneOptions(), 'value');
$timezoneEnvOptions = array_column(SelectOptions::getEnvOptions($timezoneBaseOptions)[0]['options'] ?? [], 'value');

return suggest(
label: 'What timezone should the application use?',
options: [
...$timezoneBaseOptions,
...$timezoneEnvOptions,
],
default: date_default_timezone_get(),
required: true,
validate: [new EnvValueRule([Rule::in($timezoneBaseOptions)])],
hint: 'Type $ for environment variables containing valid timezones.',
info: Env::parse(...),
);
}, 'timezone')
->submit();

$username = $this->option('username') ?? $responses['username'];
Expand All @@ -147,6 +168,7 @@ public function handle(
$siteName = $this->option('siteName') ?? $responses['siteName'];
$siteUrl = $this->option('siteUrl') ?? $responses['siteUrl'];
$language = $this->option('language') ?? $responses['language'];
$timezone = $this->option('timezone') ?? $responses['timezone'];

if ($generalConfig->useEmailAsUsername) {
$username = $email;
Expand Down Expand Up @@ -184,6 +206,7 @@ public function handle(
password: $password,
email: $email,
site: $site,
timezone: $timezone,
), 'up');

$migrator->getRepository()->log('Install', 1);
Expand Down
3 changes: 2 additions & 1 deletion src/Database/Migrations/Install.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public function __construct(
public ?string $password = null,
public ?string $email = null,
public ?Site $site = null,
public ?string $timezone = null,
public bool $applyProjectConfigYaml = true,
) {
parent::__construct();
Expand Down Expand Up @@ -1415,7 +1416,7 @@ private function _generateInitialConfig(): array
'name' => $this->site->getName(),
'live' => true,
'schemaVersion' => Cms::SCHEMA_VERSION,
'timeZone' => 'America/Los_Angeles',
'timeZone' => $this->timezone ?? 'America/Los_Angeles',
],
'users' => [
'requireEmailVerification' => true,
Expand Down
39 changes: 20 additions & 19 deletions src/Http/Controllers/InstallController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
use CraftCms\Cms\Support\Facades\I18N;
use CraftCms\Cms\Support\Str;
use CraftCms\Cms\Support\Url;
use CraftCms\Cms\Validation\Rules\EnvValueRule;
use CraftCms\Cms\Validation\Rules\LanguageRule;
use CraftCms\Cms\Validation\Rules\TimezoneRule;
use Illuminate\Database\SQLiteDatabaseDoesNotExistException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -63,32 +65,33 @@ public function index(GeneralConfig $generalConfig): \Inertia\Response
}
}

// Grab the license text
$licensePath = Aliases::get('@craftcms/LICENSE.md');
$license = file_get_contents($licensePath);
$licenseHtml = Str::markdown($license);

// Guess the site name based on the server name
$defaultSystemName = $this->defaultSiteName();
$defaultSiteUrl = $this->defaultSiteUrl();
$defaultSiteLanguage = $this->defaultSiteLanguage();
$locales = I18N::getAllLocales();
$dbConfig = DB::getConfig();
$postCpLoginRedirect = Cms::config()->postCpLoginRedirect;

$localeOptions = collect($locales)
->map(fn ($locale) => [
return Inertia::render('Install', [
'showDbScreen' => $showDbScreen,
'postCpLoginRedirect' => $postCpLoginRedirect,
'licenseHtml' => Inertia::defer(function () {
$licensePath = Aliases::get('@craftcms/LICENSE.md');
$license = file_get_contents($licensePath);

return Str::markdown($license);
}),
'localeOptions' => Inertia::defer(fn () => I18N::getAllLocales()->map(fn ($locale) => [
'id' => $locale->id,
'value' => $locale->id,
'label' => $locale->getDisplayName(app()->getLocale()),
'selected' => $locale->id === $defaultSiteLanguage,
]);
])),
'timezone' => Inertia::defer(function () {
$timezoneOptions = SelectOptions::getTimeZoneOptions();

return Inertia::render('Install', [
'showDbScreen' => $showDbScreen,
'postCpLoginRedirect' => $postCpLoginRedirect,
'licenseHtml' => Inertia::defer(fn () => $licenseHtml),
'localeOptions' => Inertia::defer(fn () => $localeOptions),
return array_merge($timezoneOptions, SelectOptions::getEnvOptions(array_column($timezoneOptions, 'value')));
}),
'baseUrlSuggestions' => SelectOptions::getEnvSuggestions(true, fn ($value) => Str::isUrl($value)),
'defaultSystemName' => $defaultSystemName,
'defaultSiteUrl' => $defaultSiteUrl,
Expand Down Expand Up @@ -144,14 +147,11 @@ public function validateSite(Request $request): Response
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'baseUrl' => ['nullable', 'string', 'max:255'],
'baseUrl' => [new EnvValueRule(['nullable', 'url', 'max:255'])],
'language' => ['required', 'string', 'max:255', new LanguageRule(onlySiteLanguages: false)],
'timezone' => [new EnvValueRule([new TimezoneRule])],
]);

$baseUrl = Env::parse($request->input('baseUrl'));

Validator::validate(compact('baseUrl'), ['baseUrl' => 'url']);

return new JsonResponse;
}

Expand Down Expand Up @@ -221,6 +221,7 @@ public function install(Request $request, Migrator $migrator, LaravelMigrations
password: $request->input('account.password'),
email: $email,
site: $site,
timezone: $request->input('site.timezone'),
)->silent();

// Run the install migration
Expand Down
48 changes: 14 additions & 34 deletions src/Http/Controllers/Settings/GeneralSettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
use CraftCms\Cms\Http\RespondsWithFlash;
use CraftCms\Cms\Http\Responses\CpScreenResponse;
use CraftCms\Cms\ProjectConfig\ProjectConfig;
use CraftCms\Cms\Support\Env;
use CraftCms\Cms\Support\Url;
use CraftCms\Cms\Validation\Rules\EnvValueRule;
use CraftCms\Cms\Validation\Rules\TimezoneRule;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\Response;

use function CraftCms\Cms\t;
Expand All @@ -27,6 +26,9 @@ public function __construct(

public function index(): CpScreenResponse
{
$timezoneOptions = SelectOptions::getTimeZoneOptions();
$timezoneOptions = array_merge($timezoneOptions, SelectOptions::getEnvOptions(array_column($timezoneOptions, 'value')));

return new CpScreenResponse()
->title(t('General Settings'))
->crumbs([
Expand All @@ -37,47 +39,25 @@ public function index(): CpScreenResponse
->inertiaPage('SettingsGeneralPage', [
'system' => $this->projectConfig->get('system') ?? [],
'nameSuggestions' => SelectOptions::getEnvSuggestions(),
'timezoneOptions' => [
...SelectOptions::getTimeZoneOptions(),
...SelectOptions::getEnvOptions(),
],
'timezoneOptions' => $timezoneOptions,
'systemStatusOptions' => SelectOptions::getBooleanEnvOptions(),
]);
}

public function store(Request $request): Response
{
$resolvedValues = [];

$envAllowedKeys = ['name', 'live', 'timeZone'];
$booleans = ['live'];
foreach ($request->all() as $key => $value) {
if (in_array($key, $envAllowedKeys) && is_string($value) && str_starts_with($value, '$')) {
$resolvedValues[$key] = in_array($key, $booleans) ? Env::parseBoolean($value) : Env::parse($value);
} else {
$resolvedValues[$key] = $value;
}
}

/**
* We want to validate against the resolved values, but we'll store what the user provided
*/
Validator::make($resolvedValues, [
'name' => ['required', 'string'],
'live' => ['required', 'boolean'],
$settings = $request->validate([
'name' => [new EnvValueRule(['required', 'string'])],
'live' => [new EnvValueRule(['required', 'boolean'])],
'retryDuration' => ['nullable', 'integer'],
'timeZone' => ['required', 'string', new TimezoneRule],
])->validate();
'timeZone' => [new EnvValueRule(['required', 'string', new TimezoneRule])],
]);

$systemSettings = $this->projectConfig->get('system') ?? [];
$systemSettings['name'] = $request->input('name');
$systemSettings['live'] = $request->input('live');
$systemSettings['retryDuration'] = $request->input('retryDuration') ?: null;
$systemSettings['timeZone'] = $request->input('timeZone');

if (! str_starts_with((string) $systemSettings['live'], '$')) {
$systemSettings['live'] = $request->boolean('live');
}
$systemSettings['name'] = $settings['name'];
$systemSettings['live'] = $settings['live'];
$systemSettings['retryDuration'] = $settings['retryDuration'] ?? null;
$systemSettings['timeZone'] = $settings['timeZone'];

$this->projectConfig->set('system', $systemSettings, 'Update system settings.');

Expand Down
Loading