From 1354c50f6ce00d42e811e4d26b00f7eeb991873d Mon Sep 17 00:00:00 2001 From: rahul Date: Wed, 20 Sep 2023 11:48:51 +0530 Subject: [PATCH] set limit option to restrict total number of records Signed-off-by: rahul --- bin/view-csv | 15 +++++-- src/CsvFileHandler.php | 52 ++++++++++++++++-------- tests/Integration/ViewCsvCommandTest.php | 13 +++++- tests/unit/CsvFileHandlerTest.php | 21 ++++++++++ 4 files changed, 78 insertions(+), 23 deletions(-) diff --git a/bin/view-csv b/bin/view-csv index 8ac58db..3aea261 100755 --- a/bin/view-csv +++ b/bin/view-csv @@ -17,25 +17,32 @@ use Symfony\Component\Console\Style\SymfonyStyle; $command = (new SingleCommandApplication()) ->addArgument('csvFile', InputArgument::REQUIRED, 'csv file name') ->addOption('hide-column', null, InputOption::VALUE_REQUIRED, 'Columns to hide (comma-separated)') + ->addOption('limit', null, InputOption::VALUE_REQUIRED, 'limit number of records') ->setCode(function (InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $csvFile = $input->getArgument('csvFile'); - $hiddenColumns = $input->getOption('hide-column'); - - $hiddenColumnsArray = explode(',', $hiddenColumns); + $limit = $input->getOption('limit'); if (!file_exists($csvFile)) { $io->error("{$csvFile} does not exists"); return Command::FAILURE; } + if (isset($limit) && !is_numeric($limit)) { + $io->error("{$limit} is not numeric"); + return Command::FAILURE; + } + + $hiddenColumns = $hiddenColumns ? explode(',', $hiddenColumns) : false; + $limit = $limit ? (int)$limit : false; + $serviceContainer = new ServiceContainer(); /** @var CsvFileHandler $csvFileHandler */ $csvFileHandler = $serviceContainer->getContainerBuilder()->get('csv_file_handler'); try { - $data = $csvFileHandler->toArray($csvFile, $hiddenColumnsArray); + $data = $csvFileHandler->toArray($csvFile, $hiddenColumns, $limit); } catch (FileHandlerException) { $io->error('invalid csv file'); return Command::FAILURE; diff --git a/src/CsvFileHandler.php b/src/CsvFileHandler.php index 10a956b..1d2734d 100644 --- a/src/CsvFileHandler.php +++ b/src/CsvFileHandler.php @@ -53,13 +53,13 @@ public function toJson(string $filename): string|false * @return array> * @throws FileHandlerException */ - public function toArray(string $filename, array|false $hideColumns = false): array + public function toArray(string $filename, array|false $hideColumns = false, int|false $limit = false): array { if (!file_exists($filename)) { throw new FileHandlerException('file not found'); } - return iterator_to_array($this->getRows($filename, $hideColumns)); + return iterator_to_array($this->getRows($filename, $hideColumns, $limit)); } public function findAndReplaceInCsv( @@ -148,22 +148,22 @@ private function isValidCsvFileFormat(array $row): bool } /** - * @param array $row + * @param array $headers * @param array $hideColumns - * @return array,int|string> + * @return array,int> */ - private function setColumnsToHide(array &$row, array $hideColumns): array + private function setColumnsToHide(array &$headers, array $hideColumns): array { $indices = []; if (!empty($hideColumns)) { foreach ($hideColumns as $hideColumn) { - $index = array_search($hideColumn, $row); + $index = array_search($hideColumn, $headers); if ($index !== false) { - $indices[] = $index; - unset($row[$index]); + $indices[] = (int)$index; + unset($headers[$index]); } } - $row = array_values($row); + $headers = array_values($headers); } return $indices; } @@ -174,7 +174,7 @@ private function setColumnsToHide(array &$row, array $hideColumns): array * @return Generator * @throws FileHandlerException */ - private function getRows(string $filename, array|false $hideColumns = false): Generator + private function getRows(string $filename, array|false $hideColumns = false, int|false $limit = false): Generator { $csvFile = fopen($filename, 'r'); if (!$csvFile) { @@ -191,6 +191,7 @@ private function getRows(string $filename, array|false $hideColumns = false): Ge $isEmptyFile = true; + $count = 0; try { while (($row = fgetcsv($csvFile)) !== false) { $isEmptyFile = false; @@ -199,18 +200,17 @@ private function getRows(string $filename, array|false $hideColumns = false): Ge } if (!empty($indices)) { - foreach ($indices as $index) { - if (isset($row[$index])) { - unset($row[$index]); - } - } - - $row = array_values($row); + $this->removeElementByIndex($row, $indices); } - $item = array_combine($headers, $row); + $item = array_combine($headers, $row); yield $item; + $count++; + + if (is_int($limit) && $limit <= $count) { + break; + } } } finally { fclose($csvFile); @@ -222,6 +222,22 @@ private function getRows(string $filename, array|false $hideColumns = false): Ge } } + /** + * @param array $row + * @param array, int> $indices + * @return void + */ + private function removeElementByIndex(array &$row, array $indices): void + { + foreach ($indices as $index) { + if (isset($row[$index])) { + unset($row[$index]); + } + } + + $row = array_values($row); + } + /** * @param array $row * @param string $keyword diff --git a/tests/Integration/ViewCsvCommandTest.php b/tests/Integration/ViewCsvCommandTest.php index a2e9a9d..b6b1aac 100644 --- a/tests/Integration/ViewCsvCommandTest.php +++ b/tests/Integration/ViewCsvCommandTest.php @@ -62,9 +62,20 @@ public function viewCsvFileDisplayInformationCorrectly(string $file): void unlink($file); } + #[Test] + public function IfLimitIsSetToNonNumericCommandShouldFail(): void + { + $command = "php bin/view-csv movie.csv --limit hello"; + exec($command, $output, $exitCode); + $actualOutput = implode("\n", $output); + + $this->assertSame(1, $exitCode); + $this->assertStringContainsString("hello is not numeric", $actualOutput); + } + #[Test] #[DataProvider('InvalidFileProvider')] - public function throwExceptionIfFileIsInvalid(string $file): void + public function commandShouldReturnErrorIfFileIsInvalid(string $file): void { $command = "php bin/view-csv {$file}"; exec($command, $output, $exitCode); diff --git a/tests/unit/CsvFileHandlerTest.php b/tests/unit/CsvFileHandlerTest.php index 485a215..b7930d3 100644 --- a/tests/unit/CsvFileHandlerTest.php +++ b/tests/unit/CsvFileHandlerTest.php @@ -125,6 +125,17 @@ public function toArrayMethodWithHideColumnsOptionReturnsValidArray(array $colum $this->assertEquals($expected, $data[0]); } + #[Test] + #[DataProvider('limitDataProvider')] + public function toArrayMethodShouldRestrictNumberOfRecordsWhenLimitIsSet(int $limit): void + { + $data = $this->csvFileHandler->toArray("movie.csv", ["Year"], $limit); + + $count = count($data); + + $this->assertSame($count, $limit); + } + #[Test] public function searchByKeywordAndReturnArray(): void { @@ -267,4 +278,14 @@ public static function columnsToHideDataProvider(): iterable yield [$hideSingleColumn, $expected1]; yield [$hideMultipleColumns, $expected2]; } + + /** + * max limit for the test file is 3 + * @return iterable> + */ + public static function limitDataProvider(): iterable + { + yield [1]; + yield [2]; + } }