/** * Emit the message in specified format * * @params $format string optional - options are "raw","json" */ public static function emit($format = 'raw') { $messenger = self::instance(); switch ($format) { case 'pantheon': case 'json': $formatted = array(); foreach ($messenger->messages as $message) { $formatted[$message['name']] = $message; } \WP_CLI::print_value($formatted, array('format' => 'json')); break; case 'raw': case 'default': foreach ($messenger->messages as $message) { // colorize if ($message['score'] == 2) { $color = "%G"; } elseif ($message['score'] == 0) { $color = "%C"; } else { $color = "%R"; } // @todo might be a better way to do this echo \cli\Colors::colorize(sprintf(str_repeat('-', 80) . PHP_EOL . "%s: (%s) \n%s\nResult:%s %s\nRecommendation: %s\n\n" . PHP_EOL, strtoupper($message['label']), $message['description'], str_repeat('-', 80), $color, $message['result'] . '%n', $message['action'])); } break; } }
/** * Returns a colorized string * * @param string $string Message to colorize for output * @return string */ private function colorize($string) { $colorization_setting = $this->runner->getConfig('colorize'); $colorize = $colorization_setting == 'auto' && !\cli\Shell::isPiped() || is_bool($colorization_setting) && $colorization_setting; $colorized_string = \cli\Colors::colorize($string, $colorize); return $colorized_string; }
/** * Returns a colorized string * * @param string $string Message to colorize for output * @return string */ function colorize($string) { $colorize = true; if (Terminus::getConfig('colorize') == 'auto') { $colorize = !\cli\Shell::isPiped(); } $colorized_string = \cli\Colors::colorize($string, $colorize); return $colorized_string; }
function test_string_cache() { $string = 'x'; $string_with_color = '%k' . $string; $colorized_string = "[30m{$string}"; // Ensure colorization works $this->assertEquals(\cli\Colors::colorize($string_with_color, true), $colorized_string); // Test that the value was cached appropriately $test_cache = array('passed' => $string_with_color, 'colorized' => $colorized_string, 'decolorized' => $string); $real_cache = \cli\Colors::getStringCache(); // Test that the cache value exists $this->assertTrue(isset($real_cache[md5($string_with_color)])); // Test that the cache value is correctly set $this->assertEquals($test_cache, $real_cache[md5($string_with_color)]); }
/** * Draw simple One column table with colored string * Output should look like: * +-------------+ * | Test Header | * +-------------+ * | x | * +-------------+ * * where `x` character has green color. * At the same time it checks that `green` defined in `cli\Colors` really looks as `green`. */ public function testDrawOneColumnColoredTable() { $headers = array('Test Header'); $rows = array(array(Colors::colorize('%Gx%n', true))); // green `x` $x = "[32;1mx[0m"; $output = <<<OUT +-------------+ | Test Header | +-------------+ | {$x} | +-------------+ OUT; $this->assertInOutEquals(array($headers, $rows), $output); }
/** * Similar to error( $message ), but outputs $message in a red box * * @param array $message Message to write. */ public function error_multi_line($message_lines) { // convert tabs to four spaces, as some shells will output the tabs as variable-length $message_lines = array_map(function ($line) { return str_replace("\t", ' ', $line); }, $message_lines); $longest = max(array_map('strlen', $message_lines)); // write an empty line before the message $empty_line = \cli\Colors::colorize('%w%1 ' . str_repeat(' ', $longest) . ' %n'); $this->write(STDERR, "\n\t{$empty_line}\n"); foreach ($message_lines as $line) { $padding = str_repeat(' ', $longest - strlen($line)); $line = \cli\Colors::colorize("%w%1 {$line} {$padding}%n"); $this->write(STDERR, "\t{$line}\n"); } // write an empty line after the message $this->write(STDERR, "\t{$empty_line}\n\n"); }
static function coloredOutput($message = "", $print = true) { $cli = new self(''); // we're not using regex here because simple str_replace is faster. However, // we may need to go that route if this function gets too complex $message = str_replace('</M>', '%n', str_replace('<M>', '%M', $message)); $message = str_replace('</m>', '%n', str_replace('<m>', '%m', $message)); $message = str_replace('</G>', '%n', str_replace('<G>', '%G', $message)); $message = str_replace('</y>', '%n', str_replace('<y>', '%y', $message)); $message = str_replace('</Y>', '%n', str_replace('<Y>', '%Y', $message)); $message = str_replace('</R>', '%n', str_replace('<R>', '%R', $message)); $message = str_replace('</r>', '%n', str_replace('<r>', '%r', $message)); $message = str_replace('</K>', '%n', str_replace('<K>', '%K', $message)); $message = \cli\Colors::colorize("{$message}", $cli->in_color); if ($print) { $cli->write(STDOUT, "{$message}\n"); } return $message; }
/** * Migrate post content from <img> tags to image shortcodes. * * ## OPTIONS * * <id>... * : One or more IDs of posts to update. * * [--dry-run] * : Only show the content which is to be changed, don't update posts. * * ## EXAMPLES * * ## Migrate all Posts to the Image Shortcake syntax * wp image-shortcake-shortcode migrate `wp post list --post_type=post` --ids` * * ## Converts images to shortcodes on one post, preserving a log to rollback in case of errors. * wp image-shortcake migrate 123 > potential-oops.txt * * * @synopsis <id>... [--dry-run] */ public function migrate($args, $assoc_args) { foreach (array_filter($args) as $post_ID) { $post = $this->fetcher->get_check($post_ID); $_content = $post->post_content; $caption_replacements = Img_Shortcode_Data_Migration::find_caption_shortcodes_for_replacement($_content); $_content = str_replace(array_keys($caption_replacements), array_values($caption_replacements), $_content); $img_tag_replacements = Img_Shortcode_Data_Migration::find_img_tags_for_replacement($_content); $_content = str_replace(array_keys($img_tag_replacements), array_values($img_tag_replacements), $_content); $replacements = array_merge((array) $caption_replacements, (array) $img_tag_replacements); WP_CLI::log(''); if (0 === count($replacements)) { WP_CLI::log('Nothing to replace on post ' . $post->ID . '. Skipping.'); WP_CLI::log(''); continue; } $header = 'Image shortcode replacements for post ' . $post->ID; WP_CLI::log($header); WP_CLI::log(str_repeat('=', strlen($header))); WP_CLI::log(''); foreach ($replacements as $del => $ins) { \WP_CLI::log(\cli\Colors::colorize('%C-%n') . $del, true); \WP_CLI::log(\cli\Colors::colorize('%G+%n') . $ins, true); } WP_CLI::log(''); if (isset($assoc_args['dry-run'])) { WP_CLI::log('Post not updated: --dry-run specifed.'); WP_CLI::log(''); continue; } global $wpdb; // @codingStandardsIgnoreStart $updated = $wpdb->update($wpdb->posts, array('post_content' => $_content), array('ID' => $post_ID)); // @codingStandardsIgnoreEnd if (1 === $updated) { clean_post_cache($post); WP_CLI::success('Updated post ' . $post->ID . '.'); } else { WP_CLI::warning('There was an unexpected error updating post ' . $post->ID . '.'); } } }
/** * Echoes a VHost skeleton with correct path inserted. * * @param string $installPath The install path to insert. * * @author Benjamin Carl <*****@*****.**> * @return void * @access protected * @static */ protected static function showVhostExample($installPath) { \cli\line(); \cli\line('You could use this skeleton (example and not production ready!) for your vhost:'); \cli\line(); \cli\line(\cli\Colors::colorize('%y<VirtualHost *:80>')); \cli\line(' ServerName www.example.com:80'); \cli\line(' ServerAlias example.com *.example.com'); \cli\line(' ServerAdmin webmaster@example.com'); \cli\line(' DocumentRoot "' . $installPath . DIRECTORY_SEPARATOR . 'web"'); \cli\line(' <Directory "' . $installPath . DIRECTORY_SEPARATOR . 'web">'); \cli\line(' Options Indexes FollowSymLinks Includes ExecCGI'); \cli\line(' AllowOverride All'); \cli\line(' Order allow,deny'); \cli\line(' Allow from all'); \cli\line(' DirectoryIndex app.php index.php index.html index.htm'); \cli\line(' </Directory>'); \cli\line('</VirtualHost>'); }
/** * Output one line of message to a resource. * * @param string $message Message to write. * @param string $label Prefix message with a label. * @param string $color Colorize label with a given color. * @param resource $handle Resource to write to. Defaults to STDOUT. */ protected function _line($message, $label, $color, $handle = STDOUT) { $label = \cli\Colors::colorize("{$color}{$label}:%n", $this->in_color); $this->write($handle, "{$label} {$message}\n"); }
/** * Installs the folders required for the bootstrap project from repo to project folder. * * @param string $targetDirectory The directory where to put the files/folders. * * @author Benjamin Carl <*****@*****.**> * * @return bool TRUE on success, otherwise FALSE * @static */ protected static function install($targetDirectory) { $notify = new \cli\notify\Spinner(\cli\Colors::colorize('%N%n%yInstalling bootstrap project ...%N%n'), 100); // Define source & destination $source = self::getSourcePath(); $destination = $targetDirectory; // Iterate and copy ... foreach (self::getFolders() as $folder) { self::xcopy($source . $folder, $destination . $folder); } $target = realpath($destination . 'vendor/maximebf/debugbar/src/DebugBar/Resources'); $link = realpath($destination . 'web') !== false ? realpath($destination . 'web') . DIRECTORY_SEPARATOR . 'assets' : false; if ($target !== false && $link !== false) { // Create important symlinks to required assets like for DebugBar $symlinked = symlink($target, $link); } else { $symlinked = false; } if ($symlinked === false) { self::showError('Could not create symlink from "' . $target . '" to "' . $link . '"'); } $notify->finish(); return true; }
/** * Installs the folders required for the bootstrap project from repo to project folder. * * @param string $targetDirectory The directory where to put the files/folders. * * @author Benjamin Carl <*****@*****.**> * @return bool TRUE on success, otherwise FALSE * @access protected * @static */ protected static function install($targetDirectory) { $notify = new \cli\notify\Spinner(\cli\Colors::colorize('%N%n%yInstalling ...%N%n'), 100); // Define source & destination $source = self::getSourcePath(); $destination = $targetDirectory; // Iterate and copy ... foreach (self::getFolders() as $folder) { self::xcopy($source . $folder, $destination . $folder); } $notify->finish(); return true; }
/** * Output a line that's appropriately nested */ private function nested_line($line, $change = false) { if ('add' == $change) { $color = '%G'; $label = '+ '; } else { if ('remove' == $change) { $color = '%R'; $label = '- '; } else { $color = false; $label = false; } } \cli\Colors::colorize("%n"); $spaces = $this->output_nesting_level * 2 + 2; if ($color && $label) { $line = \cli\Colors::colorize("{$color}{$label}") . $line . \cli\Colors::colorize("%n"); $spaces = $spaces - 2; } WP_CLI::line(str_pad(' ', $spaces) . $line); }
#!/usr/bin/php <?php $loader = (require __DIR__ . "/../vendor/autoload.php"); \cli\Colors::enable(); use InstantWin\Player; use InstantWin\Distribution\EvenOverTimeDistribution; use InstantWin\TimePeriod; $screenCols = exec('tput cols'); for ($tries = 0; $tries < 20; $tries++) { $durationInSeconds = 20000; $eachDot = ceil($durationInSeconds / ($screenCols - 3)); /* use InstantWin\Distribution\FixedOddsDistribution; $dist = new FixedOddsDistribution(); $dist->setOdds(0.002); $player = new Player(); $player->setDistribution($dist); $player->setMaxWins(3); */ $dist = new EvenOverTimeDistribution(); $timePeriod = new TimePeriod(); $timePeriod->setStartTimestamp(1); $timePeriod->setEndTimestamp($durationInSeconds); $player = new Player(); $player->setDistribution($dist); $player->setCurWins(0); $player->setMaxWins(3); $player->setTimePeriod($timePeriod); $wins = 0; $plays = 0;
<?php // Can be used by plugins/themes to check if Terminus is running or not define('Terminus', true); define('TERMINUS_VERSION', '0.4-beta'); $source = 'unknown'; if ('cli' === PHP_SAPI && isset($argv)) { $source = explode('/', $argv[0]); $source = end($source); } define('TERMINUS_SCRIPT', $source); date_default_timezone_set('UTC'); include TERMINUS_ROOT . '/php/utils.php'; include TERMINUS_ROOT . '/php/login.php'; include TERMINUS_ROOT . '/php/FileCache.php'; include TERMINUS_ROOT . '/php/dispatcher.php'; include TERMINUS_ROOT . '/php/class-terminus.php'; include TERMINUS_ROOT . '/php/class-terminus-command.php'; \Terminus\Utils\load_dependencies(); # Set a custom exception handler set_exception_handler('\\Terminus\\Utils\\handle_exception'); if (isset($_SERVER['TERMINUS_HOST']) && $_SERVER['TERMINUS_HOST'] != '') { define('TERMINUS_HOST', $_SERVER['TERMINUS_HOST']); \cli\line(\cli\Colors::colorize('%YNote: using custom target "' . $_SERVER['TERMINUS_HOST'] . '"%n')); } else { define('TERMINUS_HOST', 'dashboard.getpantheon.com'); } define('TERMINUS_PORT', '443'); Terminus::get_runner()->run();
/** * Loops through the row and sets the maximum width for each column. * * @param array $row The table row. * @return array $row */ protected function checkRow(array $row) { foreach ($row as $column => $str) { $width = Colors::length($str); if (!isset($this->_width[$column]) || $width > $this->_width[$column]) { $this->_width[$column] = $width; } } return $row; }
/** * Show items in a \cli\Table. * * @param array $items * @param array $fields */ private static function show_table($items, $fields) { $table = new \cli\Table(); $enabled = \cli\Colors::shouldColorize(); if ($enabled) { \cli\Colors::disable(true); } $table->setHeaders($fields); foreach ($items as $item) { $table->addRow(array_values(\WP_CLI\Utils\pick_fields($item, $fields))); } foreach ($table->getDisplayLines() as $line) { \WP_CLI::line($line); } if ($enabled) { \cli\Colors::enable(true); } }
echo Colors::colorize('Translating : %b' . count($entries) . '%n entries from ' . $from . ' to ' . $to . PHP_EOL); $progress = new Bar('Translate status ', count($entries)); foreach ($entries as $entry => $data) { $translate = ""; $skipped = ""; if (isset($previousEntries) && !empty($previousEntries[$entry]['msgstr'][0])) { $skipped = "(skipped)"; $translate = $previousEntries[$entry]['msgstr'][0]; } else { $translate = $translator->translate($entry, $from, $to); } $po->update_entry($entry, $translate); if ($verbose) { echo $verbose ? " {$entry} => {$translate} {$skipped}" . PHP_EOL : null; } else { $progress->tick(); } } if (!$verbose) { $progress->finish(); } echo 'Save output to: ' . $output . PHP_EOL; $po->write($output); } catch (\DownloadException $e) { $response = @json_decode($e->getResponse()); if (isset($response->error->errors[0]->reason) && $response->error->errors[0]->reason === 'keyInvalid') { die(Colors::colorize('%rInvalid Google Translate API key%n' . PHP_EOL)); } else { die(Colors::colorize('%rError "' . $e->getMessage() . '"%n' . PHP_EOL)); } }
/** * Colorizes a string with a given color. * * @param string $string The string to colorize * @param string $color The color * * @author Benjamin Carl <*****@*****.**> * * @return string The colorized string */ protected function colorize($string, $color) { return \cli\Colors::colorize('%N%n' . $color . $string . '%N%n'); }
/** * Returns a colorized string * * @param [string] $string Message to colorize for output * @return [string] $colorized_string */ static function colorize($string) { $colorized_string = \cli\Colors::colorize($string, self::getRunner()->inColor()); return $colorized_string; }
private function padColumn($content, $column) { return ' ' . Colors::pad($content, $this->_widths[$column]) . ' '; }
private function padColumn($content, $column) { return ' ' . \cli\Colors::pad($content, $this->_widths[$column], isset($this->_align[$column]) ? $this->_align[$column] : "left") . ' '; }
static function colorize($string) { return \cli\Colors::colorize($string, self::get_runner()->in_color()); }
public static function warning($message) { WP_CLI::log(Colors::colorize('%YWarning: %n' . $message)); }
private function padColumn($content, $column) { return $this->_characters['padding'] . Colors::pad($content, $this->_widths[$column]) . $this->_characters['padding']; }
public function testTables() { $this->resetStreams(); $suffix = \cli\Shell::isPiped() ? "_piped" : ""; $this->assertTrue(is_numeric($columns = \cli\Shell::columns())); $headers = array('First Name', 'Last Name', 'City', 'State'); $data = array(array('Maryam', 'Elliott', 'Elizabeth City', 'SD'), array('Jerry', 'Washington', 'Bessemer', 'ME'), array('Allegra', 'Hopkins', 'Altoona', 'ME'), array('Audrey', 'Oneil', 'Dalton', 'SK')); $table = new \cli\Table(); $table->setRenderer(new \cli\table\Ascii()); $table->setHeaders($headers); $table->setRows($data); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_1"), $output['contents']); $this->resetStreams(); $table->sort(1); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_2"), $output['contents']); $this->resetStreams(); foreach ($data as $k => $v) { $data[$k] = array_combine(array("name", "surname", "city", "state"), $v); } $renderer = new \cli\table\Ascii(); $renderer->setCharacters(array("corner" => "x", "line" => "=", "border" => "!")); $table = new \cli\Table($data); $table->setRenderer($renderer); $table->sort("surname"); $table->display(); $output = $this->getStreams(); $this->assertEquals("", $output['errors']); $this->assertEquals(file_get_contents("test/output/table_3"), $output['contents']); $this->assertEquals("[0m", \cli\Colors::color("reset")); $this->assertEquals("foo\tbar", \cli\table\Tabular::row(array("foo", "bar"))); $this->assertNull(\cli\table\Tabular::border()); // test output $this->resetStreams(); \cli\out(" \\cli\\out sends output to STDOUT\n"); \cli\out(" It does not automatically append a new line\n"); \cli\out(" It does accept any number of %s which are then %s to %s for formatting\n", 'arguments', 'passed', 'sprintf'); \cli\out(" Alternatively, {:a} can use an {:b} as the second argument.\n\n", array('a' => 'you', 'b' => 'array')); \cli\err(' \\cli\\err sends output to STDERR'); \cli\err(' It does automatically append a new line'); \cli\err(' It does accept any number of %s which are then %s to %s for formatting', 'arguments', 'passed', 'sprintf'); \cli\err(" Alternatively, {:a} can use an {:b} as the second argument.\n", array('a' => 'you', 'b' => 'array')); \cli\line(' \\cli\\line forwards to \\cli\\out for output'); \cli\line(' It does automatically append a new line'); \cli\line(' It does accept any number of %s which are then %s to %s for formatting', 'arguments', 'passed', 'sprintf'); \cli\line(" Alternatively, {:a} can use an {:b} as the second argument.\n", array('a' => 'you', 'b' => 'array')); $output = $this->getStreams(); $this->assertEquals(file_get_contents("test/output/out_errors"), $output['errors']); $this->assertEquals(file_get_contents("test/output/out_contents"), $output['contents']); $string = ""; $string .= \cli\render(' \\cli\\err sends output to STDERR' . "\n"); $string .= \cli\render(' It does automatically append a new line' . "\n"); $string .= \cli\render(' It does accept any number of %s which are then %s to %s for formatting' . "\n", 'arguments', 'passed', 'sprintf'); $string .= \cli\render(" Alternatively, {:a} can use an {:b} as the second argument.\n\n", array('a' => 'you', 'b' => 'array')); $this->assertEquals(file_get_contents("test/output/out_errors"), $string); $this->resetStreams(); $in = tmpfile(); fputs($in, "quit\n"); fseek($in, 0); \cli\Streams::setStream("in", $in); $line = \cli\prompt("prompt", false, "# "); $output = $this->getStreams(); $this->assertEquals("quit", $line); $this->assertEquals("", $output['errors']); $this->assertEquals("prompt# ", $output['contents']); fseek($in, 0); $this->assertEquals("quit", \cli\input()); fclose($in); }
<?php // Samples. Lines marked with * should be colored in output // php examples/colors.php // * All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // php examples/colors.php | cat // All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // All output is run through \cli\Colors::colorize before display // * All output is run through \cli\Colors::colorize before display // All output is run through \cli\Colors::colorize before display // All output is run through \cli\Colors::colorize before display require_once 'common.php'; \cli\line(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n'); echo \cli\Colors::colorize(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n', true) . "\n"; echo \cli\Colors::colorize(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n') . "\n"; \cli\Colors::enable(); // Forcefully enable \cli\line(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n'); \cli\Colors::disable(); // Disable forcefully! \cli\line(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n', true); \cli\Colors::enable(false); // Enable, but not forcefully \cli\line(' %C%5All output is run through %Y%6\\cli\\Colors::colorize%C%5 before display%n');
/** * Show last Exploit Scanner scan result. * * [--export-csv=<file-name>] * : It will export result to specified csv file * ## EXAMPLES * * wp exploit-scanner result * * @synopsis */ function result($args, $assoc_args) { $default = array('export-csv' => false); $assoc_args = wp_parse_args($assoc_args, $default); delete_transient('exploitscanner_results_trans'); delete_transient('exploitscanner_files'); $results = get_option('exploitscanner_results'); if ($assoc_args['export-csv'] !== false) { $export_csv = array(); $export_csv[] = array('Level', 'Location', 'Description', 'What was matched'); $colorize_start = ''; $colorize_end = ''; } else { $colorize_start = '%R'; $colorize_end = '%n'; } foreach (array('severe', 'warning', 'note') as $l) { if (!empty($results[$l])) { //Level ' . ucwords($l) . ' (' . count($results[$l]) . ' matches) $lines = array(); if (false === $assoc_args['export-csv']) { WP_CLI::line(''); WP_CLI::line(''); WP_CLI::line('Level ' . ucwords($l) . ' (' . count($results[$l]) . ' matches)'); } if (count($results[$l]) > 0) { //$#$# foreach ($results[$l] as &$r) { $r['Level'] = ucwords($l); $r['Location'] = ''; if (isset($r['loc'])) { $r['Location'] .= $r['loc']; if (isset($r['line_no'])) { $r['Location'] .= ':' . $r['line_no']; } } $r['Description'] = ''; if (isset($r['desc'])) { $r['Description'] .= $r['desc']; } $r['What was matched'] = ''; if (isset($r['line'])) { $text = $r['line']; if (strlen($text) > 200) { $start = strpos($text, '$#$#') - 50; if ($start < 0) { $start = 0; } $end = strrpos($text, '#$#$') + 50; $text = substr($text, $start, $end - $start + 1); } $start = strpos($text, '$#$#'); $temp_text = substr($text, $start + 4); $end = strrpos($temp_text, '#$#$'); $highlight_text = substr($temp_text, 0, $end); $replace_text = '$#$#' . $highlight_text . '#$#$'; if (false === $assoc_args['export-csv']) { $r['What was matched'] = htmlspecialchars_decode(str_replace($replace_text, \cli\Colors::colorize($colorize_start . $highlight_text . $colorize_end), $text)); } else { $r['What was matched'] = htmlspecialchars_decode(str_replace($replace_text, $colorize_start . $highlight_text . $colorize_end, $text)); } } if (false !== $assoc_args['export-csv']) { $export_csv[] = array($r['Level'], $r['Location'], $r['Description'], $r['What was matched']); } } if (false === $assoc_args['export-csv']) { $fields = array('Location', 'Description', 'What was matched'); \WP_CLI\Utils\format_items('table', $results[$l], $fields); } } } } if (false !== $assoc_args['export-csv']) { if (file_exists($assoc_args['export-csv'])) { WP_CLI::warning(sprintf("File already exists. The following file will be overwritten %s", $assoc_args['export-csv'])); } $fp = fopen($assoc_args['export-csv'], 'w+'); foreach ($export_csv as $fields) { fputcsv($fp, $fields); } WP_CLI::success(sprintf("File created: %s", $assoc_args['export-csv'])); } }