Skip to content

Commit bea0211

Browse files
committed
Increase and add dev dependencies
This mostly involved PHPStan and pushes us to fix some PHPStan findings.
1 parent 8656731 commit bea0211

16 files changed

Lines changed: 184 additions & 75 deletions

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Tests export-ignore
66

77
.php-cs-fixer.dist.php export-ignore
88
phpstan.neon export-ignore
9+
phpstan-baseline.neon export-ignore
910
phpunit.xml.dist export-ignore
1011

1112
shell.nix export-ignore

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
They modified `@internal` API and it is the fault of this package to use the API.
99
We therefore now move to low level public API of doctrine/dbal instead of TYPO3 internal API.
1010
We also encapsulate the access to those APIs for easier maintenance.
11+
We also raise dev dependencies to have automated CI verification that we do not use internal APIs anymore.
12+
- Proper errors if a record was found in DB, but not within assertions.
13+
- Do not include `phpstan-baseline.neon` in git exports / distribution.
1114

1215
### BREAKING
1316

Classes/Command/ConvertFromCsv.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5555
}
5656

5757
$converter = new Csv();
58-
foreach ($files as $file) {
58+
foreach ($files as $index => $file) {
59+
if (is_string($file) === false) {
60+
$output->writeln(sprintf('File at index "%s" needs to be a string.', $index));
61+
return Command::INVALID;
62+
}
63+
5964
try {
6065
$converter->convert(realpath($file) ?: $file);
6166
} catch (\Exception $e) {

Classes/Command/ConvertFromXml.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5555
}
5656

5757
$converter = new Xml();
58-
foreach ($files as $file) {
58+
foreach ($files as $index => $file) {
59+
if (is_string($file) === false) {
60+
$output->writeln(sprintf('File at index "%s" needs to be a string.', $index));
61+
return Command::INVALID;
62+
}
63+
5964
try {
6065
$converter->convert(realpath($file) ?: $file);
6166
} catch (\Exception $e) {

Classes/Connection.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
namespace Codappix\Typo3PhpDatasets;
2525

26+
use Doctrine\DBAL\ParameterType;
2627
use TYPO3\CMS\Core\Database\Connection as Typo3Connection;
2728

2829
/**
@@ -35,6 +36,10 @@ public function __construct(
3536
) {
3637
}
3738

39+
/**
40+
* @param string[] $record
41+
* @param ParameterType[] $types
42+
*/
3843
public function insert(string $tableName, array $record, array $types): void
3944
{
4045
$this->typo3Connection->insert($tableName, $record, $types);
@@ -44,7 +49,10 @@ public function getTable(string $tableName): Table
4449
{
4550
foreach ($this->typo3Connection->createSchemaManager()->listTables() as $table) {
4651
if ($table->getObjectName()->toString() === $tableName) {
47-
return new Table($table);
52+
return new Table(
53+
$tableName,
54+
$table
55+
);
4856
}
4957
}
5058

Classes/Converter/Xml.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
namespace Codappix\Typo3PhpDatasets\Converter;
2525

2626
use InvalidArgumentException;
27-
use SimpleXMLElement;
2827
use SplFileObject;
2928

3029
class Xml implements Converter
@@ -71,16 +70,8 @@ private function buildContent(string $xmlContent): string
7170
throw new \Exception('Could not parse XML content.', 1681287859);
7271
}
7372
foreach ($xml->children() as $table) {
74-
if (!$table instanceof SimpleXMLElement) {
75-
continue;
76-
}
77-
7873
$insertArray = [];
7974
foreach ($table->children() as $column) {
80-
if (!$column instanceof SimpleXMLElement) {
81-
continue;
82-
}
83-
8475
$columnName = $column->getName();
8576
$columnValue = (string)$table->$columnName;
8677

Classes/PhpDataSet.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class PhpDataSet
3030
{
3131
/**
3232
* @api
33+
* @param array<string, array<string, string>[]> $dataSet
3334
*/
3435
public function import(array $dataSet): void
3536
{

Classes/Table.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
final readonly class Table
3434
{
3535
public function __construct(
36+
private string $tableName,
3637
private DbalTable $dbalTable,
3738
) {
3839
}
@@ -49,7 +50,7 @@ public function getTypeForColumn(string $columnName): ParameterType
4950
throw new \RuntimeException(sprintf(
5051
'Column "%s" does not exist in table: %s',
5152
$columnName,
52-
$this->dbalTable->getName(),
53+
$this->tableName,
5354
), 1760941225);
5455
}
5556
}

Classes/TestingFramework.php

Lines changed: 74 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ trait TestingFramework
3636
*/
3737
protected function importPHPDataSet(string $filePath): void
3838
{
39-
$this->ensureFileExists($filePath);
40-
41-
$dataSet = include $filePath;
39+
$dataSet = $this->getDataSet($filePath);
4240
try {
4341
(new PhpDataSet())->import($dataSet);
4442
} catch (Exception $e) {
@@ -52,57 +50,106 @@ protected function importPHPDataSet(string $filePath): void
5250
*/
5351
protected function assertPHPDataSet(string $filePath): void
5452
{
55-
$this->ensureFileExists($filePath);
53+
if (is_array($GLOBALS['TCA'] ?? null) === false) {
54+
throw new \RuntimeException('TYPO3 GLOBALS["TCA"] is not defined.', 1760942400);
55+
}
5656

57-
$dataSet = include $filePath;
5857
$failMessages = [];
59-
60-
foreach ($dataSet as $tableName => $expectedRecords) {
58+
foreach ($this->getDataSet($filePath) as $tableName => $expectedRecords) {
6159
$records = $this->getAllRecords($tableName, (isset($GLOBALS['TCA'][$tableName])));
6260

6361
foreach ($expectedRecords as $assertion) {
6462
$result = $this->assertInRecords($assertion, $records);
6563
if ($result === false) {
66-
// Handle error
67-
if (isset($assertion['uid']) && empty($records[$assertion['uid']])) {
68-
$failMessages[] = 'Record "' . $tableName . ':' . $assertion['uid'] . '" not found in database';
69-
continue;
70-
}
71-
if (isset($assertion['uid'])) {
72-
$recordIdentifier = $tableName . ':' . $assertion['uid'];
73-
$additionalInformation = $this->renderRecords($assertion, $records[$assertion['uid']]);
74-
} else {
75-
$recordIdentifier = $tableName;
76-
$additionalInformation = $this->arrayToString($assertion);
77-
}
78-
79-
$failMessages[] = 'Assertion in data-set failed for "' . $recordIdentifier . '":' . PHP_EOL . $additionalInformation;
64+
$failMessages[] = $this->getAssertionErrorMessageForNoneMatchingRecord($assertion, $records, $tableName);
8065
continue;
8166
}
8267

83-
// Unset asserted record
68+
// Unset already asserted record to only keep unexpected records.
8469
unset($records[$result]);
70+
8571
// Increase assertion counter
86-
self::assertTrue($result !== false);
72+
self::assertTrue(true);
8773
}
8874

89-
if (!empty($records)) {
90-
foreach ($records as $record) {
91-
$recordIdentifier = $tableName . ':' . ($record['uid'] ?? '');
92-
$failMessages[] = 'Not asserted record found for "' . $recordIdentifier . '".';
75+
foreach ($records as $record) {
76+
if (is_array($record) === false) {
77+
throw new \RuntimeException('Something went horribly wrong while fetching records, record was not an array.', 1760943536);
9378
}
79+
80+
$failMessages[] = $this->getAssertionErrorMessageForUnexpectedRecord($record, $tableName);
9481
}
9582
}
9683

84+
$failMessages = array_filter($failMessages);
85+
9786
if (!empty($failMessages)) {
9887
self::fail(implode(PHP_EOL, $failMessages));
9988
}
10089
}
10190

91+
/**
92+
* @return array<string, array<string, string>[]>
93+
*/
94+
private function getDataSet(string $filePath): array
95+
{
96+
$this->ensureFileExists($filePath);
97+
98+
$dataSet = require $filePath;
99+
if (is_array($dataSet) === false) {
100+
throw new \RuntimeException('Given file did not return an array: ' . $filePath, 1760942255);
101+
}
102+
103+
return $dataSet;
104+
}
105+
102106
private function ensureFileExists(string $filePath): void
103107
{
104108
if (file_exists($filePath) === false) {
105109
throw new InvalidArgumentException('The requested PHP data-set file "' . $filePath . '" does not exist.', 1681207108);
106110
}
107111
}
112+
113+
/**
114+
* @param array{uid: int|string|null} $assertion
115+
* @param array<string|int, mixed[]> $records
116+
*/
117+
private function getAssertionErrorMessageForNoneMatchingRecord(array $assertion, array $records, string $tableName): string
118+
{
119+
// Handle error
120+
if (isset($assertion['uid']) && empty($records[$assertion['uid']])) {
121+
return 'Record "' . $tableName . ':' . $assertion['uid'] . '" not found in database';
122+
}
123+
124+
if (isset($assertion['uid'])) {
125+
$record = $records[$assertion['uid']] ?? null;
126+
if (is_array($record) === false) {
127+
return 'Assertion in data-set failed for "' . $tableName . ':' . $assertion['uid'] . '": Uid missing in database' . PHP_EOL;
128+
}
129+
130+
return 'Assertion in data-set failed for "' . $tableName . ':' . $assertion['uid'] . '":' . PHP_EOL . $this->renderRecords($assertion, $record);
131+
}
132+
133+
return 'Assertion in data-set failed for "' . $tableName . '":' . PHP_EOL . $this->arrayToString($assertion);
134+
}
135+
136+
/**
137+
* @param mixed[] $record
138+
*/
139+
private function getAssertionErrorMessageForUnexpectedRecord(array $record, string $tableName): string
140+
{
141+
if (is_numeric($record['uid'] ?? null)) {
142+
return sprintf(
143+
'Not asserted record with uid "%s" found for table "%s".',
144+
$record['uid'],
145+
$tableName
146+
);
147+
}
148+
149+
return sprintf(
150+
'Not asserted record found for table "%s": %s',
151+
$tableName,
152+
PHP_EOL . var_export($record, true)
153+
);
154+
}
108155
}

Tests/Functional/AssertTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,15 @@ public function failsForAssertionForMmRelation(): void
120120
' \'sorting_foreign\' => \'3\'',
121121
')',
122122
'',
123-
'Not asserted record found for "sys_category_record_mm:".',
123+
'Not asserted record found for table "sys_category_record_mm": ',
124+
'array (',
125+
' \'uid_local\' => 1,',
126+
' \'uid_foreign\' => 2,',
127+
' \'sorting\' => 0,',
128+
' \'sorting_foreign\' => 2,',
129+
' \'tablenames\' => \'pages\',',
130+
' \'fieldname\' => \'categories\',',
131+
')',
124132
]));
125133
$this->assertPHPDataSet(__DIR__ . '/Fixtures/MmRelationBroken.php');
126134
}
@@ -131,7 +139,7 @@ public function failsForAdditionalNoneAssertedRecords(): void
131139
$this->importPHPDataSet(__DIR__ . '/Fixtures/WithDifferentColumns.php');
132140

133141
$this->expectException(AssertionFailedError::class);
134-
$this->expectExceptionMessage('Not asserted record found for "pages:2".');
142+
$this->expectExceptionMessage('Not asserted record with uid "2" found for table "pages".');
135143
$this->assertPHPDataSet(__DIR__ . '/Fixtures/AssertAdditionalRecords.php');
136144
}
137145

0 commit comments

Comments
 (0)