diff --git a/src/Csv.php b/src/Csv.php index 9a77efd..212f10e 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -793,8 +793,15 @@ class Csv { $entry = array(); // create heading + $fieldOrder = $this->_validate_fields_for_unparse($fields); + if (!$fieldOrder && !empty($data)) { + $column_count = count($data[0]); + $columns = range(0, $column_count - 1, 1); + $fieldOrder = array_combine($columns, $columns); + } + if ($this->heading && !$append && !empty($fields)) { - foreach ($fields as $key => $column_name) { + foreach ($fieldOrder as $column_name) { $entry[] = $this->_enclose_value($column_name, $delimiter); } @@ -804,7 +811,8 @@ class Csv { // create data foreach ($data as $key => $row) { - foreach ($row as $cell_value) { + foreach (array_keys($fieldOrder) as $index){ + $cell_value = $row[$index]; $entry[] = $this->_enclose_value($cell_value, $delimiter); } @@ -819,6 +827,36 @@ class Csv { return $string; } + private function _validate_fields_for_unparse($fields){ + if (empty($fields)){ + return []; + } + + // both are identical, also in ordering + if (array_values($fields) === array_values($this->titles)){ + return array_combine($fields, $fields); + } + + // if renaming given by: $oldName => $newName (maybe with reorder and / or subset): + // todo: this will only work if titles are unique + $fieldOrder = array_intersect(array_flip($fields), $this->titles); + if (!empty($fieldOrder)) { + return array_flip($fieldOrder); + } + + $fieldOrder = array_intersect($fields, $this->titles); + if (!empty($fieldOrder)) { + return array_combine($fieldOrder, $fieldOrder); + } + + // original titles are not given in fields. that is okay if count is okay. + if (count($fields) != count($this->titles)) { + throw new \UnexpectedValueException('The specified fields do not match any titles and do not match column count.'); + } + + return array_combine($this->titles, $fields); + } + /** * Load local file or string * diff --git a/tests/methods/UnparseTest.php b/tests/methods/UnparseTest.php new file mode 100644 index 0000000..dbc1f75 --- /dev/null +++ b/tests/methods/UnparseTest.php @@ -0,0 +1,62 @@ +csv = new Csv(); + $this->csv->auto(__DIR__ . '/fixtures/auto-double-enclosure.csv'); + } + + public function testUnparseDefault() { + $expected = "column1,column2\rvalue1,value2\rvalue3,value4\r"; + $this->unparseAndCompare($expected); + } + + public function testUnparseDefaultWithoutHeading(){ + $this->csv->heading = false; + $this->csv->auto(__DIR__ . '/fixtures/auto-double-enclosure.csv'); + $expected = "column1,column2\rvalue1,value2\rvalue3,value4\r"; + $this->unparseAndCompare($expected); + + } + + public function testUnparseRenameFields() { + $expected = "C1,C2\rvalue1,value2\rvalue3,value4\r"; + $this->unparseAndCompare($expected, array("C1", "C2")); + } + + public function testReorderFields() { + $expected = "column2,column1\rvalue2,value1\rvalue4,value3\r"; + $this->unparseAndCompare($expected, array("column2", "column1")); + } + + public function testSubsetFields() { + $expected = "column1\rvalue1\rvalue3\r"; + $this->unparseAndCompare($expected, array("column1")); + } + + public function testReorderAndRenameFields() { + $fields = array( + 'column2' => 'C2', + 'column1' => 'C1', + ); + $expected = "C2,C1\rvalue2,value1\rvalue4,value3\r"; + $this->unparseAndCompare($expected, $fields); + } + + private function unparseAndCompare($expected, $fields = array()) { + $str = $this->csv->unparse($this->csv->data, $fields); + $this->assertEquals($expected, $str); + } + +}