Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A PHP trait to write data from WP-CLI to a CSV, in a memory-friendly and won't-lose-data-if-CLI-errors way.
<?php
/**
* Simplify progressive generation of a CSV output file. Permits a command to
* write each row to a CSV as records are considered, avoiding the need to
* maintain the entire dataset in memory.
*/
/* phpcs:disable HM.Files.ClassFileName.MismatchedName */
// (HM's standards want this to be class-*, which is misleading.)
namespace MyProject\CLI;
trait CSV_Report {
/**
* Dictionary of CSV resources, keyed by file path.
*
* @var array
*/
private $csv_report_handles;
/**
* Create and store a file resource at a particular path.
*
* @param string $path Path of CSV to create.
*/
private function csv_report_open( string $path ) : void {
if ( ! isset( $this->csv_report_handles ) ) {
$this->csv_report_handles = [];
}
$this->csv_report_handles[ $path ] = fopen( $path, 'w' );
}
/**
* Append a row of data to the CSV at a specific path. If the CSV resouve
* does not yet exist, a file handler will be opened and the array keys
* of the received data object will be written as the first row in the file.
*
* @param string $path The path of the CSV file to write to.
* @param array $data Associative array of data to write to the CSV file.
*/
protected function csv_report_append( string $path, array $data ) : void {
if ( ! isset( $this->csv_report_handles[ $path ] ) ) {
$this->csv_report_open( $path );
fputcsv( $this->csv_report_handles[ $path ], array_keys( $data ) );
}
fputcsv( $this->csv_report_handles[ $path ], $data );
}
/**
* Create and store a file resource at a particular path.
*
* @param string $path Path of CSV to create.
*/
protected function csv_report_close( string $path ) : void {
if ( isset( $this->csv_report_handles[ $path ] ) ) {
fclose( $this->csv_report_handles[ $path ] );
}
}
/**
* Wrap a bulk_task callback with a handler which will write the return
* value of each callback execution to a specified CSV. Return "false"
* from the passed callable to omit the result from the output file.
*
* @param callable $callback Alley_CLI_Bulk_Task bulk_task callback.
* @param string $path The path of the CSV file to write to.
* @return callable Wrapped callback.
*/
protected function csv_report_from_callback( callable $callback, string $path = '' ) : callable {
if ( empty( $path ) ) {
return $callback;
}
return function( $post ) use ( $callback, $path ) {
$result = $callback( $post );
if ( $result ) {
$this->csv_report_append( $path, $result );
}
return $result;
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment