@@ -31,23 +31,33 @@ class CsvResponse extends DownloadResponse
31
31
{
32
32
use InjectContentTypeTrait;
33
33
34
+ const DEFAULT_SEPARATOR = ', ' ;
35
+
36
+ /**
37
+ * @var array
38
+ */
39
+ private $ options ;
40
+
34
41
/**
35
42
* Create a CSV response.
36
43
*
37
44
* Produces a CSV response with a Content-Type of text/csv and a default
38
45
* status of 200.
39
46
*
40
- * @param string|StreamInterface $text String or stream for the message body.
47
+ * @param array|string|StreamInterface $text String or stream for the message body.
48
+ * @param array $options
41
49
* @param int $status Integer status code for the response; 200 by default.
42
50
* @param string $filename
43
51
* @param array $headers Array of headers to use at initialization.
44
52
*/
45
- public function __construct ($ text , int $ status = 200 , string $ filename = '' , array $ headers = [])
53
+ public function __construct ($ text , array $ options = [], int $ status = 200 , string $ filename = '' , array $ headers = [])
46
54
{
47
55
if ($ filename !== '' ) {
48
56
$ headers = $ this ->prepareDownloadHeaders ($ filename , $ headers );
49
57
}
50
58
59
+ $ this ->options = $ options ;
60
+
51
61
parent ::__construct (
52
62
$ this ->createBody ($ text ),
53
63
$ status ,
@@ -56,19 +66,36 @@ public function __construct($text, int $status = 200, string $filename = '', arr
56
66
}
57
67
58
68
/**
59
- * Create the CSV message body.
60
- *
69
+ * Create the body of the CSV response
61
70
* @param string|StreamInterface $text
62
71
* @return StreamInterface
63
72
* @throws Exception\InvalidArgumentException if $text is neither a string or stream.
64
73
*/
65
74
private function createBody ($ text ) : StreamInterface
66
75
{
76
+ $ body = null ;
77
+
78
+ if (is_string ($ text )) {
79
+ $ body = $ this ->createBodyFromString ($ text );
80
+ }
81
+
67
82
if ($ text instanceof StreamInterface) {
68
- return $ text ;
83
+ $ body = $ text ;
69
84
}
70
85
71
- if (! is_string ($ text )) {
86
+ return $ body ;
87
+ }
88
+
89
+ /**
90
+ * Create the CSV message body from a CSV string.
91
+ *
92
+ * @param string $text
93
+ * @return StreamInterface
94
+ * @throws Exception\InvalidArgumentException if $text is neither a string or stream.
95
+ */
96
+ private function createBodyFromString (string $ text ) : StreamInterface
97
+ {
98
+ if (empty ($ text )) {
72
99
throw new Exception \InvalidArgumentException (sprintf (
73
100
'Invalid CSV content (%s) provided to %s ' ,
74
101
(is_object ($ text ) ? get_class ($ text ) : gettype ($ text )),
@@ -81,4 +108,43 @@ private function createBody($text) : StreamInterface
81
108
$ body ->rewind ();
82
109
return $ body ;
83
110
}
111
+
112
+ /**
113
+ * Get a fully rendered CSV record
114
+ * @param array $row
115
+ * @param array $last
116
+ * @return string
117
+ */
118
+ public function getRecord (array $ row , array $ last ): string
119
+ {
120
+ $ lineEnding = $ this ->getLineEnding ($ row , $ last );
121
+ $ row = implode ($ this ->options ['field_separator ' ] ?? self ::DEFAULT_SEPARATOR , $ row );
122
+
123
+ return $ row . $ lineEnding ;
124
+ }
125
+
126
+ /**
127
+ * Is the current row the last one
128
+ * @param array $current
129
+ * @param array $last
130
+ * @return bool
131
+ */
132
+ public function isLastLine ($ current , $ last )
133
+ {
134
+ return ($ current == $ last );
135
+ }
136
+
137
+ /**
138
+ * @param array $row
139
+ * @param array $last
140
+ * @return string
141
+ */
142
+ public function getLineEnding (array $ row , array $ last ): string
143
+ {
144
+ $ lineEnding = ($ this ->isLastLine ($ row , $ last ))
145
+ ? ''
146
+ : $ this ->options ['line_ending ' ] ?? self ::DEFAULT_LINE_ENDING ;
147
+
148
+ return $ lineEnding ;
149
+ }
84
150
}
0 commit comments