user('controlpanel') ?? $this->user()); } protected function prepareForValidation(): void { $this->merge([ 'is_active' => $this->boolean('is_active'), 'is_dismissible' => $this->boolean('is_dismissible', true), 'remove_background_image' => $this->boolean('remove_background_image'), 'priority' => $this->filled('priority') ? (int) $this->input('priority') : 0, 'dismiss_version' => $this->filled('dismiss_version') ? (int) $this->input('dismiss_version') : 1, 'overlay_opacity' => $this->filled('overlay_opacity') ? (int) $this->input('overlay_opacity') : 55, ]); } public function rules(): array { return [ 'title' => ['required', 'string', 'max:180'], 'subtitle' => ['nullable', 'string', 'max:255'], 'badge_text' => ['nullable', 'string', 'max:100'], 'content_html' => ['nullable', 'string'], 'type' => ['required', 'string', Rule::in(HomepageAnnouncement::types())], 'status' => ['required', 'string', Rule::in(HomepageAnnouncement::statuses())], 'is_active' => ['required', 'boolean'], 'starts_at' => ['nullable', 'date'], 'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'], 'priority' => ['required', 'integer', 'min:-9999', 'max:9999'], 'is_dismissible' => ['required', 'boolean'], 'dismiss_version' => ['required', 'integer', 'min:1', 'max:999999'], 'gradient_preset' => ['nullable', 'string', Rule::in(HomepageAnnouncement::gradientPresets())], 'theme_preset' => ['nullable', 'string', 'max:80'], 'placement' => ['required', 'string', Rule::in(HomepageAnnouncement::placements())], 'text_color' => ['nullable', 'string', 'max:32'], 'overlay_opacity' => ['nullable', 'integer', 'min:0', 'max:100'], 'background_image' => ['nullable', 'string', 'max:2048'], 'background_image_file' => ['nullable', 'file', 'image', 'mimes:jpeg,jpg,png,webp', 'max:5120'], 'remove_background_image' => ['nullable', 'boolean'], 'primary_link_label' => ['nullable', 'string', 'max:80'], 'primary_link_type' => ['nullable', 'string', Rule::in(HomepageAnnouncement::linkTypes())], 'primary_link_url' => ['nullable', 'string', 'max:2048'], 'primary_link_target_id' => ['nullable', 'integer', 'min:1'], 'secondary_link_label' => ['nullable', 'string', 'max:80'], 'secondary_link_type' => ['nullable', 'string', Rule::in(HomepageAnnouncement::linkTypes())], 'secondary_link_url' => ['nullable', 'string', 'max:2048'], 'secondary_link_target_id' => ['nullable', 'integer', 'min:1'], ]; } public function withValidator($validator): void { $validator->after(function ($validator): void { $sanitizer = app(HomepageAnnouncementSanitizer::class); foreach (['primary', 'secondary'] as $prefix) { $type = (string) ($this->input($prefix . '_link_type') ?: HomepageAnnouncement::LINK_TYPE_NONE); $label = trim((string) $this->input($prefix . '_link_label', '')); $url = trim((string) $this->input($prefix . '_link_url', '')); $targetId = (int) $this->input($prefix . '_link_target_id', 0); if ($url !== '' && ! $sanitizer->isSafeCustomUrl($url)) { $validator->errors()->add($prefix . '_link_url', 'Use a relative path starting with / or an https:// URL. Unsafe protocols are not allowed.'); } if ($type !== HomepageAnnouncement::LINK_TYPE_NONE && $label === '') { $validator->errors()->add($prefix . '_link_label', 'Provide a CTA label when this link is enabled.'); } if ($type === HomepageAnnouncement::LINK_TYPE_CUSTOM_URL && $url === '') { $validator->errors()->add($prefix . '_link_url', 'Provide a URL for custom links.'); } if (! in_array($type, [HomepageAnnouncement::LINK_TYPE_NONE, HomepageAnnouncement::LINK_TYPE_CUSTOM_URL, HomepageAnnouncement::LINK_TYPE_EXPLORE, HomepageAnnouncement::LINK_TYPE_UPLOAD], true) && $url === '' && $targetId < 1) { $validator->errors()->add($prefix . '_link_target_id', 'Provide a target id or a fallback URL for this CTA type.'); } } }); } }