PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 8.2.5
WooCommerce v8.2.5
10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / export / abstract-wc-csv-exporter.php
woocommerce / includes / export Last commit date
abstract-wc-csv-batch-exporter.php 3 years ago abstract-wc-csv-exporter.php 2 years ago class-wc-product-csv-exporter.php 3 years ago
abstract-wc-csv-exporter.php
490 lines
1 <?php
2 /**
3 * Handles CSV export.
4 *
5 * @package WooCommerce\Export
6 * @version 3.1.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * WC_CSV_Exporter Class.
15 */
16 abstract class WC_CSV_Exporter {
17
18 /**
19 * Type of export used in filter names.
20 *
21 * @var string
22 */
23 protected $export_type = '';
24
25 /**
26 * Filename to export to.
27 *
28 * @var string
29 */
30 protected $filename = 'wc-export.csv';
31
32 /**
33 * Batch limit.
34 *
35 * @var integer
36 */
37 protected $limit = 50;
38
39 /**
40 * Number exported.
41 *
42 * @var integer
43 */
44 protected $exported_row_count = 0;
45
46 /**
47 * Raw data to export.
48 *
49 * @var array
50 */
51 protected $row_data = array();
52
53 /**
54 * Total rows to export.
55 *
56 * @var integer
57 */
58 protected $total_rows = 0;
59
60 /**
61 * Columns ids and names.
62 *
63 * @var array
64 */
65 protected $column_names = array();
66
67 /**
68 * List of columns to export, or empty for all.
69 *
70 * @var array
71 */
72 protected $columns_to_export = array();
73
74 /**
75 * The delimiter parameter sets the field delimiter (one character only).
76 *
77 * @var string
78 */
79 protected $delimiter = ',';
80
81 /**
82 * Prepare data that will be exported.
83 */
84 abstract public function prepare_data_to_export();
85
86 /**
87 * Return an array of supported column names and ids.
88 *
89 * @since 3.1.0
90 * @return array
91 */
92 public function get_column_names() {
93 return apply_filters( "woocommerce_{$this->export_type}_export_column_names", $this->column_names, $this );
94 }
95
96 /**
97 * Set column names.
98 *
99 * @since 3.1.0
100 * @param array $column_names Column names array.
101 */
102 public function set_column_names( $column_names ) {
103 $this->column_names = array();
104
105 foreach ( $column_names as $column_id => $column_name ) {
106 $this->column_names[ wc_clean( $column_id ) ] = wc_clean( $column_name );
107 }
108 }
109
110 /**
111 * Return an array of columns to export.
112 *
113 * @since 3.1.0
114 * @return array
115 */
116 public function get_columns_to_export() {
117 return $this->columns_to_export;
118 }
119
120 /**
121 * Return the delimiter to use in CSV file
122 *
123 * @since 3.9.0
124 * @return string
125 */
126 public function get_delimiter() {
127 return apply_filters( "woocommerce_{$this->export_type}_export_delimiter", $this->delimiter );
128 }
129
130 /**
131 * Set columns to export.
132 *
133 * @since 3.1.0
134 * @param array $columns Columns array.
135 */
136 public function set_columns_to_export( $columns ) {
137 $this->columns_to_export = array_map( 'wc_clean', $columns );
138 }
139
140 /**
141 * See if a column is to be exported or not.
142 *
143 * @since 3.1.0
144 * @param string $column_id ID of the column being exported.
145 * @return boolean
146 */
147 public function is_column_exporting( $column_id ) {
148 $column_id = strstr( $column_id, ':' ) ? current( explode( ':', $column_id ) ) : $column_id;
149 $columns_to_export = $this->get_columns_to_export();
150
151 if ( empty( $columns_to_export ) ) {
152 return true;
153 }
154
155 if ( in_array( $column_id, $columns_to_export, true ) || 'meta' === $column_id ) {
156 return true;
157 }
158
159 return false;
160 }
161
162 /**
163 * Return default columns.
164 *
165 * @since 3.1.0
166 * @return array
167 */
168 public function get_default_column_names() {
169 return array();
170 }
171
172 /**
173 * Do the export.
174 *
175 * @since 3.1.0
176 */
177 public function export() {
178 $this->prepare_data_to_export();
179 $this->send_headers();
180 $this->send_content( chr( 239 ) . chr( 187 ) . chr( 191 ) . $this->export_column_headers() . $this->get_csv_data() );
181 die();
182 }
183
184 /**
185 * Set the export headers.
186 *
187 * @since 3.1.0
188 */
189 public function send_headers() {
190 if ( function_exists( 'gc_enable' ) ) {
191 gc_enable(); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gc_enableFound
192 }
193 if ( function_exists( 'apache_setenv' ) ) {
194 @apache_setenv( 'no-gzip', 1 ); // @codingStandardsIgnoreLine
195 }
196 @ini_set( 'zlib.output_compression', 'Off' ); // @codingStandardsIgnoreLine
197 @ini_set( 'output_buffering', 'Off' ); // @codingStandardsIgnoreLine
198 @ini_set( 'output_handler', '' ); // @codingStandardsIgnoreLine
199 ignore_user_abort( true );
200 wc_set_time_limit( 0 );
201 wc_nocache_headers();
202 header( 'Content-Type: text/csv; charset=utf-8' );
203 header( 'Content-Disposition: attachment; filename=' . $this->get_filename() );
204 header( 'Pragma: no-cache' );
205 header( 'Expires: 0' );
206 }
207
208 /**
209 * Set filename to export to.
210 *
211 * @param string $filename Filename to export to.
212 */
213 public function set_filename( $filename ) {
214 $this->filename = sanitize_file_name( str_replace( '.csv', '', $filename ) . '.csv' );
215 }
216
217 /**
218 * Generate and return a filename.
219 *
220 * @return string
221 */
222 public function get_filename() {
223 return sanitize_file_name( apply_filters( "woocommerce_{$this->export_type}_export_get_filename", $this->filename ) );
224 }
225
226 /**
227 * Set the export content.
228 *
229 * @since 3.1.0
230 * @param string $csv_data All CSV content.
231 */
232 public function send_content( $csv_data ) {
233 echo $csv_data; // @codingStandardsIgnoreLine
234 }
235
236 /**
237 * Get CSV data for this export.
238 *
239 * @since 3.1.0
240 * @return string
241 */
242 protected function get_csv_data() {
243 return $this->export_rows();
244 }
245
246 /**
247 * Export column headers in CSV format.
248 *
249 * @since 3.1.0
250 * @return string
251 */
252 protected function export_column_headers() {
253 $columns = $this->get_column_names();
254 $export_row = array();
255 $buffer = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
256 ob_start();
257
258 foreach ( $columns as $column_id => $column_name ) {
259 if ( ! $this->is_column_exporting( $column_id ) ) {
260 continue;
261 }
262 $export_row[] = $this->format_data( $column_name );
263 }
264
265 $this->fputcsv( $buffer, $export_row );
266
267 return ob_get_clean();
268 }
269
270 /**
271 * Get data that will be exported.
272 *
273 * @since 3.1.0
274 * @return array
275 */
276 protected function get_data_to_export() {
277 return $this->row_data;
278 }
279
280 /**
281 * Export rows in CSV format.
282 *
283 * @since 3.1.0
284 * @return string
285 */
286 protected function export_rows() {
287 $data = $this->get_data_to_export();
288 $buffer = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
289 ob_start();
290
291 array_walk( $data, array( $this, 'export_row' ), $buffer );
292
293 return apply_filters( "woocommerce_{$this->export_type}_export_rows", ob_get_clean(), $this );
294 }
295
296 /**
297 * Export rows to an array ready for the CSV.
298 *
299 * @since 3.1.0
300 * @param array $row_data Data to export.
301 * @param string $key Column being exported.
302 * @param resource $buffer Output buffer.
303 */
304 protected function export_row( $row_data, $key, $buffer ) {
305 $columns = $this->get_column_names();
306 $export_row = array();
307
308 foreach ( $columns as $column_id => $column_name ) {
309 if ( ! $this->is_column_exporting( $column_id ) ) {
310 continue;
311 }
312 if ( isset( $row_data[ $column_id ] ) ) {
313 $export_row[] = $this->format_data( $row_data[ $column_id ] );
314 } else {
315 $export_row[] = '';
316 }
317 }
318
319 $this->fputcsv( $buffer, $export_row );
320
321 ++ $this->exported_row_count;
322 }
323
324 /**
325 * Get batch limit.
326 *
327 * @since 3.1.0
328 * @return int
329 */
330 public function get_limit() {
331 return apply_filters( "woocommerce_{$this->export_type}_export_batch_limit", $this->limit, $this );
332 }
333
334 /**
335 * Set batch limit.
336 *
337 * @since 3.1.0
338 * @param int $limit Limit to export.
339 */
340 public function set_limit( $limit ) {
341 $this->limit = absint( $limit );
342 }
343
344 /**
345 * Get count of records exported.
346 *
347 * @since 3.1.0
348 * @return int
349 */
350 public function get_total_exported() {
351 return $this->exported_row_count;
352 }
353
354 /**
355 * Escape a string to be used in a CSV context
356 *
357 * Malicious input can inject formulas into CSV files, opening up the possibility
358 * for phishing attacks and disclosure of sensitive information.
359 *
360 * Additionally, Excel exposes the ability to launch arbitrary commands through
361 * the DDE protocol.
362 *
363 * @see http://www.contextis.com/resources/blog/comma-separated-vulnerabilities/
364 * @see https://hackerone.com/reports/72785
365 *
366 * @since 3.1.0
367 * @param string $data CSV field to escape.
368 * @return string
369 */
370 public function escape_data( $data ) {
371 $active_content_triggers = array( '=', '+', '-', '@' );
372
373 if ( in_array( mb_substr( $data, 0, 1 ), $active_content_triggers, true ) ) {
374 $data = "'" . $data;
375 }
376
377 return $data;
378 }
379
380 /**
381 * Format and escape data ready for the CSV file.
382 *
383 * @since 3.1.0
384 * @param string $data Data to format.
385 * @return string
386 */
387 public function format_data( $data ) {
388 if ( ! is_scalar( $data ) ) {
389 if ( is_a( $data, 'WC_Datetime' ) ) {
390 $data = $data->date( 'Y-m-d G:i:s' );
391 } else {
392 $data = ''; // Not supported.
393 }
394 } elseif ( is_bool( $data ) ) {
395 $data = $data ? 1 : 0;
396 }
397
398 $use_mb = function_exists( 'mb_convert_encoding' );
399
400 if ( $use_mb ) {
401 $is_valid_utf_8 = mb_check_encoding( $data, 'UTF-8' );
402 if ( ! $is_valid_utf_8 ) {
403 $data = mb_convert_encoding( $data, 'UTF-8', 'ISO-8859-1' );
404 }
405 }
406
407 return $this->escape_data( $data );
408 }
409
410 /**
411 * Format term ids to names.
412 *
413 * @since 3.1.0
414 * @param array $term_ids Term IDs to format.
415 * @param string $taxonomy Taxonomy name.
416 * @return string
417 */
418 public function format_term_ids( $term_ids, $taxonomy ) {
419 $term_ids = wp_parse_id_list( $term_ids );
420
421 if ( ! count( $term_ids ) ) {
422 return '';
423 }
424
425 $formatted_terms = array();
426
427 if ( is_taxonomy_hierarchical( $taxonomy ) ) {
428 foreach ( $term_ids as $term_id ) {
429 $formatted_term = array();
430 $ancestor_ids = array_reverse( get_ancestors( $term_id, $taxonomy ) );
431
432 foreach ( $ancestor_ids as $ancestor_id ) {
433 $term = get_term( $ancestor_id, $taxonomy );
434 if ( $term && ! is_wp_error( $term ) ) {
435 $formatted_term[] = $term->name;
436 }
437 }
438
439 $term = get_term( $term_id, $taxonomy );
440
441 if ( $term && ! is_wp_error( $term ) ) {
442 $formatted_term[] = $term->name;
443 }
444
445 $formatted_terms[] = implode( ' > ', $formatted_term );
446 }
447 } else {
448 foreach ( $term_ids as $term_id ) {
449 $term = get_term( $term_id, $taxonomy );
450
451 if ( $term && ! is_wp_error( $term ) ) {
452 $formatted_terms[] = $term->name;
453 }
454 }
455 }
456
457 return $this->implode_values( $formatted_terms );
458 }
459
460 /**
461 * Implode CSV cell values using commas by default, and wrapping values
462 * which contain the separator.
463 *
464 * @since 3.2.0
465 * @param array $values Values to implode.
466 * @return string
467 */
468 protected function implode_values( $values ) {
469 $values_to_implode = array();
470
471 foreach ( $values as $value ) {
472 $value = (string) is_scalar( $value ) ? html_entity_decode( $value, ENT_QUOTES ) : '';
473 $values_to_implode[] = str_replace( ',', '\\,', $value );
474 }
475
476 return implode( ', ', $values_to_implode );
477 }
478
479 /**
480 * Write to the CSV file.
481 *
482 * @since 3.4.0
483 * @param resource $buffer Resource we are writing to.
484 * @param array $export_row Row to export.
485 */
486 protected function fputcsv( $buffer, $export_row ) {
487 fputcsv( $buffer, $export_row, $this->get_delimiter(), '"', "\0" ); // @codingStandardsIgnoreLine
488 }
489 }
490