Skip to content

Commit 712b4fc

Browse files
committed
Feat: putcsv custom delimiter
1 parent 5bc20a5 commit 712b4fc

File tree

6 files changed

+202
-14
lines changed

6 files changed

+202
-14
lines changed

include/csv.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
#ifndef PHP_EXT_XLS_WRITER_CSV_H
1414
#define PHP_EXT_XLS_WRITER_CSV_H
1515

16-
unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache);
16+
unsigned int xlsx_to_csv(
17+
zval *stream_resource,
18+
const char *delimiter_str, int delimiter_str_len,
19+
const char *enclosure_str, int enclosure_str_len,
20+
const char *escape_str, int escape_str_len,
21+
xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
22+
);
1723

1824
#endif // PHP_EXT_XLS_WRITER_CSV_H

kernel/csv.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@
1515
#include "ext/standard/file.h"
1616

1717
/* {{{ */
18-
unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
18+
unsigned int xlsx_to_csv(
19+
zval *stream_resource,
20+
const char *delimiter_str, int delimiter_str_len,
21+
const char *enclosure_str, int enclosure_str_len,
22+
const char *escape_str, int escape_str_len,
23+
xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
24+
)
1925
{
20-
zval *_zv_type_arr_t = NULL;
21-
php_stream *_stream_t;
22-
2326
ssize_t ret = 0;
24-
char delimiter = ',';
25-
char enclosure = '"';
26-
int escape_char = (unsigned char) '\\';
27+
zval *_zv_type_arr_t = NULL;
28+
php_stream *_stream_t = NULL;
29+
char delimiter = ',', enclosure = '"', escape_char = '\\';
2730

2831
ZEND_ASSERT(Z_TYPE_P(stream_resource) == IS_RESOURCE);
2932

@@ -32,6 +35,42 @@ unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval
3235
return XLSWRITER_FALSE;
3336
}
3437

38+
if (delimiter_str != NULL) {
39+
if (delimiter_str_len < 1) {
40+
zend_throw_exception(vtiful_exception_ce, "delimiter must be a character", 190);
41+
return XLSWRITER_FALSE;
42+
} else if (delimiter_str_len > 1) {
43+
zend_throw_exception(vtiful_exception_ce, "delimiter must be a single character", 191);
44+
return XLSWRITER_FALSE;
45+
}
46+
47+
delimiter = *delimiter_str;
48+
}
49+
50+
if (enclosure_str != NULL) {
51+
if (enclosure_str_len < 1) {
52+
zend_throw_exception(vtiful_exception_ce, "enclosure must be a character", 192);
53+
return XLSWRITER_FALSE;
54+
} else if (enclosure_str_len > 1) {
55+
zend_throw_exception(vtiful_exception_ce, "enclosure must be a single character", 193);
56+
return XLSWRITER_FALSE;
57+
}
58+
59+
enclosure = *enclosure_str;
60+
}
61+
62+
if (escape_str != NULL) {
63+
if (escape_str_len < 1) {
64+
zend_throw_exception(vtiful_exception_ce, "escape must be a character", 194);
65+
return XLSWRITER_FALSE;
66+
} else if (escape_str_len > 1) {
67+
zend_throw_exception(vtiful_exception_ce, "escape must be a single character", 195);
68+
return XLSWRITER_FALSE;
69+
}
70+
71+
escape_char = *escape_str;
72+
}
73+
3574
if (Z_TYPE_P(zv_type_arr_t) == IS_ARRAY) {
3675
_zv_type_arr_t = zv_type_arr_t;
3776
}

kernel/excel.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,17 @@ ZEND_END_ARG_INFO()
176176

177177
ZEND_BEGIN_ARG_INFO_EX(xls_put_csv_arginfo, 0, 0, 1)
178178
ZEND_ARG_INFO(0, fp)
179+
ZEND_ARG_INFO(0, delimiter_str)
180+
ZEND_ARG_INFO(0, enclosure_str)
181+
ZEND_ARG_INFO(0, escape_str)
179182
ZEND_END_ARG_INFO()
180183

181184
ZEND_BEGIN_ARG_INFO_EX(xls_put_csv_callback_arginfo, 0, 0, 2)
182185
ZEND_ARG_INFO(0, callback)
183186
ZEND_ARG_INFO(0, fp)
187+
ZEND_ARG_INFO(0, delimiter_str)
188+
ZEND_ARG_INFO(0, enclosure_str)
189+
ZEND_ARG_INFO(0, escape_str)
184190
ZEND_END_ARG_INFO()
185191

186192
ZEND_BEGIN_ARG_INFO_EX(xls_set_type_arginfo, 0, 0, 1)
@@ -991,10 +997,16 @@ PHP_METHOD(vtiful_xls, setType)
991997
*/
992998
PHP_METHOD(vtiful_xls, putCSV)
993999
{
994-
zval *fp = NULL, *zv_type = NULL;;
1000+
zval *fp = NULL, *zv_type = NULL;
1001+
char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
1002+
size_t delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
9951003

996-
ZEND_PARSE_PARAMETERS_START(1, 1)
1004+
ZEND_PARSE_PARAMETERS_START(1, 4)
9971005
Z_PARAM_RESOURCE(fp)
1006+
Z_PARAM_OPTIONAL
1007+
Z_PARAM_STRING(delimiter_str, delimiter_str_len)
1008+
Z_PARAM_STRING(enclosure_str, enclosure_str_len)
1009+
Z_PARAM_STRING(escape_str,escape_str_len)
9981010
ZEND_PARSE_PARAMETERS_END();
9991011

10001012
xls_object *obj = Z_XLS_P(getThis());
@@ -1005,7 +1017,10 @@ PHP_METHOD(vtiful_xls, putCSV)
10051017

10061018
zv_type = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
10071019

1008-
if (xlsx_to_csv(fp, obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, NULL, NULL) == XLSWRITER_TRUE) {
1020+
if (xlsx_to_csv(
1021+
fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
1022+
obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, NULL, NULL
1023+
) == XLSWRITER_TRUE) {
10091024
RETURN_TRUE;
10101025
}
10111026

@@ -1018,12 +1033,18 @@ PHP_METHOD(vtiful_xls, putCSV)
10181033
PHP_METHOD(vtiful_xls, putCSVCallback)
10191034
{
10201035
zval *fp = NULL, *zv_type = NULL;
1021-
zend_fcall_info fci = empty_fcall_info;
1036+
zend_fcall_info fci = empty_fcall_info;
10221037
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
1038+
char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
1039+
size_t delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
10231040

1024-
ZEND_PARSE_PARAMETERS_START(2, 2)
1041+
ZEND_PARSE_PARAMETERS_START(2, 5)
10251042
Z_PARAM_FUNC(fci, fci_cache)
10261043
Z_PARAM_RESOURCE(fp)
1044+
Z_PARAM_OPTIONAL
1045+
Z_PARAM_STRING(delimiter_str, delimiter_str_len)
1046+
Z_PARAM_STRING(enclosure_str, enclosure_str_len)
1047+
Z_PARAM_STRING(escape_str,escape_str_len)
10271048
ZEND_PARSE_PARAMETERS_END();
10281049

10291050
xls_object *obj = Z_XLS_P(getThis());
@@ -1034,7 +1055,10 @@ PHP_METHOD(vtiful_xls, putCSVCallback)
10341055

10351056
zv_type = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
10361057

1037-
if (xlsx_to_csv(fp, obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, &fci, &fci_cache) == XLSWRITER_TRUE) {
1058+
if (xlsx_to_csv(
1059+
fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
1060+
obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, &fci, &fci_cache
1061+
) == XLSWRITER_TRUE) {
10381062
RETURN_TRUE;
10391063
}
10401064

package.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
<file md5sum="39f7c511d9019c6815bcf7fd0f7e8224" name="tests/chart_style.phpt" role="test" />
182182
<file md5sum="bfdf9e054f8efd971a65d00eca465f2f" name="tests/chart_title.phpt" role="test" />
183183
<file md5sum="9badb50b14bd81536bafcfefcb5677d6" name="tests/column_index_from_string.phpt" role="test" />
184+
<file name="tests/const_memory_index_out_range.phpt" role="test" />
184185
<file name="tests/default_format.phpt" role="test" />
185186
<file name="tests/fix-207.phpt" role="test" />
186187
<file md5sum="df2a6af4ced4ea7660a1691d18e75e8c" name="tests/format_align.phpt" role="test" />
@@ -223,6 +224,8 @@
223224
<file md5sum="5811dd930d7b0f916c662139ff1053d4" name="tests/string_from_column_index.phpt" role="test" />
224225
<file md5sum="42b26f050d9291509d6f583ef43ebde9" name="tests/xlsx_to_csv.phpt" role="test" />
225226
<file name="tests/xlsx_to_csv_callback.phpt" role="test" />
227+
<file name="tests/xlsx_to_csv_callback_custom_delimiter.phpt" role="test" />
228+
<file name="tests/xlsx_to_csv_custom_delimiter.phpt" role="test" />
226229
<file md5sum="a9af7f4ca385ba41b008b50ac67f8e96" name="tests/zoom.phpt" role="test" />
227230
<file md5sum="f4a2d1a28ad1bf782502d698de0b1907" name="tests/include/skipif.inc" role="test" />
228231
<file md5sum="bb4256831dfd81f951bd6f4afbe1719f" name="CREDITS" role="doc" />
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
Check for vtiful presence
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/include/skipif.inc';
6+
skip_disable_reader();
7+
?>
8+
--FILE--
9+
<?php
10+
$config = ['path' => './tests'];
11+
$excel = new \Vtiful\Kernel\Excel($config);
12+
$filePath = $excel->fileName('tutorial.xlsx', 'TestSheet1')
13+
->header(['Item', 'Cost'])
14+
->data([
15+
['Item_1', 'Cost_1', 10, 10.9999995],
16+
])
17+
->output();
18+
19+
$fp = fopen('./tests/file.csv', 'w');
20+
21+
$csvResult = $excel->openFile('tutorial.xlsx')
22+
->openSheet()
23+
->putCSVCallback(function($row){
24+
return $row;
25+
}, $fp, ';');
26+
27+
var_dump($csvResult);
28+
29+
if (($csvHandler = fopen('./tests/file.csv', 'r')) === FALSE) {
30+
die('csv file open failure');
31+
}
32+
33+
while (($data = fgetcsv($csvHandler, 1000, ';')) !== FALSE) {
34+
var_dump($data);
35+
}
36+
?>
37+
--CLEAN--
38+
<?php
39+
@unlink(__DIR__ . '/tutorial.xlsx');
40+
@unlink(__DIR__ . '/file.csv');
41+
?>
42+
--EXPECT--
43+
bool(true)
44+
array(2) {
45+
[0]=>
46+
string(4) "Item"
47+
[1]=>
48+
string(4) "Cost"
49+
}
50+
array(4) {
51+
[0]=>
52+
string(6) "Item_1"
53+
[1]=>
54+
string(6) "Cost_1"
55+
[2]=>
56+
string(2) "10"
57+
[3]=>
58+
string(10) "10.9999995"
59+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
Check for vtiful presence
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/include/skipif.inc';
6+
skip_disable_reader();
7+
?>
8+
--FILE--
9+
<?php
10+
$config = ['path' => './tests'];
11+
$excel = new \Vtiful\Kernel\Excel($config);
12+
$filePath = $excel->fileName('tutorial.xlsx', 'TestSheet1')
13+
->header(['Item', 'Cost'])
14+
->data([
15+
['Item_1', 'Cost_1', 10, 10.9999995],
16+
])
17+
->output();
18+
19+
$fp = fopen('./tests/file.csv', 'w');
20+
21+
$csvResult = $excel->openFile('tutorial.xlsx')
22+
->openSheet()
23+
->putCSV($fp, ';');
24+
25+
var_dump($csvResult);
26+
27+
if (($csvHandler = fopen('./tests/file.csv', 'r')) === FALSE) {
28+
die('csv file open failure');
29+
}
30+
31+
while (($data = fgetcsv($csvHandler, 1000, ';')) !== FALSE) {
32+
var_dump($data);
33+
}
34+
?>
35+
--CLEAN--
36+
<?php
37+
@unlink(__DIR__ . '/tutorial.xlsx');
38+
@unlink(__DIR__ . '/file.csv');
39+
?>
40+
--EXPECT--
41+
bool(true)
42+
array(2) {
43+
[0]=>
44+
string(4) "Item"
45+
[1]=>
46+
string(4) "Cost"
47+
}
48+
array(4) {
49+
[0]=>
50+
string(6) "Item_1"
51+
[1]=>
52+
string(6) "Cost_1"
53+
[2]=>
54+
string(2) "10"
55+
[3]=>
56+
string(10) "10.9999995"
57+
}

0 commit comments

Comments
 (0)