diff --git a/config/config.default.php b/config/config.default.php index 990515cb..b60d0b07 100644 --- a/config/config.default.php +++ b/config/config.default.php @@ -233,6 +233,16 @@ return [ // Users are able to sign up 'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true), + // Required fields on sign-up page + 'signup_required_fields' => [ + 'pronoun' => (bool) env('PRONOUN_REQUIRED', false), + 'firstname' => (bool) env('FIRSTNAME_REQUIRED', false), + 'lastname' => (bool) env('LASTNAME_REQUIRED', false), + 'tshirt_size' => (bool) env('TSHIRT_SIZE_REQUIRED', true), + 'mobile' => (bool) env('MOBILE_REQUIRED', false), + 'dect' => (bool) env('DECT_REQUIRED', false), + ], + // Only arrived angels can sign up for shifts 'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false), diff --git a/includes/view/User_view.php b/includes/view/User_view.php index 318bb22b..aa0eb016 100644 --- a/includes/view/User_view.php +++ b/includes/view/User_view.php @@ -952,7 +952,11 @@ function render_user_tshirt_hint() { $goodie = GoodieType::from(config('goodie_type')); $goodie_tshirt = $goodie === GoodieType::Tshirt; - if ($goodie_tshirt && !auth()->user()->personalData->shirt_size) { + if ( + $goodie_tshirt + && config('signup_required_fields')['tshirt_size'] + && !auth()->user()->personalData->shirt_size + ) { $text = __('You need to specify a tshirt size in your settings!'); return render_profile_link($text); } diff --git a/resources/lang/de_DE/additional.po b/resources/lang/de_DE/additional.po index 123725fb..94998c04 100644 --- a/resources/lang/de_DE/additional.po +++ b/resources/lang/de_DE/additional.po @@ -23,20 +23,20 @@ msgstr "Das angegebene Passwort ist zu kurz." msgid "validation.login.required" msgstr "Bitte gib einen Loginnamen an." -msgid "validation.pronoun.optional" -msgstr "Das Pronomen, das Du eingegeben hast, ist zu lang. Verwende maximal 15 Zeichen." +msgid "validation.pronoun.required" +msgstr "Bitte gebe dein Pronomen an." -msgid "validation.firstname.optional" -msgstr "Der von dir eingegebene Vorname ist zu lang. Verwende maximal 64 Zeichen." +msgid "validation.firstname.required" +msgstr "Bitte gebe deinen Vornamen an." -msgid "validation.lastname.optional" -msgstr "Der von dir eingegebene Vorname ist zu lang. Verwende maximal 64 Zeichen." +msgid "validation.lastname.required" +msgstr "Bitte gebe deinen Nachnamen an." -msgid "validation.mobile.optional" -msgstr "Der von dir eingegebene Handynummer ist zu lang. Verwende maximal 40 Zeichen." +msgid "validation.mobile.required" +msgstr "Bitte gebe deine Handynummer an." -msgid "validation.dect.optional" -msgstr "Der von dir eingegebene DECT-Nummer ist zu lang. Verwende maximal 40 Zeichen." +msgid "validation.dect.required" +msgstr "Bitte gebe deine DECT-Nummer an." msgid "validation.username.required" msgstr "Bitte gebe deinen Nick an." diff --git a/resources/lang/en_US/additional.po b/resources/lang/en_US/additional.po index dae46a16..7e52d6e2 100644 --- a/resources/lang/en_US/additional.po +++ b/resources/lang/en_US/additional.po @@ -21,20 +21,20 @@ msgstr "The password entered is too short." msgid "validation.login.required" msgstr "The login name is required." -msgid "validation.pronoun.length" -msgstr "The pronoun you have entered is too long. Use a maximum of 15 characters." +msgid "validation.pronoun.required" +msgstr "Please enter your pronoun." -msgid "validation.firstname.length" -msgstr "The first name you have entered is too long. Use a maximum of 64 characters." +msgid "validation.firstname.required" +msgstr "Please enter your first name." -msgid "validation.lastname.length" -msgstr "The last name you have entered is too long. Use a maximum of 64 characters." +msgid "validation.lastname.required" +msgstr "Please enter your last name." -msgid "validation.mobile.optional" -msgstr "The mobile number you have entered is too long. Use a maximum of 40 characters." +msgid "validation.mobile.required" +msgstr "Please enter your mobile number." -msgid "validation.dect.optional" -msgstr "The DECT number you have entered is too long. Use a maximum of 40 characters." +msgid "validation.dect.required" +msgstr "Please enter your DECT number." msgid "validation.username.required" msgstr "Please enter your nick." diff --git a/resources/views/pages/settings/profile.twig b/resources/views/pages/settings/profile.twig index c82bcd6e..043f89dc 100644 --- a/resources/views/pages/settings/profile.twig +++ b/resources/views/pages/settings/profile.twig @@ -28,6 +28,8 @@ {{ f.input('pronoun', __('settings.profile.pronoun'), { 'value': user.personalData.pronoun, 'max_length': 15, + 'required': isPronounRequired, + 'required_icon': isPronounRequired, }) }} {{ m.info(__('settings.profile.pronoun.info')) }} @@ -40,12 +42,16 @@ {{ f.input('first_name', __('settings.profile.firstname'), { 'value': user.personalData.first_name, 'max_length': 64, + 'required': isFirstnameRequired, + 'required_icon': isFirstnameRequired, }) }}
{{ f.input('last_name', __('settings.profile.lastname'), { 'value': user.personalData.last_name, 'max_length': 64, + 'required': isLastnameRequired, + 'required_icon': isLastnameRequired, }) }}
@@ -82,6 +88,8 @@ {{ f.input('dect', __('general.dect'), { 'value': user.contact.dect, 'max_length': 40, + 'required': isDectRequired, + 'required_icon': isDectRequired, }) }} {% endif %} @@ -89,6 +97,8 @@ {{ f.input('mobile', __('settings.profile.mobile'), { 'value': user.contact.mobile, 'max_length': 40, + 'required': isMobileRequired, + 'required_icon': isMobileRequired, }) }} {% if config('enable_mobile_show') %} {{ f.checkbox('mobile_show', __('settings.profile.mobile_show'), { @@ -141,8 +151,8 @@
{{ f.select('shirt_size', __('settings.profile.shirt_size'), config('tshirt_sizes'), { 'selected': user.personalData.shirt_size, - 'required': true, - 'required_icon': true, + 'required': isTShirtSizeRequired, + 'required_icon': isTShirtSizeRequired, 'default_option': __('form.select_placeholder'), }) }}
diff --git a/resources/views/pages/sign-up.twig b/resources/views/pages/sign-up.twig index eb4d2196..c9e177f6 100644 --- a/resources/views/pages/sign-up.twig +++ b/resources/views/pages/sign-up.twig @@ -31,6 +31,8 @@ __('settings.profile.pronoun'), { 'max_length': 15, + 'required': isPronounRequired, + 'required_icon': isPronounRequired, 'value': f.formData('pronoun', ''), } ) }} @@ -162,6 +164,8 @@ { 'autocomplete': 'given-name', 'max_length': 64, + 'required': isFirstnameRequired, + 'required_icon': isFirstnameRequired, 'value': f.formData('firstname', ''), } ) }} @@ -173,6 +177,8 @@ { 'autocomplete': 'family-name', 'max_length': 64, + 'required': isLastnameRequired, + 'required_icon': isLastnameRequired, 'value': f.formData('lastname', ''), } ) }} @@ -227,8 +233,8 @@ tShirtSizes, { 'default_option': __('form.select_placeholder'), - 'required': true, - 'required_icon': true, + 'required': isTShirtSizeRequired, + 'required_icon': isTShirtSizeRequired, 'selected': f.formData('tshirt_size', ''), } ) }} @@ -242,6 +248,8 @@ { 'type': 'tel-national', 'max_length': 40, + 'required': isMobileRequired, + 'required_icon': isMobileRequired, 'value': f.formData('mobile', ''), } ) }} @@ -265,6 +273,8 @@ { 'type': 'tel-local', 'max_length': 40, + 'required': isDectRequired, + 'required_icon': isDectRequired, 'value': f.formData('dect', ''), } ) }} diff --git a/src/Controllers/SettingsController.php b/src/Controllers/SettingsController.php index 916d0aec..d64a3aee 100644 --- a/src/Controllers/SettingsController.php +++ b/src/Controllers/SettingsController.php @@ -35,6 +35,7 @@ class SettingsController extends BaseController public function profile(): Response { $user = $this->auth->user(); + $requiredFields = $this->config->get('signup_required_fields'); return $this->response->withView( 'pages/settings/profile', @@ -43,6 +44,12 @@ class SettingsController extends BaseController 'user' => $user, 'goodie_tshirt' => $this->config->get('goodie_type') === GoodieType::Tshirt->value, 'goodie_enabled' => $this->config->get('goodie_type') !== GoodieType::None->value, + 'isPronounRequired' => $requiredFields['pronoun'], + 'isFirstnameRequired' => $requiredFields['firstname'], + 'isLastnameRequired' => $requiredFields['lastname'], + 'isTShirtSizeRequired' => $requiredFields['tshirt_size'], + 'isMobileRequired' => $requiredFields['mobile'], + 'isDectRequired' => $requiredFields['dect'], ] ); } @@ -359,6 +366,12 @@ class SettingsController extends BaseController return true; } + private function isRequired(string $key): string + { + $requiredFields = $this->config->get('signup_required_fields'); + return $requiredFields[$key] ? 'required' : 'optional'; + } + /** * @return string[] */ @@ -366,11 +379,12 @@ class SettingsController extends BaseController { $goodie_tshirt = $this->config->get('goodie_type') === GoodieType::Tshirt->value; $rules = [ - 'pronoun' => 'optional|max:15', - 'first_name' => 'optional|max:64', - 'last_name' => 'optional|max:64', - 'dect' => 'optional|length:0:40', // dect/mobile can be purely numbers. "max" would have - 'mobile' => 'optional|length:0:40', // checked their values, not their character length. + 'pronoun' => $this->isRequired('pronoun') . '|max:15', + 'first_name' => $this->isRequired('firstname') . '|max:64', + 'last_name' => $this->isRequired('lastname') . '|max:64', + 'dect' => $this->isRequired('dect') . '|length:0:40', + // dect/mobile can be purely numbers. "max" would have checked their values, not their character length. + 'mobile' => $this->isRequired('mobile') . '|length:0:40', 'mobile_show' => 'optional|checked', 'email' => 'required|email|max:254', 'email_shiftinfo' => 'optional|checked', @@ -384,7 +398,7 @@ class SettingsController extends BaseController $rules['planned_departure_date'] = 'optional|date:Y-m-d'; } if ($goodie_tshirt) { - $rules['shirt_size'] = 'required|shirt_size'; + $rules['shirt_size'] = $this->isRequired('tshirt_size') . '|shirt_size'; } return $rules; } diff --git a/src/Controllers/SignUpController.php b/src/Controllers/SignUpController.php index 51e34b2b..ed634fc7 100644 --- a/src/Controllers/SignUpController.php +++ b/src/Controllers/SignUpController.php @@ -79,6 +79,7 @@ class SignUpController extends BaseController { $goodieType = GoodieType::from($this->config->get('goodie_type')); $preselectedAngelTypes = $this->determinePreselectedAngelTypes(); + $requiredFields = $this->config->get('signup_required_fields'); // form-data-register-submit is a marker, that the form was submitted. // It will be used for instance to use the default angel types or the user selected ones. @@ -101,6 +102,12 @@ class SignUpController extends BaseController 'isPronounEnabled' => $this->config->get('enable_pronoun'), 'isFullNameEnabled' => $this->config->get('enable_user_name'), 'isPlannedArrivalDateEnabled' => $this->config->get('enable_planned_arrival'), + 'isPronounRequired' => $requiredFields['pronoun'], + 'isFirstnameRequired' => $requiredFields['firstname'], + 'isLastnameRequired' => $requiredFields['lastname'], + 'isTShirtSizeRequired' => $requiredFields['tshirt_size'], + 'isMobileRequired' => $requiredFields['mobile'], + 'isDectRequired' => $requiredFields['dect'], ], ); } diff --git a/src/Factories/User.php b/src/Factories/User.php index 44f971a5..4fbd4e66 100644 --- a/src/Factories/User.php +++ b/src/Factories/User.php @@ -67,6 +67,12 @@ class User return $this->config->get('buildup_start') ?? CarbonImmutable::now(); } + private function isRequired(string $key): string + { + $requiredFields = $this->config->get('signup_required_fields'); + return $requiredFields[$key] ? 'required' : 'optional'; + } + /** * @param Array $rawData * @throws ValidationException @@ -82,7 +88,7 @@ class User 'email_news' => 'optional|checked', 'email_goody' => 'optional|checked', // Using length here, because min/max would validate dect/mobile as numbers. - 'mobile' => 'optional|length:0:40', + 'mobile' => $this->isRequired('mobile') . '|length:0:40', ]; $isPasswordEnabled = $this->determineIsPasswordEnabled(); @@ -96,14 +102,14 @@ class User $isFullNameEnabled = $this->config->get('enable_user_name'); if ($isFullNameEnabled) { - $validationRules['firstname'] = 'optional|length:0:64'; - $validationRules['lastname'] = 'optional|length:0:64'; + $validationRules['firstname'] = $this->isRequired('firstname') . '|length:0:64'; + $validationRules['lastname'] = $this->isRequired('lastname') . '|length:0:64'; } $isPronounEnabled = $this->config->get('enable_pronoun'); if ($isPronounEnabled) { - $validationRules['pronoun'] = 'optional|max:15'; + $validationRules['pronoun'] = $this->isRequired('pronoun') . '|max:15'; } $isShowMobileEnabled = $this->config->get('enable_mobile_show'); @@ -137,14 +143,14 @@ class User if ($isDECTEnabled) { // Using length here, because min/max would validate dect/mobile as numbers. - $validationRules['dect'] = 'optional|length:0:40'; + $validationRules['dect'] = $this->isRequired('dect') . '|length:0:40'; } $goodieType = GoodieType::from($this->config->get('goodie_type')); $isGoodieTShirt = $goodieType === GoodieType::Tshirt; if ($isGoodieTShirt) { - $validationRules['tshirt_size'] = 'required|shirt-size'; + $validationRules['tshirt_size'] = $this->isRequired('tshirt_size') . '|shirt-size'; } $data = $this->validate($rawData, $validationRules); diff --git a/tests/Unit/Controllers/SettingsControllerTest.php b/tests/Unit/Controllers/SettingsControllerTest.php index f09f018e..89354e38 100644 --- a/tests/Unit/Controllers/SettingsControllerTest.php +++ b/tests/Unit/Controllers/SettingsControllerTest.php @@ -106,6 +106,7 @@ class SettingsControllerTest extends ControllerTest /** * @covers \Engelsystem\Controllers\SettingsController::saveProfile * @covers \Engelsystem\Controllers\SettingsController::getSaveProfileRules + * @covers \Engelsystem\Controllers\SettingsController::isRequired */ public function testSaveProfile(): void { @@ -934,12 +935,21 @@ class SettingsControllerTest extends ControllerTest 'de_DE' => 'Deutsch', ]; $tshirt_sizes = ['S' => 'Small']; + $requiredFields = [ + 'pronoun' => false, + 'firstname' => false, + 'lastname' => false, + 'tshirt_size' => true, + 'mobile' => false, + 'dect' => false, + ]; $this->config = new Config([ 'min_password_length' => 6, 'themes' => $themes, 'locales' => $languages, 'tshirt_sizes' => $tshirt_sizes, 'goodie_type' => GoodieType::Goodie->value, + 'signup_required_fields' => $requiredFields, ]); $this->app->instance('config', $this->config); $this->app->instance(Config::class, $this->config); diff --git a/tests/Utils/SignUpConfig.php b/tests/Utils/SignUpConfig.php index 5a9aeb6b..5f97c7cf 100644 --- a/tests/Utils/SignUpConfig.php +++ b/tests/Utils/SignUpConfig.php @@ -11,6 +11,14 @@ final class SignUpConfig { public static function setMaximumConfig(Config $config): void { + $requiredFields = [ + 'pronoun' => false, + 'firstname' => false, + 'lastname' => false, + 'tshirt_size' => true, + 'mobile' => false, + 'dect' => false, + ]; $config->set('registration_enabled', true); $config->set('enable_password', true); $config->set('enable_pronoun', true); @@ -27,10 +35,25 @@ final class SignUpConfig $config->set('enable_user_name', true); $config->set('enable_mobile_show', true); $config->set('enable_dect', true); + $config->set('signup_required_fields', $requiredFields); } public static function setMinimumConfig(Config $config): void { + $requiredFields = [ + 'pronoun' => false, + 'firstname' => false, + 'lastname' => false, + 'tshirt_size' => true, + 'mobile' => false, + 'dect' => false, + ]; + $requiredFields['pronoun'] = false; + $requiredFields['firstname'] = false; + $requiredFields['lastname'] = false; + $requiredFields['tshirt_size'] = true; + $requiredFields['mobile'] = false; + $requiredFields['dect'] = false; $config->set('registration_enabled', true); $config->set('enable_password', true); $config->set('enable_pronoun', false); @@ -43,5 +66,6 @@ final class SignUpConfig $config->set('enable_user_name', false); $config->set('enable_mobile_show', false); $config->set('enable_dect', false); + $config->set('signup_required_fields', $requiredFields); } }