user() !== null; } public function rules(): array { $validation = (array) config('nova_cards.validation', []); return [ 'title' => ['sometimes', 'string', 'min:2', 'max:' . (int) ($validation['title_max'] ?? 120)], 'quote_text' => ['sometimes', 'string', 'min:' . (int) ($validation['quote_min'] ?? 3), 'max:' . (int) ($validation['quote_max'] ?? 420)], 'quote_author' => ['sometimes', 'nullable', 'string', 'max:160'], 'quote_source' => ['sometimes', 'nullable', 'string', 'max:180'], 'description' => ['sometimes', 'nullable', 'string', 'max:' . (int) ($validation['description_max'] ?? 500)], 'format' => ['sometimes', Rule::in(array_keys((array) config('nova_cards.formats', [])))], 'template_id' => ['sometimes', 'nullable', 'integer', 'exists:nova_card_templates,id'], 'category_id' => ['sometimes', 'nullable', 'integer', 'exists:nova_card_categories,id'], 'background_type' => ['sometimes', Rule::in(['gradient', 'upload', 'template', 'solid'])], 'background_image_id' => ['sometimes', 'nullable', 'integer', 'exists:nova_card_backgrounds,id'], 'visibility' => ['sometimes', Rule::in([NovaCard::VISIBILITY_PUBLIC, NovaCard::VISIBILITY_UNLISTED, NovaCard::VISIBILITY_PRIVATE])], 'allow_download' => ['sometimes', 'boolean'], 'allow_remix' => ['sometimes', 'boolean'], 'editor_mode_last_used' => ['sometimes', Rule::in(['quick', 'full'])], 'tags' => ['sometimes', 'array', 'max:' . (int) ($validation['max_tags'] ?? 8)], 'tags.*' => ['string', 'min:2', 'max:32'], 'project_json' => ['sometimes', 'array'], 'project_json.schema_version' => ['sometimes', 'integer', 'min:1', 'max:9'], 'project_json.text_blocks' => ['sometimes', 'array', 'max:' . (int) ($validation['max_text_blocks'] ?? 8)], 'project_json.text_blocks.*.key' => ['sometimes', 'string', 'max:40'], 'project_json.text_blocks.*.type' => ['sometimes', Rule::in(['title', 'quote', 'author', 'source', 'body', 'caption'])], 'project_json.text_blocks.*.text' => ['sometimes', 'nullable', 'string', 'max:' . (int) ($validation['quote_max'] ?? 420)], 'project_json.text_blocks.*.enabled' => ['sometimes', 'boolean'], 'project_json.assets.pack_ids' => ['sometimes', 'array'], 'project_json.assets.pack_ids.*' => ['integer'], 'project_json.assets.template_pack_ids' => ['sometimes', 'array'], 'project_json.assets.template_pack_ids.*' => ['integer'], 'project_json.assets.items' => ['sometimes', 'array', 'max:' . (int) ($validation['max_asset_items'] ?? 12)], 'project_json.assets.items.*.asset_key' => ['sometimes', 'string', 'max:80'], 'project_json.assets.items.*.label' => ['sometimes', 'string', 'max:120'], 'project_json.assets.items.*.glyph' => ['sometimes', 'string', 'max:4'], 'project_json.layout.alignment' => ['sometimes', Rule::in((array) ($validation['allowed_alignments'] ?? ['left', 'center', 'right']))], 'project_json.layout.layout' => ['sometimes', Rule::in((array) ($validation['allowed_layouts'] ?? []))], 'project_json.layout.position' => ['sometimes', Rule::in((array) ($validation['allowed_positions'] ?? []))], 'project_json.layout.padding' => ['sometimes', Rule::in((array) ($validation['allowed_padding_presets'] ?? []))], 'project_json.layout.max_width' => ['sometimes', Rule::in((array) ($validation['allowed_max_widths'] ?? []))], 'project_json.typography.font_preset' => ['sometimes', Rule::in(array_keys((array) config('nova_cards.font_presets', [])))], 'project_json.typography.quote_size' => ['sometimes', 'integer', 'min:24', 'max:160'], 'project_json.typography.author_size' => ['sometimes', 'integer', 'min:12', 'max:72'], 'project_json.typography.letter_spacing' => ['sometimes', 'integer', 'min:-2', 'max:12'], 'project_json.typography.line_height' => ['sometimes', 'numeric', 'min:0.9', 'max:1.8'], 'project_json.typography.shadow_preset' => ['sometimes', Rule::in(array_column((array) config('nova_cards.shadow_presets', []), 'key'))], 'project_json.typography.text_color' => ['sometimes', 'regex:/^#(?:[0-9a-fA-F]{3}){1,2}$/'], 'project_json.typography.accent_color' => ['sometimes', 'regex:/^#(?:[0-9a-fA-F]{3}){1,2}$/'], 'project_json.background.type' => ['sometimes', Rule::in(['gradient', 'upload', 'template', 'solid'])], 'project_json.background.gradient_preset' => ['sometimes', Rule::in(array_keys((array) config('nova_cards.gradient_presets', [])))], 'project_json.background.gradient_colors' => ['sometimes', 'array', 'min:2', 'max:3'], 'project_json.background.gradient_colors.*' => ['regex:/^#(?:[0-9a-fA-F]{3}){1,2}$/'], 'project_json.background.solid_color' => ['sometimes', 'regex:/^#(?:[0-9a-fA-F]{3}){1,2}$/'], 'project_json.background.overlay_style' => ['sometimes', Rule::in((array) ($validation['allowed_overlay_styles'] ?? []))], 'project_json.background.focal_position' => ['sometimes', Rule::in(array_column((array) config('nova_cards.focal_positions', []), 'key'))], 'project_json.background.blur_level' => ['sometimes', Rule::in((array) ($validation['allowed_blur_levels'] ?? []))], 'project_json.background.opacity' => ['sometimes', Rule::in((array) ($validation['allowed_opacity_levels'] ?? []))], 'project_json.source_context.editor_mode' => ['sometimes', Rule::in(['quick', 'full'])], 'project_json.decorations' => ['sometimes', 'array', 'max:' . (int) ($validation['max_decorations'] ?? 6)], 'project_json.decorations.*.key' => ['sometimes', 'string', 'max:40'], 'project_json.decorations.*.glyph' => ['sometimes', 'string', 'max:4'], 'project_json.decorations.*.placement' => ['sometimes', 'string', 'max:24'], 'project_json.decorations.*.x' => ['sometimes', 'numeric', 'min:0', 'max:1920'], 'project_json.decorations.*.y' => ['sometimes', 'numeric', 'min:0', 'max:1920'], 'project_json.decorations.*.size' => ['sometimes', 'integer', 'min:2', 'max:120'], ]; } }