44
55use Illuminate \Database \Eloquent \Model ;
66use Illuminate \Support \Collection ;
7+ use Throwable ;
78use Vitorccs \LaravelCsv \Concerns \FromArray ;
89use Vitorccs \LaravelCsv \Concerns \FromCollection ;
910use Vitorccs \LaravelCsv \Concerns \FromQuery ;
11+ use Vitorccs \LaravelCsv \Concerns \FromQueryCursor ;
1012use Vitorccs \LaravelCsv \Concerns \WithColumnFormatting ;
1113use Vitorccs \LaravelCsv \Concerns \WithHeadings ;
1214use Vitorccs \LaravelCsv \Concerns \WithMapping ;
@@ -70,6 +72,10 @@ public function generate(object $exportable)
7072 );
7173 }
7274
75+ if ($ exportable instanceof FromQueryCursor) {
76+ $ this ->iterateRows ($ exportable , $ exportable ->query ()->cursor ());
77+ }
78+
7379 return $ this ->handler ->getResource ();
7480 }
7581
@@ -81,67 +87,76 @@ public function generate(object $exportable)
8187 */
8288 private function iterateRows (object $ exportable , $ rows ): void
8389 {
84- if ($ rows instanceof Collection) {
85- $ rows = iterator_to_array ($ rows ->values ());
90+ $ formats = $ exportable instanceof WithColumnFormatting ? $ exportable ->columnFormats () : [];
91+ $ withMapping = $ exportable instanceof WithMapping;
92+ $ row_index = 1 ;
93+ foreach ($ rows as $ row ) {
94+ $ mappedRow = $ withMapping ? $ exportable ->map ($ row ) : $ row ;
95+ $ normalizedRow = $ this ->normalizeRow ($ mappedRow );
96+ $ formattedRow = $ this ->applyFormatting ($ normalizedRow , $ formats , $ row_index ++);
97+ $ this ->writeRow ($ formattedRow );
8698 }
99+ }
87100
88- if ($ exportable instanceof WithMapping) {
89- $ rows = array_map (fn ($ row ) => $ exportable ->map ($ row ), $ rows );
101+ private function normalizeRow ($ row ): array
102+ {
103+ if ($ row instanceof Model) {
104+ $ row = ModelHelper::toArrayValues ($ row );
105+ }
106+ if (is_object ($ row )) {
107+ $ row = (array )$ row ;
90108 }
109+ if (is_array ($ row )) {
110+ $ row = array_values ($ row );
111+ }
112+ return $ row ;
113+ }
91114
92- $ rows = array_map (function ($ row ) {
93- if ($ row instanceof Model) {
94- $ row = ModelHelper::toArrayValues ($ row );
95- }
96- if (is_object ($ row )) {
97- $ row = (array )$ row ;
98- }
99- if (is_array ($ row )) {
100- $ row = array_values ($ row );
101- }
102- return $ row ;
103- }, $ rows );
104-
105- $ rows = array_map (function ($ row , int $ iRow ) use ($ exportable ) {
106- return array_map (function ($ column , int $ iColumn ) use ($ exportable , $ iRow ) {
107- $ formats = $ exportable instanceof WithColumnFormatting
108- ? $ exportable ->columnFormats ()
109- : [];
110- $ columnLetter = CsvHelper::getColumnLetter ($ iColumn + 1 );
111- $ format = $ formats [$ columnLetter ] ?? null ;
112-
113- if ($ format === CellFormat::DATE ) {
114-
115- $ column = $ this ->formatter ->date ($ column );
116- }
117-
118- if ($ format === CellFormat::DATETIME ) {
119- $ column = $ this ->formatter ->datetime ($ column );
120- }
121-
122- if ($ format === CellFormat::DECIMAL ) {
123- $ column = $ this ->formatter ->decimal ($ column );
124- }
125-
126- if ($ format === CellFormat::INTEGER ) {
127- $ column = $ this ->formatter ->integer ($ column );
128- }
129-
130- try {
131- if (!is_string ($ column )) {
132- $ column = (string )$ column ;
133- }
134- } catch (\Throwable $ e ) {
135- throw new InvalidCellValueException ("{$ columnLetter }{$ iRow }" );
136- }
137-
138- return $ column ;
139- }, $ row , array_keys ($ row ));
140- }, $ rows , array_keys ($ rows ));
115+ /**
116+ * @throws InvalidCellValueException
117+ */
118+ private function applyFormatting (array $ row , array $ formats , int $ row_index ): array
119+ {
120+ return array_map (
121+ fn ($ value , int $ column_index ) => $ this ->formatCellValue ($ value , $ formats , $ row_index , $ column_index ),
122+ $ row ,
123+ array_keys ($ row )
124+ );
125+ }
141126
142- foreach ($ rows as $ row ) {
143- $ this ->writeRow ($ row );
127+ /**
128+ * @throws InvalidCellValueException
129+ */
130+ private function formatCellValue ($ value , array $ formats , int $ row_index , int $ column_index ): string
131+ {
132+ $ columnLetter = CsvHelper::getColumnLetter ($ column_index + 1 );
133+ $ format = $ formats [$ columnLetter ] ?? null ;
134+
135+ if ($ format === CellFormat::DATE ) {
136+ return $ this ->formatter ->date ($ value );
137+ }
138+
139+ if ($ format === CellFormat::DATETIME ) {
140+ return $ this ->formatter ->datetime ($ value );
144141 }
142+
143+ if ($ format === CellFormat::DECIMAL ) {
144+ return $ this ->formatter ->decimal ($ value );
145+ }
146+
147+ if ($ format === CellFormat::INTEGER ) {
148+ return $ this ->formatter ->integer ($ value );
149+ }
150+
151+ try {
152+ if (! is_string ($ value )) {
153+ return (string )$ value ;
154+ }
155+ } catch (Throwable $ e ) {
156+ throw new InvalidCellValueException ("{$ columnLetter }{$ row_index }" );
157+ }
158+
159+ return $ value ;
145160 }
146161
147162 /**
0 commit comments