diff --git a/src/Csv.php b/src/Csv.php index d433d75..51ca6b0 100644 --- a/src/Csv.php +++ b/src/Csv.php @@ -508,6 +508,44 @@ class Csv { return $this->delimiter; } + /** + * Get total number of data rows (exclusive heading line if present) in csv + * without parsing whole data. + * + * @return bool|int + */ + public function getTotalDataRowCount() { + if (empty($this->file_data)) { + return false; + } + + $data = $this->file_data; + + $this->_detect_and_remove_sep_row_from_data($data); + + $pattern = sprintf('/(%1$s[^%1$s]*%1$s)/i', $this->enclosure); + preg_match_all($pattern, $data, $matches); + + foreach ($matches[0] as $match) { + if (empty($match) || (strpos($match, $this->enclosure) === false)) { + continue; + } + + $replace = str_replace(["\r", "\n"], '', $match); + $data = str_replace($match, $replace, $data); + } + + $headingRow = $this->heading ? 1 : 0; + + $count = substr_count($data, "\r") + + substr_count($data, "\n") + - substr_count($data, "\r\n") + - $headingRow; + + + return $count; + } + // ============================================== // ----- [ Core Functions ] --------------------- // ============================================== @@ -883,12 +921,19 @@ class Csv { */ protected function _validate_row_condition($row, $condition) { $operators = array( - '=', 'equals', 'is', - '!=', 'is not', - '<', 'is less than', - '>', 'is greater than', - '<=', 'is less than or equals', - '>=', 'is greater than or equals', + '=', + 'equals', + 'is', + '!=', + 'is not', + '<', + 'is less than', + '>', + 'is greater than', + '<=', + 'is less than or equals', + '>=', + 'is greater than or equals', 'contains', 'does not contain', ); diff --git a/tests/methods/DataRowCountTest.php b/tests/methods/DataRowCountTest.php new file mode 100644 index 0000000..693d736 --- /dev/null +++ b/tests/methods/DataRowCountTest.php @@ -0,0 +1,76 @@ +csv = new Csv(); + } + + public function countRowsProvider() { + return [ + 'auto-double-enclosure' => [ + 'auto-double-enclosure.csv', + 2, + ], + 'auto-single-enclosure' => [ + 'auto-single-enclosure.csv', + 2, + ], + 'UTF-8_sep_row' => [ + 'datatype.csv', + 3, + ], + ]; + } + + /** + * @dataProvider countRowsProvider + * + * @param string $file + * @param int $expectedRows + */ + public function testGetTotalRowCountFromFile($file, $expectedRows) { + $this->csv->heading = true; + $this->csv->load_data(__DIR__ . '/fixtures/' . $file); + $this->assertEquals($expectedRows, $this->csv->getTotalDataRowCount()); + } + + public function testGetTotalRowCountMissingEndingLineBreak() { + $this->csv->heading = false; + $this->csv->enclosure = '"'; + $sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\"c\r\nd\""; + $this->csv->load_data($sInput); + $this->assertEquals(3, $this->csv->getTotalDataRowCount()); + } + + + public function testGetTotalRowCountSingleEnclosure() { + $this->csv->heading = false; + $this->csv->enclosure = "'"; + $sInput = "86545235689,a\r\n34365587654,b\r\n13469874576,\'c\r\nd\'"; + $this->csv->load_data($sInput); + $this->assertEquals(3, $this->csv->getTotalDataRowCount()); + } + +}