mirror of
https://github.com/Codappix/typo3-php-datasets.git
synced 2024-12-04 20:16:11 +01:00
Add command to convert from CSV to PHP (#10)
This commit is contained in:
parent
3e594a0d15
commit
7589a2bf9a
12 changed files with 346 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
$finder = (new PhpCsFixer\Finder())
|
||||
->ignoreVCSIgnored(true)
|
||||
->exclude('Tests/Functional/Converter/Fixtures/Csv/')
|
||||
->exclude('Tests/Functional/Converter/Fixtures/Xml/')
|
||||
->in(realpath(__DIR__))
|
||||
;
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
## v1.4.0 - 2023-11-07
|
||||
|
||||
### Added
|
||||
|
||||
- Add command `convert-from-csv`.
|
||||
|
||||
## v1.3.1 - 2023-08-10
|
||||
|
||||
### Added
|
||||
|
|
62
Classes/Command/ConvertFromCsv.php
Normal file
62
Classes/Command/ConvertFromCsv.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
namespace Codappix\Typo3PhpDatasets\Command;
|
||||
|
||||
use Codappix\Typo3PhpDatasets\Converter\Csv;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ConvertFromCsv extends Command
|
||||
{
|
||||
protected static $defaultName = 'convert-from-csv';
|
||||
protected static $defaultDescription = 'Converts CSV data-sets to PHP data-sets.';
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->addArgument('file', InputArgument::IS_ARRAY, 'The file(s) to convert.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$files = $input->getArgument('file');
|
||||
if (is_array($files) === false) {
|
||||
$output->writeln('File needs to be an array.');
|
||||
return Command::INVALID;
|
||||
}
|
||||
|
||||
$converter = new Csv();
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$converter->convert(realpath($file) ?: $file);
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln($e->getMessage());
|
||||
return Command::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
99
Classes/Converter/Csv.php
Normal file
99
Classes/Converter/Csv.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
namespace Codappix\Typo3PhpDatasets\Converter;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SplFileObject;
|
||||
|
||||
class Csv implements Converter
|
||||
{
|
||||
public function convert(string $fileName): string
|
||||
{
|
||||
if (file_exists($fileName) === false) {
|
||||
throw new InvalidArgumentException('Given file "' . $fileName . '" does not exist.', 1681283739);
|
||||
}
|
||||
|
||||
$phpFileName = $this->getNewFileName($fileName);
|
||||
$incomingFile = new SplFileObject($fileName);
|
||||
|
||||
try {
|
||||
file_put_contents($phpFileName, $this->buildContent($incomingFile));
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Could not generate new file.', 1681287881, $e);
|
||||
}
|
||||
|
||||
return $phpFileName;
|
||||
}
|
||||
|
||||
private function getNewFileName(string $fileName): string
|
||||
{
|
||||
$file = new SplFileObject($fileName);
|
||||
return str_replace(
|
||||
$file->getBasename(),
|
||||
$file->getBasename($file->getExtension()) . 'php',
|
||||
$file->getRealPath()
|
||||
);
|
||||
}
|
||||
|
||||
private function buildContent(SplFileObject $incomingFile): string
|
||||
{
|
||||
$phpArray = [];
|
||||
$tableName = '';
|
||||
$columns = [];
|
||||
|
||||
$incomingFile->setFlags(SplFileObject::READ_CSV);
|
||||
$incomingFile->setCsvControl(',', '"', '"');
|
||||
|
||||
foreach ($incomingFile as $line) {
|
||||
if (is_array($line) && count($line) === 1 && is_null($line[0])) {
|
||||
// End of file
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_array($line) && count($line) === 1 && is_string($line[0])) {
|
||||
// Line is a new table, introducing also new columns o next row
|
||||
$tableName = $line[0];
|
||||
$columns = [];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($columns === [] && is_array($line)) {
|
||||
$columns = array_slice($line, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($line)) {
|
||||
$values = array_slice($line, 1);
|
||||
$phpArray[$tableName][] = array_combine($columns, $values);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, [
|
||||
'<?php',
|
||||
'',
|
||||
'return ' . var_export($phpArray, true) . ';',
|
||||
'',
|
||||
]);
|
||||
}
|
||||
}
|
104
Tests/Functional/Converter/CsvTest.php
Normal file
104
Tests/Functional/Converter/CsvTest.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
namespace Codappix\Typo3PhpDatasets\Tests\Functional\Converter;
|
||||
|
||||
use Codappix\Typo3PhpDatasets\Converter\Csv;
|
||||
use GlobIterator;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \Codappix\Typo3PhpDatasets\Converter\Csv
|
||||
* @testdox The CSV converter
|
||||
*/
|
||||
class CsvTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$filesToDelete = new GlobIterator(__DIR__ . '/Fixtures/Csv/*Incoming.php');
|
||||
foreach ($filesToDelete as $file) {
|
||||
unlink((string)$file);
|
||||
}
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new Csv();
|
||||
|
||||
self::assertInstanceOf(
|
||||
Csv::class,
|
||||
$subject
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function throwsExceptionForNoneExistingFile(): void
|
||||
{
|
||||
$subject = new Csv();
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionCode(1681283739);
|
||||
$this->expectExceptionMessage('Given file "NoneExistingFile.csv" does not exist.');
|
||||
$subject->convert('NoneExistingFile.csv');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider possibleCsvFiles
|
||||
* @testdox Converts $_dataName CSV to PHP
|
||||
*/
|
||||
public function convertsCsvFileToPhpFile(
|
||||
string $incomingCsvFile,
|
||||
string $expectedResultFile
|
||||
): void {
|
||||
$subject = new Csv();
|
||||
$result = $subject->convert($incomingCsvFile);
|
||||
|
||||
self::assertFileEquals($expectedResultFile, $result);
|
||||
}
|
||||
|
||||
public static function possibleCsvFiles(): array
|
||||
{
|
||||
return [
|
||||
'Simple' => [
|
||||
'incomingCsvFile' => __DIR__ . '/Fixtures/Csv/SimpleIncoming.csv',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Csv/SimpleAssert.php',
|
||||
],
|
||||
'Multiple records in single table' => [
|
||||
'incomingCsvFile' => __DIR__ . '/Fixtures/Csv/MultipleRecordsInSingleTableIncoming.csv',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Csv/MultipleRecordsInSingleTableAssert.php',
|
||||
],
|
||||
'Records in different tables' => [
|
||||
'incomingCsvFile' => __DIR__ . '/Fixtures/Csv/RecordsInDifferentTablesIncoming.csv',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Csv/RecordsInDifferentTablesAssert.php',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
return array (
|
||||
'pages' =>
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
'uid' => '1',
|
||||
'pid' => '0',
|
||||
'title' => 'Page with uid 1 below 0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
'uid' => '2',
|
||||
'pid' => '1',
|
||||
'title' => 'Page with uid 2 below 1',
|
||||
'deleted' => '0',
|
||||
),
|
||||
),
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
pages
|
||||
,uid,pid,title,deleted
|
||||
,1,0,Page with uid 1 below 0,0
|
||||
,2,1,Page with uid 2 below 1,0
|
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
return array (
|
||||
'pages' =>
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
'uid' => '1',
|
||||
'pid' => '0',
|
||||
'title' => 'Page with uid 1 below 0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
),
|
||||
'tt_content' =>
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
'uid' => '1',
|
||||
'pid' => '1',
|
||||
'header' => 'Content with uid 1 on page 1',
|
||||
'deleted' => '0',
|
||||
),
|
||||
),
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
pages
|
||||
,uid,pid,title,deleted
|
||||
,1,0,Page with uid 1 below 0,0
|
||||
tt_content
|
||||
,uid,pid,header,deleted
|
||||
,1,1,Content with uid 1 on page 1,0
|
|
14
Tests/Functional/Converter/Fixtures/Csv/SimpleAssert.php
Normal file
14
Tests/Functional/Converter/Fixtures/Csv/SimpleAssert.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
return array (
|
||||
'pages' =>
|
||||
array (
|
||||
0 =>
|
||||
array (
|
||||
'uid' => '1',
|
||||
'pid' => '0',
|
||||
'title' => 'Page with uid 1 below 0',
|
||||
'deleted' => '0',
|
||||
),
|
||||
),
|
||||
);
|
|
@ -0,0 +1,3 @@
|
|||
pages
|
||||
,uid,pid,title,deleted
|
||||
,1,0,Page with uid 1 below 0,0
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
require $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Codappix\Typo3PhpDatasets\Command\ConvertFromCsv;
|
||||
use Codappix\Typo3PhpDatasets\Command\ConvertFromXml;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$application = new Application();
|
||||
|
||||
$application->add(new ConvertFromXml());
|
||||
$application->add(new ConvertFromCsv());
|
||||
|
||||
$application->run();
|
||||
|
|
Loading…
Reference in a new issue