mirror of
https://github.com/Codappix/typo3-php-datasets.git
synced 2024-12-04 20:16:11 +01:00
Add command to convert from XML to PHP (#2)
A bin was added with a single command. That command allows to convert multiple XML files to PHP files in place.
This commit is contained in:
parent
5887cb87fe
commit
ae33eeddc9
16 changed files with 459 additions and 5 deletions
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
$finder = (new PhpCsFixer\Finder())
|
||||
->ignoreVCSIgnored(true)
|
||||
->in(realpath(__DIR__));
|
||||
->exclude('Tests/Functional/Converter/Fixtures/Xml/')
|
||||
->in(realpath(__DIR__))
|
||||
;
|
||||
|
||||
return (new \PhpCsFixer\Config())
|
||||
->setRiskyAllowed(true)
|
||||
|
|
13
CHANGELOG.md
Normal file
13
CHANGELOG.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Changelog
|
||||
|
||||
## v1.1.0 - 2023-04-12
|
||||
|
||||
### Added
|
||||
|
||||
- Add bin `typo3-php-datasets`.
|
||||
|
||||
- Add command `convert-from-xml`.
|
||||
|
||||
## v1.0.0 - 2023-04-11
|
||||
|
||||
_Initial release._
|
62
Classes/Command/ConvertFromXml.php
Normal file
62
Classes/Command/ConvertFromXml.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\Xml;
|
||||
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 ConvertFromXml extends Command
|
||||
{
|
||||
protected static $defaultName = 'convert-from-xml';
|
||||
protected static $defaultDescription = 'Converts XML 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 Xml();
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$converter->convert(realpath($file) ?: $file);
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln($e->getMessage());
|
||||
return Command::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
32
Classes/Converter/Converter.php
Normal file
32
Classes/Converter/Converter.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?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;
|
||||
|
||||
interface Converter
|
||||
{
|
||||
/**
|
||||
* @return string The absolute file path to converted file.
|
||||
*/
|
||||
public function convert(string $fileName): string;
|
||||
}
|
104
Classes/Converter/Xml.php
Normal file
104
Classes/Converter/Xml.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\Converter;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use SimpleXMLElement;
|
||||
use SplFileObject;
|
||||
|
||||
class Xml implements Converter
|
||||
{
|
||||
public function convert(string $xmlFileName): string
|
||||
{
|
||||
if (file_exists($xmlFileName) === false) {
|
||||
throw new InvalidArgumentException('Given file "' . $xmlFileName . '" does not exist.', 1681283739);
|
||||
}
|
||||
|
||||
$phpFileName = $this->getNewFileName($xmlFileName);
|
||||
$xmlContent = file_get_contents($xmlFileName);
|
||||
if ($xmlContent === false) {
|
||||
throw new \Exception('Could not read content of file "' . $xmlFileName . '".', 1681287782);
|
||||
}
|
||||
|
||||
try {
|
||||
file_put_contents($phpFileName, $this->buildContent($xmlContent));
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Could not generate new file.', 1681287881, $e);
|
||||
}
|
||||
|
||||
return $phpFileName;
|
||||
}
|
||||
|
||||
private function getNewFileName(string $xmlFileName): string
|
||||
{
|
||||
$file = new SplFileObject($xmlFileName);
|
||||
return str_replace(
|
||||
$file->getBasename(),
|
||||
$file->getBasename($file->getExtension()) . 'php',
|
||||
$file->getRealPath()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from TYPO3 testing framework XML import.
|
||||
*/
|
||||
private function buildContent(string $xmlContent): string
|
||||
{
|
||||
$phpArray = [];
|
||||
$xml = simplexml_load_string($xmlContent);
|
||||
if ($xml === false) {
|
||||
throw new \Exception('Could not parse XML content.', 1681287859);
|
||||
}
|
||||
foreach ($xml->children() as $table) {
|
||||
if (!$table instanceof SimpleXMLElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$insertArray = [];
|
||||
foreach ($table->children() as $column) {
|
||||
if (!$column instanceof SimpleXMLElement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$columnName = $column->getName();
|
||||
$columnValue = (string)$table->$columnName;
|
||||
|
||||
if ((string)($column['is-NULL'] ?? '') === 'yes') {
|
||||
$columnValue = null;
|
||||
}
|
||||
|
||||
$insertArray[$columnName] = $columnValue;
|
||||
}
|
||||
|
||||
$phpArray[$table->getName()][] = $insertArray;
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, [
|
||||
'<?php',
|
||||
'',
|
||||
'return ' . var_export($phpArray, true) . ';',
|
||||
'',
|
||||
]);
|
||||
}
|
||||
}
|
12
README.rst
12
README.rst
|
@ -71,6 +71,18 @@ Within testing framework
|
|||
|
||||
$this->assertPHPDataSet(__DIR__ . '/Fixtures/SimpleSet.php');
|
||||
|
||||
Converter
|
||||
=========
|
||||
|
||||
The package provides a single bin with command to convert existing data-sets.
|
||||
The bin is available as ``typo3-php-datasets``.
|
||||
Available commands:
|
||||
|
||||
- ``convert-from-xml``
|
||||
|
||||
Each command will convert the existing file(s) and place a new php variant next to it.
|
||||
Existing files are only read, not changed.
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
|
|
|
@ -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,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<dataset>
|
||||
<pages>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<title>Page with uid 1 below 0</title>
|
||||
<deleted>0</deleted>
|
||||
</pages>
|
||||
<pages>
|
||||
<uid>2</uid>
|
||||
<pid>1</pid>
|
||||
<title>Page with uid 2 below 1</title>
|
||||
<deleted>0</deleted>
|
||||
</pages>
|
||||
</dataset>
|
|
@ -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,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<dataset>
|
||||
<pages>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<title>Page with uid 1 below 0</title>
|
||||
<deleted>0</deleted>
|
||||
</pages>
|
||||
<tt_content>
|
||||
<uid>1</uid>
|
||||
<pid>1</pid>
|
||||
<header>Content with uid 1 on page 1</header>
|
||||
<deleted>0</deleted>
|
||||
</tt_content>
|
||||
</dataset>
|
14
Tests/Functional/Converter/Fixtures/Xml/SimpleAssert.php
Normal file
14
Tests/Functional/Converter/Fixtures/Xml/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,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<dataset>
|
||||
<pages>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<title>Page with uid 1 below 0</title>
|
||||
<deleted>0</deleted>
|
||||
</pages>
|
||||
</dataset>
|
104
Tests/Functional/Converter/XmlTest.php
Normal file
104
Tests/Functional/Converter/XmlTest.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\Xml;
|
||||
use GlobIterator;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \Codappix\Typo3PhpDatasets\Converter\Xml
|
||||
* @testdox The XML converter
|
||||
*/
|
||||
class XmlTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$filesToDelete = new GlobIterator(__DIR__ . '/Fixtures/Xml/*Incoming.php');
|
||||
foreach ($filesToDelete as $file) {
|
||||
unlink((string)$file);
|
||||
}
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new Xml();
|
||||
|
||||
self::assertInstanceOf(
|
||||
Xml::class,
|
||||
$subject
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function throwsExceptionForNoneExistingFile(): void
|
||||
{
|
||||
$subject = new Xml();
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionCode(1681283739);
|
||||
$this->expectExceptionMessage('Given file "NoneExistingFile.xml" does not exist.');
|
||||
$subject->convert('NoneExistingFile.xml');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider possibleXmlFiles
|
||||
* @testdox Converts $_dataName XML to PHP
|
||||
*/
|
||||
public function convertsXmlFileToPhpFile(
|
||||
string $incomingXmlFile,
|
||||
string $expectedResultFile
|
||||
): void {
|
||||
$subject = new Xml();
|
||||
$result = $subject->convert($incomingXmlFile);
|
||||
|
||||
self::assertFileEquals($expectedResultFile, $result);
|
||||
}
|
||||
|
||||
public static function possibleXmlFiles(): array
|
||||
{
|
||||
return [
|
||||
'Simple' => [
|
||||
'incomingXmlFile' => __DIR__ . '/Fixtures/Xml/SimpleIncoming.xml',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Xml/SimpleAssert.php',
|
||||
],
|
||||
'Multiple records in single table' => [
|
||||
'incomingXmlFile' => __DIR__ . '/Fixtures/Xml/MultipleRecordsInSingleTableIncoming.xml',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Xml/MultipleRecordsInSingleTableAssert.php',
|
||||
],
|
||||
'Records in different tables' => [
|
||||
'incomingXmlFile' => __DIR__ . '/Fixtures/Xml/RecordsInDifferentTablesIncoming.xml',
|
||||
'expectedResultFile' => __DIR__ . '/Fixtures/Xml/RecordsInDifferentTablesAssert.php',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
13
bin/typo3-php-datasets
Executable file
13
bin/typo3-php-datasets
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Codappix\Typo3PhpDatasets\Command\ConvertFromXml;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
$application = new Application();
|
||||
|
||||
$application->add(new ConvertFromXml());
|
||||
|
||||
$application->run();
|
|
@ -19,9 +19,14 @@
|
|||
"email": "coding@daniel-siepmann.de"
|
||||
}
|
||||
],
|
||||
"bin": [
|
||||
"bin/typo3-php-datasets"
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3 || ^7.4 || ^8.0 || ^8.1 || ^8.2",
|
||||
"composer-runtime-api": "^2.2",
|
||||
"doctrine/dbal": "^2.13",
|
||||
"symfony/console": "^5.4",
|
||||
"typo3/cms-core": "^10.4 || ^11.5"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -41,6 +46,8 @@
|
|||
"allow-plugins": {
|
||||
"typo3/class-alias-loader": true,
|
||||
"typo3/cms-composer-installers": true
|
||||
}
|
||||
},
|
||||
"lock": false,
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
|
|
13
shell.nix
13
shell.nix
|
@ -27,19 +27,26 @@ let
|
|||
composer install --prefer-dist --no-progress --working-dir="$PROJECT_ROOT"
|
||||
'';
|
||||
};
|
||||
projectCgl = pkgs.writeShellApplication {
|
||||
name = "project-cgl";
|
||||
runtimeInputs = [
|
||||
php
|
||||
];
|
||||
text = ''
|
||||
./vendor/bin/php-cs-fixer fix --diff
|
||||
'';
|
||||
};
|
||||
|
||||
in pkgs.mkShell {
|
||||
name = "TYPO3 PHP Datasets";
|
||||
buildInputs = [
|
||||
projectInstall
|
||||
projectCgl
|
||||
phpWithXdebug
|
||||
composer
|
||||
pkgs.parallel
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
export PROJECT_ROOT="$(pwd)"
|
||||
|
||||
export typo3DatabaseDriver=pdo_sqlite
|
||||
'';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue