Skip to content

Commit 2171fd1

Browse files
committed
feat(config): Configuration from JSON generation with conditions for export/import
feat(export): Introduced `ExportTable` and `ExportTableFactory` chore: fix psr-4 path for PHPStorm, add singlethreaded tests run
1 parent 301ad8a commit 2171fd1

30 files changed

+1308
-78
lines changed

composer.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525
],
2626
"autoload": {
2727
"psr-4": {
28-
"EcomDev\\MySQL2JSONL\\": "src"
28+
"EcomDev\\MySQL2JSONL\\": "src/"
2929
}
3030
},
3131
"autoload-dev": {
3232
"psr-4": {
33-
"EcomDev\\MySQL2JSONL\\": "tests"
33+
"EcomDev\\MySQL2JSONL\\": "tests/"
3434
}
3535
},
3636
"scripts": {
3737
"test": "XDEBUG_MODE=coverage paratest --coverage-text",
38+
"test:single-threaded": "XDEBUG_MODE=coverage phpunit --coverage-text",
3839
"format:check": "phpcs",
3940
"format:write": "phpcbf"
4041
},

schema.json

+32-8
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616
"description": "List of tables to exclude from the database dump"
1717
}
1818
},
19+
"additionalProperties": false,
1920
"definitions": {
2021
"matchExpression": {
2122
"type": "object",
2223
"description": "Match condition for table name",
2324
"properties": {
2425
"regexp": {
2526
"type": "string",
26-
"description": "Valid regular expression for a table name with qualifiers"
27+
"description": "Valid regular expression for a table name, # sign is prohibited as used as delimiter",
28+
"pattern": "^[^#]+$"
2729
},
2830
"startsWith": {
2931
"type": "string",
@@ -60,14 +62,34 @@
6062
"type": "string",
6163
"pattern": "^[0-9a-zA-Z$_\u0080-\uFFFF]+$"
6264
},
65+
"andCondition": {
66+
"type": "array",
67+
"description": "Table matching conditions",
68+
"items": {
69+
"oneOf": [
70+
{ "$ref": "#/definitions/matchExpression" },
71+
{ "$ref": "#/definitions/rowCount" },
72+
{ "$ref": "#/definitions/tableName" }
73+
]
74+
}
75+
},
6376
"tableConditions": {
6477
"type": "array",
6578
"description": "Table matching conditions",
66-
"oneOf": [
67-
{ "$ref": "#/definitions/matchExpression" },
68-
{ "$ref": "#/definitions/rowCount" },
69-
{ "$ref": "#/definitions/tableName" }
70-
]
79+
"default": [],
80+
"items": {
81+
"anyOf": [
82+
{ "$ref": "#/definitions/matchExpression" },
83+
{ "$ref": "#/definitions/rowCount" },
84+
{ "$ref": "#/definitions/tableName" },
85+
{
86+
"type": "object",
87+
"properties": {
88+
"and": {"$ref": "#/definitions/andCondition"}
89+
}
90+
}
91+
]
92+
}
7193
},
7294
"connection": {
7395
"type": "object",
@@ -107,11 +129,13 @@
107129
},
108130
"sqlMode": {
109131
"type": "string",
110-
"description": "SQL_MODE to set for the connection"
132+
"description": "SQL_MODE to set for the connection",
133+
"default": ""
111134
},
112135
"useCompression": {
113136
"type": "boolean",
114-
"description": "Use compression for MySQL connection"
137+
"description": "Use compression for MySQL connection",
138+
"default": false
115139
},
116140
"key": {
117141
"type": "string",

src/Condition/AndTableCondition.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
final readonly class AndTableCondition implements TableCondition
15+
{
16+
public function __construct(private array $conditions)
17+
{
18+
}
19+
20+
public function isSatisfiedBy(string $tableName, int $rows): bool
21+
{
22+
return array_reduce(
23+
$this->conditions,
24+
fn ($carry, TableCondition $condition) => $carry && $condition->isSatisfiedBy($tableName, $rows),
25+
true
26+
);
27+
}
28+
29+
public function withCondition(TableCondition $condition): TableCondition
30+
{
31+
$conditions = $this->conditions;
32+
$conditions[] = $condition;
33+
return new self($conditions);
34+
}
35+
36+
public static function from(TableCondition...$conditions): TableCondition
37+
{
38+
return new self($conditions);
39+
}
40+
}

src/Condition/AnyTableCondition.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
final readonly class AnyTableCondition implements TableCondition
15+
{
16+
public function __construct(private array $conditions)
17+
{
18+
19+
}
20+
21+
public function isSatisfiedBy(string $tableName, int $rows): bool
22+
{
23+
return array_reduce(
24+
$this->conditions,
25+
fn ($carry, TableCondition $condition) => $carry || $condition->isSatisfiedBy($tableName, $rows),
26+
false
27+
);
28+
}
29+
30+
public function withCondition(TableCondition $condition): TableCondition
31+
{
32+
$conditions = $this->conditions;
33+
$conditions[] = $condition;
34+
return new self($conditions);
35+
}
36+
}

src/Condition/ComposeAndCondition.php

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
trait ComposeAndCondition
15+
{
16+
public function withCondition(TableCondition $condition): TableCondition
17+
{
18+
return new AndTableCondition([$this, $condition]);
19+
}
20+
}

src/Condition/ComposeAnyCondition.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
trait ComposeAnyCondition
15+
{
16+
public function withCondition(TableCondition $condition): TableCondition
17+
{
18+
return match ($this::class) {
19+
StaticTableCondition::class => new AnyTableCondition([$condition]),
20+
default => new AnyTableCondition([$this, $condition]),
21+
};
22+
}
23+
}

src/StaticTableCondition.php renamed to src/Condition/StaticTableCondition.php

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
<?php
22

3-
namespace EcomDev\MySQL2JSONL;
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
413

514
final readonly class StaticTableCondition implements TableCondition
615
{
16+
use ComposeAnyCondition;
17+
718
private function __construct(private bool $result)
819
{
920
}
@@ -23,9 +34,4 @@ public function isSatisfiedBy(string $tableName, int $rows): bool
2334
{
2435
return $this->result;
2536
}
26-
27-
public function withCondition(TableCondition $condition): TableCondition
28-
{
29-
return $this;
30-
}
3137
}

src/Condition/TableNameCondition.php

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
final readonly class TableNameCondition implements TableCondition
15+
{
16+
use ComposeAndCondition;
17+
18+
private const EXACT_MATCH = 'exact';
19+
private const STARTS_WITH = 'starts';
20+
private const ENDS_WITH = 'ends';
21+
private const CONTAINS = 'contains';
22+
private const REGEXP = 'regexp';
23+
24+
private function __construct(private string $tableName, private string $matchType)
25+
{
26+
}
27+
28+
public static function exactMatch(string $tableName): TableNameCondition
29+
{
30+
return new TableNameCondition($tableName, self::EXACT_MATCH);
31+
}
32+
33+
public static function startsWith(string $tableName): TableNameCondition
34+
{
35+
return new TableNameCondition($tableName, self::STARTS_WITH);
36+
}
37+
38+
public static function endsWith(string $tableName): TableNameCondition
39+
{
40+
return new TableNameCondition($tableName, self::ENDS_WITH);
41+
}
42+
43+
public static function contains(string $tableName): TableNameCondition
44+
{
45+
return new TableNameCondition($tableName, self::CONTAINS);
46+
}
47+
48+
public static function regexp(string $regexp): TableNameCondition
49+
{
50+
return new TableNameCondition($regexp, self::REGEXP);
51+
}
52+
53+
54+
public function isSatisfiedBy(string $tableName, int $rows): bool
55+
{
56+
return match ($this->matchType) {
57+
self::EXACT_MATCH => $tableName === $this->tableName,
58+
self::STARTS_WITH => str_starts_with($tableName, $this->tableName),
59+
self::ENDS_WITH => str_ends_with($tableName, $this->tableName),
60+
self::CONTAINS => str_contains($tableName, $this->tableName),
61+
self::REGEXP => !!preg_match($this->tableName, $tableName),
62+
default => false
63+
};
64+
}
65+
}

src/Condition/TableRowsCondition.php

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/**
4+
* Copyright © EcomDev B.V. All rights reserved.
5+
* See LICENSE for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace EcomDev\MySQL2JSONL\Condition;
11+
12+
use EcomDev\MySQL2JSONL\TableCondition;
13+
14+
class TableRowsCondition implements TableCondition
15+
{
16+
use ComposeAndCondition;
17+
18+
private const MIN_ROWS = 'min_rows';
19+
private const MAX_ROWS = 'max_rows';
20+
21+
public function __construct(
22+
private readonly int $rowsCount,
23+
private readonly string $type
24+
)
25+
{
26+
27+
}
28+
29+
public static function minRows(int $minRows): self
30+
{
31+
return new self($minRows, self::MIN_ROWS);
32+
}
33+
34+
public static function maxRows(int $maxRows): self
35+
{
36+
return new self($maxRows, self::MAX_ROWS);
37+
}
38+
39+
public function isSatisfiedBy(string $tableName, int $rows): bool
40+
{
41+
return match ($this->type) {
42+
self::MIN_ROWS => $rows >= $this->rowsCount,
43+
self::MAX_ROWS => $rows <= $this->rowsCount,
44+
default => false,
45+
};
46+
}
47+
}

0 commit comments

Comments
 (0)