Browse Source

Feat: set global type

viest 4 năm trước cách đây
mục cha
commit
2b8c3290da
7 tập tin đã thay đổi với 185 bổ sung18 xóa
  1. 3 1
      include/csv.h
  2. 3 3
      include/read.h
  3. 2 0
      include/xlswriter.h
  4. 4 2
      kernel/csv.c
  5. 41 6
      kernel/excel.c
  6. 14 6
      kernel/read.c
  7. 118 0
      tests/open_xlsx_global_data_type.phpt

+ 3 - 1
include/csv.h

@@ -18,7 +18,9 @@ unsigned int xlsx_to_csv(
         const char *delimiter_str, int delimiter_str_len,
         const char *enclosure_str, int enclosure_str_len,
         const char *escape_str, int escape_str_len,
-        xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
+        xlsxioreadersheet sheet_t,
+        zval *zv_type_arr_t, zend_long data_type_default,
+        unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
 );
 
 #endif // PHP_EXT_XLS_WRITER_CSV_H

+ 3 - 3
include/read.h

@@ -22,10 +22,10 @@ void data_to_null(zval *zv_result_t);
 int sheet_read_row(xlsxioreadersheet sheet_t);
 void sheet_list(xlsxioreader file_t, zval *zv_result_t);
 xlsxioreader file_open(const char *directory, const char *file_name);
-void skip_rows(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long zl_skip_row);
-void load_sheet_all_data(xlsxioreadersheet sheet_t, zval *zv_type_t, zval *zv_result_t);
+void skip_rows(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long data_type_default, zend_long zl_skip_row);
+void load_sheet_all_data(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long data_type_default, zval *zv_result_t);
 xlsxioreadersheet sheet_open(xlsxioreader file_t, const zend_string *zs_sheet_name_t, const zend_long zl_flag);
-unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type, unsigned int flag);
+unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type, zend_long data_type_default, unsigned int flag);
 unsigned int load_sheet_current_row_data_callback(zend_string *zs_sheet_name_t, xlsxioreader file_t, void *callback_data);
 void data_to_custom_type(const char *string_value, const size_t string_value_length, const zend_ulong type, zval *zv_result_t, const zend_ulong zv_hashtable_index);
 

+ 2 - 0
include/xlswriter.h

@@ -44,9 +44,11 @@
 typedef struct {
     xlsxioreader      file_t;
     xlsxioreadersheet sheet_t;
+    zend_long         data_type_default;
 } xls_resource_read_t;
 
 typedef struct {
+    zend_long             data_type_default;
     zval                  *zv_type_t;
     zend_fcall_info       *fci;
     zend_fcall_info_cache *fci_cache;

+ 4 - 2
kernel/csv.c

@@ -20,7 +20,9 @@ unsigned int xlsx_to_csv(
         const char *delimiter_str, int delimiter_str_len,
         const char *enclosure_str, int enclosure_str_len,
         const char *escape_str, int escape_str_len,
-        xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
+        xlsxioreadersheet sheet_t,
+        zval *zv_type_arr_t, zend_long data_type_default,
+        unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
 )
 {
     ssize_t ret = 0;
@@ -80,7 +82,7 @@ unsigned int xlsx_to_csv(
 
     while (sheet_read_row(sheet_t))
     {
-        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, _zv_type_arr_t, flag);
+        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, _zv_type_arr_t, data_type_default, flag);
 
         if (fci != NULL && fci_cache != NULL) {
             zval retval;

+ 41 - 6
kernel/excel.c

@@ -40,6 +40,8 @@ PHP_VTIFUL_API zend_object *vtiful_xls_objects_new(zend_class_entry *ce)
     intern->read_ptr.sheet_t  = NULL;
     intern->format_ptr.format = NULL;
 
+    intern->read_ptr.data_type_default = READ_TYPE_EMPTY;
+
     return &intern->zo;
 }
 /* }}} */
@@ -226,6 +228,10 @@ ZEND_BEGIN_ARG_INFO_EX(xls_set_type_arginfo, 0, 0, 1)
                 ZEND_ARG_INFO(0, zv_type_t)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(xls_set_global_type_arginfo, 0, 0, 1)
+                ZEND_ARG_INFO(0, zv_type_t)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(xls_set_skip_arginfo, 0, 0, 1)
                 ZEND_ARG_INFO(0, zv_skip_t)
 ZEND_END_ARG_INFO()
@@ -1154,6 +1160,33 @@ PHP_METHOD(vtiful_xls, setType)
 }
 /* }}} */
 
+/** {{{ \Vtiful\Kernel\Excel::setGlobalType(int $rowType)
+ */
+PHP_METHOD(vtiful_xls, setGlobalType)
+{
+    zend_long zl_type = 0;
+
+    ZEND_PARSE_PARAMETERS_START(1, 1)
+            Z_PARAM_LONG(zl_type)
+    ZEND_PARSE_PARAMETERS_END();
+
+    if (zl_type < READ_TYPE_STRING || zl_type > READ_TYPE_DATETIME) {
+        zend_throw_exception(vtiful_exception_ce, "Invalid data type", 220);
+        return;
+    }
+
+    if (zl_type != READ_TYPE_STRING && (zl_type % 2) != 0) {
+        zend_throw_exception(vtiful_exception_ce, "Invalid data type", 220);
+        return;
+    }
+
+    ZVAL_COPY(return_value, getThis());
+
+    xls_object* obj = Z_XLS_P(return_value);
+    obj->read_ptr.data_type_default = zl_type;
+}
+/* }}} */
+
 /** {{{ \Vtiful\Kernel\Excel::setSkipRows(int $skip)
  */
 PHP_METHOD(vtiful_xls, setSkipRows)
@@ -1172,7 +1205,7 @@ PHP_METHOD(vtiful_xls, setSkipRows)
         RETURN_FALSE;
     }
 
-    skip_rows(obj->read_ptr.sheet_t, NULL, zl_skip);
+    skip_rows(obj->read_ptr.sheet_t, NULL, obj->read_ptr.data_type_default, zl_skip);
 }
 /* }}} */
 
@@ -1202,7 +1235,7 @@ PHP_METHOD(vtiful_xls, putCSV)
 
     if (xlsx_to_csv(
             fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
-            obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, NULL, NULL
+            obj->read_ptr.sheet_t, zv_type, obj->read_ptr.data_type_default, READ_SKIP_ROW, NULL, NULL
             ) == XLSWRITER_TRUE) {
         RETURN_TRUE;
     }
@@ -1240,7 +1273,7 @@ PHP_METHOD(vtiful_xls, putCSVCallback)
 
     if (xlsx_to_csv(
             fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
-            obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, &fci, &fci_cache
+            obj->read_ptr.sheet_t, zv_type, obj->read_ptr.data_type_default, READ_SKIP_ROW, &fci, &fci_cache
             ) == XLSWRITER_TRUE) {
         RETURN_TRUE;
     }
@@ -1262,12 +1295,12 @@ PHP_METHOD(vtiful_xls, getSheetData)
     zval *zv_type = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
 
     if (zv_type != NULL && Z_TYPE_P(zv_type) == IS_ARRAY) {
-        load_sheet_all_data(obj->read_ptr.sheet_t, zv_type, return_value);
+        load_sheet_all_data(obj->read_ptr.sheet_t, zv_type, obj->read_ptr.data_type_default, return_value);
 
         return;
     }
 
-    load_sheet_all_data(obj->read_ptr.sheet_t, NULL, return_value);
+    load_sheet_all_data(obj->read_ptr.sheet_t, NULL, obj->read_ptr.data_type_default, return_value);
 }
 /* }}} */
 
@@ -1292,7 +1325,7 @@ PHP_METHOD(vtiful_xls, nextRow)
         zv_type_t = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
     }
 
-    load_sheet_current_row_data(obj->read_ptr.sheet_t, return_value, zv_type_t, READ_ROW);
+    load_sheet_current_row_data(obj->read_ptr.sheet_t, return_value, zv_type_t, obj->read_ptr.data_type_default, READ_ROW);
 }
 /* }}} */
 
@@ -1318,6 +1351,7 @@ PHP_METHOD(vtiful_xls, nextCellCallback)
 
     xls_read_callback_data callback_data;
 
+    callback_data.data_type_default = obj->read_ptr.data_type_default;
     callback_data.zv_type_t = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
 
     callback_data.fci = &fci;
@@ -1371,6 +1405,7 @@ zend_function_entry xls_methods[] = {
         PHP_ME(vtiful_xls, putCSVCallback,   xls_put_csv_callback_arginfo,   ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, sheetList,        xls_sheet_list_arginfo,         ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, setType,          xls_set_type_arginfo,           ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_xls, setGlobalType,    xls_set_global_type_arginfo,    ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, setSkipRows,      xls_set_skip_arginfo,           ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, getSheetData,     xls_get_sheet_data_arginfo,     ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, nextRow,          xls_next_row_arginfo,           ZEND_ACC_PUBLIC)

+ 14 - 6
kernel/read.c

@@ -212,7 +212,7 @@ int sheet_read_row(xlsxioreadersheet sheet_t)
 /* }}} */
 
 /* {{{ */
-unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type_arr_t, unsigned int flag)
+unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type_arr_t, zend_long data_type_default, unsigned int flag)
 {
     zend_long _type, _cell_index = 0, _last_cell_index = 0;
     zend_bool _skip_empty_value_cell = 0;
@@ -256,7 +256,11 @@ unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_res
 
             if (_current_type != NULL && Z_TYPE_P(_current_type) == IS_LONG) {
                 _type = Z_LVAL_P(_current_type);
+            } else {
+                _type = data_type_default;
             }
+        } else {
+            _type = data_type_default;
         }
 
         data_to_custom_type(_string_value, _string_value_length, _type, zv_result_t, _cell_index);
@@ -332,7 +336,7 @@ int sheet_cell_callback (size_t row, size_t col, const char *value, void *callba
         goto CALL_USER_FUNCTION;
     }
 
-    if (Z_TYPE_P(_callback_data->zv_type_t) != IS_ARRAY) {
+    if (Z_TYPE_P(_callback_data->zv_type_t) != IS_ARRAY && _callback_data->data_type_default == READ_TYPE_EMPTY) {
         zend_long _long = 0; double _double = 0;
 
         if (is_numeric_string(value, _value_length, &_long, &_double, 0)) {
@@ -346,6 +350,10 @@ int sheet_cell_callback (size_t row, size_t col, const char *value, void *callba
         }
     }
 
+    if (Z_TYPE_P(_callback_data->zv_type_t) != IS_ARRAY && _callback_data->data_type_default != READ_TYPE_EMPTY) {
+        data_to_custom_type(value, _value_length, _callback_data->data_type_default, &args[2], 0);
+    }
+
     if (Z_TYPE_P(_callback_data->zv_type_t) == IS_ARRAY) {
         zval *_current_type = NULL;
         zend_ulong _type = READ_TYPE_EMPTY;
@@ -382,7 +390,7 @@ unsigned int load_sheet_current_row_data_callback (zend_string *zs_sheet_name_t,
 /* }}} */
 
 /* {{{ */
-void load_sheet_all_data (xlsxioreadersheet sheet_t, zval *zv_type_t, zval *zv_result_t)
+void load_sheet_all_data (xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long data_type_default, zval *zv_result_t)
 {
     if (Z_TYPE_P(zv_result_t) != IS_ARRAY) {
         array_init(zv_result_t);
@@ -393,13 +401,13 @@ void load_sheet_all_data (xlsxioreadersheet sheet_t, zval *zv_type_t, zval *zv_r
         zval _zv_tmp_row;
         ZVAL_NULL(&_zv_tmp_row);
 
-        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, zv_type_t, READ_SKIP_ROW);
+        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, zv_type_t, data_type_default, READ_SKIP_ROW);
         add_next_index_zval(zv_result_t, &_zv_tmp_row);
     }
 }
 /* }}} */
 
-void skip_rows(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long zl_skip_row)
+void skip_rows(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long data_type_default, zend_long zl_skip_row)
 {
     while (sheet_read_row(sheet_t))
     {
@@ -410,7 +418,7 @@ void skip_rows(xlsxioreadersheet sheet_t, zval *zv_type_t, zend_long zl_skip_row
             sheet_read_row(sheet_t);
         }
 
-        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, zv_type_t, READ_SKIP_ROW);
+        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, zv_type_t, data_type_default, READ_SKIP_ROW);
 
         zval_ptr_dtor(&_zv_tmp_row);
 

+ 118 - 0
tests/open_xlsx_global_data_type.phpt

@@ -0,0 +1,118 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php
+require __DIR__ . '/include/skipif.inc';
+skip_disable_reader();
+?>
+--FILE--
+<?php
+$config   = ['path' => './tests'];
+$excel    = new \Vtiful\Kernel\Excel($config);
+$filePath = $excel->fileName('tutorial.xlsx')
+    ->header(['Item', 'Cost', 'Int', 'Double'])
+    ->data([
+        ['Item_1', 'Cost_1', 10, 10.9999995],
+    ])
+    ->output();
+
+$excel->openFile('tutorial.xlsx')
+    ->setGlobalType(\Vtiful\Kernel\Excel::TYPE_DOUBLE)
+    ->nextCellCallback(function ($row, $cell, $data) {
+        echo 'cell:' . $cell . ', row:' . $row . PHP_EOL;
+        var_dump($data);
+    });
+
+echo '----------------' . PHP_EOL;
+
+$data = $excel->openFile('tutorial.xlsx')
+    ->openSheet()
+    ->setGlobalType(\Vtiful\Kernel\Excel::TYPE_STRING)
+    ->getSheetData();
+
+var_dump($data);
+
+$excel->openFile('tutorial.xlsx')
+    ->openSheet()
+    ->setGlobalType(\Vtiful\Kernel\Excel::TYPE_INT);
+
+echo '----------------' . PHP_EOL;
+
+var_dump($excel->nextRow());
+var_dump($excel->nextRow());
+var_dump($excel->nextRow());
+var_dump($excel->nextRow());
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+cell:0, row:0
+string(4) "Item"
+cell:1, row:0
+string(4) "Cost"
+cell:2, row:0
+string(3) "Int"
+cell:3, row:0
+string(6) "Double"
+cell:3, row:0
+string(12) "XLSX_ROW_END"
+cell:0, row:1
+string(6) "Item_1"
+cell:1, row:1
+string(6) "Cost_1"
+cell:2, row:1
+float(10)
+cell:3, row:1
+float(10.9999995)
+cell:3, row:1
+string(12) "XLSX_ROW_END"
+----------------
+array(2) {
+  [0]=>
+  array(4) {
+    [0]=>
+    string(4) "Item"
+    [1]=>
+    string(4) "Cost"
+    [2]=>
+    string(3) "Int"
+    [3]=>
+    string(6) "Double"
+  }
+  [1]=>
+  array(4) {
+    [0]=>
+    string(6) "Item_1"
+    [1]=>
+    string(6) "Cost_1"
+    [2]=>
+    string(2) "10"
+    [3]=>
+    string(10) "10.9999995"
+  }
+}
+----------------
+array(4) {
+  [0]=>
+  string(4) "Item"
+  [1]=>
+  string(4) "Cost"
+  [2]=>
+  string(3) "Int"
+  [3]=>
+  string(6) "Double"
+}
+array(4) {
+  [0]=>
+  string(6) "Item_1"
+  [1]=>
+  string(6) "Cost_1"
+  [2]=>
+  int(10)
+  [3]=>
+  int(10)
+}
+NULL
+NULL