Skip to content

Commit c6af52a

Browse files
committed
feat: csv file helper
1 parent 9582612 commit c6af52a

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

src/CsvFile.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yajra\SQLLoader;
6+
7+
final class CsvFile
8+
{
9+
/**
10+
* @param resource $stream
11+
*/
12+
private function __construct(public string $file, public $stream)
13+
{
14+
}
15+
16+
public static function make(string $filename, string $mode): CsvFile
17+
{
18+
if (! file_exists($filename)) {
19+
$filename = self::create($filename);
20+
}
21+
22+
$stream = fopen($filename, $mode);
23+
24+
if ($stream === false) {
25+
throw new \RuntimeException("Failed to open file [{$filename}].");
26+
}
27+
28+
return new self($filename, $stream);
29+
}
30+
31+
public static function create(string $file): string
32+
{
33+
$stream = fopen($file, 'w');
34+
if ($stream === false) {
35+
throw new \RuntimeException('Could not open file for writing: '.$file);
36+
}
37+
fclose($stream);
38+
39+
return $file;
40+
}
41+
42+
public static function blank(string $file): string
43+
{
44+
if (file_exists($file)) {
45+
unlink($file);
46+
}
47+
48+
return self::create($file);
49+
}
50+
51+
public function close(): void
52+
{
53+
$this->__destruct();
54+
}
55+
56+
public function __destruct()
57+
{
58+
if (is_resource($this->stream)) {
59+
fclose($this->stream);
60+
}
61+
}
62+
63+
public function headers(array $fields): CsvFile
64+
{
65+
if ($this->isEmpty()) {
66+
$this->append(array_keys($fields));
67+
}
68+
69+
$this->append($fields);
70+
71+
return $this;
72+
}
73+
74+
public function isEmpty(): bool
75+
{
76+
clearstatcache(true, $this->file);
77+
78+
return filesize($this->file) === 0;
79+
}
80+
81+
public function append(
82+
array $fields,
83+
string $separator = ',',
84+
string $enclosure = '"',
85+
string $escape = '\\',
86+
string $eol = PHP_EOL
87+
): CsvFile {
88+
fputcsv($this->stream, $fields, $separator, $enclosure, $escape, $eol);
89+
90+
return $this;
91+
}
92+
93+
public function insert(array $updates): CsvFile
94+
{
95+
foreach ($updates as $row) {
96+
$this->append($row);
97+
}
98+
99+
return $this;
100+
}
101+
102+
public function get(): string
103+
{
104+
$contents = file_get_contents($this->file);
105+
106+
if ($contents === false) {
107+
return '';
108+
}
109+
110+
return $contents;
111+
}
112+
}

tests/Feature/CsvFileTest.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
use Yajra\SQLLoader\CsvFile;
4+
5+
test('it can create a blank csv file', function () {
6+
$file = CsvFile::blank(storage_path('test.csv'));
7+
8+
expect($file)->toBeString()
9+
->and($file)->toBe(storage_path('test.csv'))
10+
->and(file_exists($file))->toBeTrue();
11+
});
12+
13+
test('it can create a csv file', function () {
14+
$file = CsvFile::create(storage_path('test.csv'));
15+
16+
expect($file)->toBeString()
17+
->and($file)->toBe(storage_path('test.csv'))
18+
->and(file_exists($file))->toBeTrue();
19+
});
20+
21+
test('it can make a csv file with array content', function () {
22+
$file = CsvFile::make(storage_path('test.csv'), 'w');
23+
$file->append(['id', 'name', 'email']);
24+
25+
expect($file)->toBeInstanceOf(CsvFile::class)
26+
->and($file->isEmpty())->toBeFalse()
27+
->and($file->get())->toContain('id,name,email'.PHP_EOL);
28+
});
29+
30+
test('it can have a csv header', function () {
31+
$file = CsvFile::make(storage_path('test.csv'), 'w');
32+
$file->headers(['id', 'name', 'email']);
33+
34+
expect($file)->toBeInstanceOf(CsvFile::class)
35+
->and($file->isEmpty())->toBeFalse()
36+
->and($file->get())->toContain('id,name,email'.PHP_EOL);
37+
});
38+
39+
test('it can insert data using array', function () {
40+
$file = CsvFile::make(storage_path('test.csv'), 'w');
41+
$file->headers(['id', 'name', 'email']);
42+
$file->insert([
43+
['1', 'John Doe', '[email protected]'],
44+
['2', 'Jane Doe', 'e'],
45+
['3', 'Jane, Doe', '3'],
46+
['3', 'Jane" Doe', '3'],
47+
]);
48+
49+
$content = $file->get();
50+
51+
expect($file)->toBeInstanceOf(CsvFile::class)
52+
->and($file->isEmpty())->toBeFalse()
53+
->and($content)->toContain('1,"John Doe",[email protected]'.PHP_EOL)
54+
->and($content)->toContain('2,"Jane Doe",e'.PHP_EOL)
55+
->and($content)->toContain('3,"Jane, Doe",3'.PHP_EOL)
56+
->and($content)->toContain('3,"Jane"" Doe",3'.PHP_EOL);
57+
});

0 commit comments

Comments
 (0)