Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
CsvExportService
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 resolveDelimiter
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 downloadWithUserDelimiter
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Http\Services;
4
5use App\Http\Models\Auth\User;
6use App\Http\Repositories\UserSettingRepository;
7use Symfony\Component\HttpFoundation\StreamedResponse;
8use Vitorccs\LaravelCsv\Entities\CsvConfig;
9
10/**
11 * Service for applying user-specific CSV delimiter settings to exports.
12 *
13 * Reads the user's `csv_split_separator` setting and applies it as the
14 * CSV delimiter for both V1 (Vitorccs LaravelCSV) and V2 (native fputcsv) exports.
15 */
16class CsvExportService
17{
18    public function __construct(
19        private UserSettingRepository $settingRepository
20    ) {}
21
22    /**
23     * Resolve the CSV delimiter for a given user.
24     *
25     * Returns the user's `csv_split_separator` setting if it is a valid
26     * single character. Falls back to comma (`,`) otherwise.
27     *
28     * @param  User  $user  The authenticated user
29     * @return string A single-character CSV delimiter
30     */
31    public function resolveDelimiter(User $user): string
32    {
33        $setting = $this->settingRepository->findByUserId($user->getKey());
34
35        if (! $setting) {
36            return ',';
37        }
38
39        $separator = $setting->csv_split_separator;
40
41        if (! is_string($separator) || mb_strlen($separator) !== 1) {
42            return ',';
43        }
44
45        return $separator;
46    }
47
48    /**
49     * Download a V1 (Vitorccs LaravelCSV) export using the user's delimiter.
50     *
51     * Temporarily overrides the CsvConfig singleton's `csv_delimiter` property
52     * for the duration of the export callback, then restores the original value.
53     *
54     * @param  User  $user  The authenticated user
55     * @param  callable  $exportCallback  A callable that returns a StreamedResponse (e.g., `fn() => $export->download('file.csv')`)
56     */
57    public function downloadWithUserDelimiter(User $user, callable $exportCallback): StreamedResponse
58    {
59        $csvConfig = app(CsvConfig::class);
60        $originalDelimiter = $csvConfig->csv_delimiter;
61
62        try {
63            $csvConfig->csv_delimiter = $this->resolveDelimiter($user);
64
65            return $exportCallback();
66        } finally {
67            $csvConfig->csv_delimiter = $originalDelimiter;
68        }
69    }
70}