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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Tests export-ignore

.php-cs-fixer.dist.php export-ignore
phpstan.neon export-ignore
phpstan-baseline.neon export-ignore
phpunit.xml.dist export-ignore

shell.nix export-ignore
65 changes: 0 additions & 65 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ jobs:
strategy:
matrix:
php-version:
- 7.2
- 7.3
- 7.4
- 8.0
- 8.1
- 8.2
- 8.3
- 8.4
Expand Down Expand Up @@ -102,42 +97,6 @@ jobs:
strategy:
matrix:
include:
- db-version: '5.7'
php-version: '7.2'
typo3-version: '^10.4'
- db-version: '5.7'
php-version: '7.3'
typo3-version: '^10.4'
- db-version: '8'
php-version: '7.4'
typo3-version: '^10.4'
- db-version: '8'
php-version: '7.4'
typo3-version: '^11.5'
- db-version: '8'
php-version: '8.0'
typo3-version: '^11.5'
- db-version: '8'
php-version: '8.1'
typo3-version: '^11.5'
- db-version: '8'
php-version: '8.2'
typo3-version: '^11.5'
- db-version: '8'
php-version: '8.3'
typo3-version: '^11.5'
- db-version: '8'
php-version: '8.1'
typo3-version: '^12.4'
- db-version: '8'
php-version: '8.2'
typo3-version: '^12.4'
- db-version: '8'
php-version: '8.3'
typo3-version: '^12.4'
- db-version: '8'
php-version: '8.4'
typo3-version: '^12.4'
- db-version: '8'
php-version: '8.2'
typo3-version: '^13.0'
Expand Down Expand Up @@ -189,30 +148,6 @@ jobs:
strategy:
matrix:
include:
- php-version: '7.2'
typo3-version: '^10.4'
- php-version: '7.3'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^10.4'
- php-version: '7.4'
typo3-version: '^11.5'
- php-version: '8.0'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^11.5'
- php-version: '8.2'
typo3-version: '^11.5'
- php-version: '8.3'
typo3-version: '^11.5'
- php-version: '8.1'
typo3-version: '^12.4'
- php-version: '8.2'
typo3-version: '^12.4'
- php-version: '8.3'
typo3-version: '^12.4'
- php-version: '8.4'
typo3-version: '^12.4'
- php-version: '8.2'
typo3-version: '^13.4'
- php-version: '8.3'
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## v2.0.0 - 2025-10-20

### Added

- Support for TYPO3 13.4.19.
They modified `@internal` API and it is the fault of this package to use the API.
We therefore now move to low level public API of doctrine/dbal instead of TYPO3 internal API.
We also encapsulate the access to those APIs for easier maintenance.
We also raise dev dependencies to have automated CI verification that we do not use internal APIs anymore.
- Proper errors if a record was found in DB, but not within assertions.
- Do not include `phpstan-baseline.neon` in git exports / distribution.

### BREAKING

- Remove support for older dependencies.
The older versions of this package should work just fine.
There is not much more to this package, so no need to stay compatible with all versions.

## v1.6.0 - 2025-03-04

### Added
Expand Down
7 changes: 6 additions & 1 deletion Classes/Command/ConvertFromCsv.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

$converter = new Csv();
foreach ($files as $file) {
foreach ($files as $index => $file) {
if (is_string($file) === false) {
$output->writeln(sprintf('File at index "%s" needs to be a string.', $index));
return Command::INVALID;
}

try {
$converter->convert(realpath($file) ?: $file);
} catch (\Exception $e) {
Expand Down
7 changes: 6 additions & 1 deletion Classes/Command/ConvertFromXml.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

$converter = new Xml();
foreach ($files as $file) {
foreach ($files as $index => $file) {
if (is_string($file) === false) {
$output->writeln(sprintf('File at index "%s" needs to be a string.', $index));
return Command::INVALID;
}

try {
$converter->convert(realpath($file) ?: $file);
} catch (\Exception $e) {
Expand Down
61 changes: 61 additions & 0 deletions Classes/Connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

/*
* Copyright (C) 2025 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;

use Doctrine\DBAL\ParameterType;
use TYPO3\CMS\Core\Database\Connection as Typo3Connection;

/**
* @internal
*/
final readonly class Connection
{
public function __construct(
private Typo3Connection $typo3Connection,
) {
}

/**
* @param string[] $record
* @param ParameterType[] $types
*/
public function insert(string $tableName, array $record, array $types): void
{
$this->typo3Connection->insert($tableName, $record, $types);
}

public function getTable(string $tableName): Table
{
foreach ($this->typo3Connection->createSchemaManager()->listTables() as $table) {
if ($table->getObjectName()->toString() === $tableName) {
return new Table(
$tableName,
$table
);
}
}

throw new \RuntimeException('Could not fetch table details for table: ' . $tableName, 1760939710);
}
}
37 changes: 37 additions & 0 deletions Classes/ConnectionFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/*
* Copyright (C) 2025 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;

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;

final readonly class ConnectionFactory
{
public function createForTable(string $tableName): Connection
{
return new Connection(
GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName)
);
}
}
9 changes: 0 additions & 9 deletions Classes/Converter/Xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
namespace Codappix\Typo3PhpDatasets\Converter;

use InvalidArgumentException;
use SimpleXMLElement;
use SplFileObject;

class Xml implements Converter
Expand Down Expand Up @@ -71,16 +70,8 @@ private function buildContent(string $xmlContent): string
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;

Expand Down
39 changes: 13 additions & 26 deletions Classes/PhpDataSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,27 @@

namespace Codappix\Typo3PhpDatasets;

use RuntimeException;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* @api
*/
class PhpDataSet
{
/**
* @api
* @param array<string, array<string, string>[]> $dataSet
*/
public function import(array $dataSet): void
{
foreach ($dataSet as $tableName => $records) {
$connection = $this->getConnectionPool()->getConnectionForTable($tableName);

if (method_exists($connection, 'getSchemaManager')) {
// <= 12
$tableDetails = $connection->getSchemaManager()->listTableDetails($tableName);
} elseif (method_exists($connection, 'getSchemaInformation')) {
// >= 13
$tableDetails = $connection->getSchemaInformation()->introspectTable($tableName);
} else {
throw new RuntimeException('Could not check the schema for table: ' . $tableName, 1707144020);
}
$connectionFactory = new ConnectionFactory();

foreach ($records as $record) {
$types = [];
foreach (array_keys($record) as $columnName) {
$types[] = $tableDetails->getColumn((string)$columnName)->getType()->getBindingType();
}
foreach ($dataSet as $tableName => $records) {
$connection = $connectionFactory->createForTable($tableName);
$table = $connection->getTable($tableName);

foreach ($records as $index => $record) {
$types = array_map($table->getTypeForColumn(...), array_keys($record));
$connection->insert($tableName, $record, $types);
}
}
}

private function getConnectionPool(): ConnectionPool
{
return GeneralUtility::makeInstance(ConnectionPool::class);
}
}
57 changes: 57 additions & 0 deletions Classes/Table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

/*
* Copyright (C) 2025 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;

use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Doctrine\DBAL\Schema\Table as DbalTable;

/**
* @internal
*/
final readonly class Table
{
public function __construct(
private string $tableName,
private DbalTable $dbalTable,
) {
}

public function getTypeForColumn(string $columnName): ParameterType
{
try {
return $this->dbalTable
->getColumn((string)$columnName)
->getType()
->getBindingType()
;
} catch (ColumnDoesNotExist $e) {
throw new \RuntimeException(sprintf(
'Column "%s" does not exist in table: %s',
$columnName,
$this->tableName,
), 1760941225);
}
}
}
Loading
Loading