Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions bin/view-csv
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ require 'vendor/autoload.php';

use rcsofttech85\FileHandler\CsvFileHandler;
use rcsofttech85\FileHandler\DI\ServiceContainer;
use rcsofttech85\FileHandler\Exception\FileHandlerException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SingleCommandApplication;
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)')
->setCode(function (InputInterface $input, OutputInterface $output): int {
$io = new SymfonyStyle($input, $output);
$csvFile = $input->getArgument('csvFile');

$hiddenColumns = $input->getOption('hide-column');

$hiddenColumnsArray = explode(',', $hiddenColumns);

if (!file_exists($csvFile)) {
$io->error("{$csvFile} does not exists");
Expand All @@ -28,23 +34,20 @@ $command = (new SingleCommandApplication())
/** @var CsvFileHandler $csvFileHandler */
$csvFileHandler = $serviceContainer->getContainerBuilder()->get('csv_file_handler');

$io->title($csvFile);
$table = $io->createTable();
$headers = $csvFileHandler->extractHeader($csvFile);

if (!$headers) {
try {
$data = $csvFileHandler->toArray($csvFile, $hiddenColumnsArray);
} catch (FileHandlerException) {
$io->error('invalid csv file');
return Command::FAILURE;
}


$headers = array_keys($data[0]);
$io->title($csvFile);
$table = $io->createTable();
$table->setHeaders($headers);
$table->setRows($csvFileHandler->toArray($csvFile));

$table->setRows($data);
$table->render();

$io->newLine();


return Command::SUCCESS;
})->run();
46 changes: 42 additions & 4 deletions src/CsvFileHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,17 @@ public function toJson(string $filename): string|false

/**
* @param string $filename
* @param array<string> $hideColumns
* @return array<int,array<string,string>>
* @throws FileHandlerException
*/
public function toArray(string $filename): array
public function toArray(string $filename, array|false $hideColumns = false): array
{
if (!file_exists($filename)) {
throw new FileHandlerException('file not found');
}

return iterator_to_array($this->getRows($filename));
return iterator_to_array($this->getRows($filename, $hideColumns));
}

public function findAndReplaceInCsv(
Expand Down Expand Up @@ -107,7 +108,7 @@ public function findAndReplaceInCsv(
* @return array<string>|false
*/

public function extractHeader(mixed $file): array|false
private function extractHeader(mixed $file): array|false
{
$headers = [];
if (is_resource($file)) {
Expand Down Expand Up @@ -146,12 +147,34 @@ private function isValidCsvFileFormat(array $row): bool
return true;
}

/**
* @param array<string> $row
* @param array<string> $hideColumns
* @return array<int<0, max>,int|string>
*/
private function setColumnsToHide(array &$row, array $hideColumns): array
{
$indices = [];
if (!empty($hideColumns)) {
foreach ($hideColumns as $hideColumn) {
$index = array_search($hideColumn, $row);
if ($index !== false) {
$indices[] = $index;
unset($row[$index]);
}
}
$row = array_values($row);
}
return $indices;
}

/**
* @param string $filename
* @param array<string>|false $hideColumns
* @return Generator
* @throws FileHandlerException
*/
private function getRows(string $filename): Generator
private function getRows(string $filename, array|false $hideColumns = false): Generator
{
$csvFile = fopen($filename, 'r');
if (!$csvFile) {
Expand All @@ -162,6 +185,10 @@ private function getRows(string $filename): Generator
throw new FileHandlerException('could not extract header');
}

if (is_array($hideColumns)) {
$indices = $this->setColumnsToHide($headers, $hideColumns);
}


$isEmptyFile = true;
try {
Expand All @@ -170,6 +197,17 @@ private function getRows(string $filename): Generator
if (!$this->isValidCsvFileFormat($row)) {
throw new FileHandlerException('invalid csv file format');
}

if (!empty($indices)) {
foreach ($indices as $index) {
if (isset($row[$index])) {
unset($row[$index]);
}
}

$row = array_values($row);
}

$item = array_combine($headers, $row);

yield $item;
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/CsvFileHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ public function toArrayMethodReturnsValidArray(): void
$this->assertEquals($expected, $data[0]);
}

/**
* @param array<string> $columnsToHide
* @param array<string,string> $expected
* @return void
* @throws FileHandlerException
*/
#[Test]
#[DataProvider('columnsToHideDataProvider')]
public function toArrayMethodWithHideColumnsOptionReturnsValidArray(array $columnsToHide, array $expected): void
{
$data = $this->csvFileHandler->toArray("movie.csv", $columnsToHide);
$this->assertEquals($expected, $data[0]);
}

#[Test]
public function searchByKeywordAndReturnArray(): void
{
Expand Down Expand Up @@ -220,4 +234,37 @@ public static function wrongColumnNameProvider(): iterable
yield ["wrong"];
yield ["honey bee"];
}

/**
* @return iterable<array<array<string>>>
*/
public static function columnsToHideDataProvider(): iterable
{
$hideSingleColumn = ["Film"];
$expected1 = [
'Genre' => 'Romance',
'Lead Studio' => 'The Weinstein Company',
'Audience score %' => '70',
'Profitability' => '1.747541667',
'Rotten Tomatoes %' => '64',
'Worldwide Gross' => '$41.94 ',
'Year' => '2008'

];

$hideMultipleColumns = ["Film", "Profitability", "Year"];
$expected2 = [
'Genre' => 'Romance',
'Lead Studio' => 'The Weinstein Company',
'Audience score %' => '70',
'Rotten Tomatoes %' => '64',
'Worldwide Gross' => '$41.94 ',


];


yield [$hideSingleColumn, $expected1];
yield [$hideMultipleColumns, $expected2];
}
}