Skip to content
Open
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
155 changes: 149 additions & 6 deletions src/Anonymization/Anonymizer/AnonymizerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

use Composer\InstalledVersions;
use MakinaCorpus\DbToolsBundle\Anonymization\Config\AnonymizerConfig;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackEnumAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackEnumGeneratedAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackFileEnumAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackFileMultipleColumnAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackMultipleColumnAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackMultipleColumnGeneratedAnonymizer;
use MakinaCorpus\DbToolsBundle\Anonymization\Pack\PackRegistry;
use MakinaCorpus\DbToolsBundle\Attribute\AsAnonymizer;
use MakinaCorpus\QueryBuilder\DatabaseSession;

Expand All @@ -32,15 +40,33 @@
Core\StringPatternAnonymizer::class,
];

private PackRegistry $packRegistry;

/** @var array<string, string> */
private ?array $classes = null;

/** @var array<string, AsAnonymizer> */
private ?array $metadata = null;

/**
* Paths where to lookup for custom anonymizers.
*
* @var array<string>
*/
private array $paths = [];

public function __construct(?array $paths = null)
/**
* Pack filenames where to lookup for PHP-less packs.
*
* @var array<string>
*/
private array $packs = [];

public function __construct(?array $paths = null, ?array $packs = null)
{
$this->addPath($paths ?? []);
$this->addPack($packs ?? []);
$this->packRegistry = new PackRegistry();
}

/**
Expand All @@ -51,6 +77,14 @@
$this->paths = \array_unique(\array_merge($this->paths, $paths));
}

/**
* Add PHP-less configuration file pack.
*/
public function addPack(array $packs): void
{
$this->packs = \array_unique(\array_merge($this->packs, $packs));
}

/**
* Get all registered anonymizers classe names.
*
Expand All @@ -72,10 +106,19 @@
Context $context,
DatabaseSession $databaseSession,
): AbstractAnonymizer {
$className = $this->getAnonymizerClass($name);

$ret = new $className($config->table, $config->targetName, $databaseSession, $context, $config->options);
\assert($ret instanceof AbstractAnonymizer);
if ($this->packRegistry->hasPack($name)) {
$ret = $this->createAnonymizerFromPack(
$this->packRegistry->getPackAnonymizer($name),
$config,
$context,
$databaseSession,
);
} else {
$className = $this->getAnonymizerClass($name);

$ret = new $className($config->table, $config->targetName, $databaseSession, $context, $config->options);
\assert($ret instanceof AbstractAnonymizer);
}

if ($ret instanceof WithAnonymizerRegistry) {
$ret->setAnonymizerRegistry($this);
Expand All @@ -84,6 +127,98 @@
return $ret;
}

/**
* Create anonymizer instance from pack.
*/
private function createAnonymizerFromPack(
PackAnonymizer $packAnonymizer,
AnonymizerConfig $config,
Context $context,
DatabaseSession $databaseSession
): AbstractAnonymizer {
// Merge incomming user options with options from the pack.
// Pack given options will override the user one.
$options = $config->options->with($packAnonymizer->options->all());

// Anonymizer from pack factory. Hardcoded for now.
if ($packAnonymizer instanceof PackEnumAnonymizer) {
return new Core\StringAnonymizer(
$config->table,
$config->targetName,
$databaseSession,
$context,
// @todo Convert data to an array if an iterable was
// here. Later, change getSample() signature of
// AbstractEnumAnonymizer to accept any iterable.
$options->with([
'sample' => \is_array($packAnonymizer->data) ? $packAnonymizer->data : \iterator_to_array($packAnonymizer->data),
]),
);
}

if ($packAnonymizer instanceof PackMultipleColumnAnonymizer) {
return new Core\MultipleColumnAnonymizer(

Check failure on line 160 in src/Anonymization/Anonymizer/AnonymizerRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis (8.2)

Method MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AnonymizerRegistry::createAnonymizerFromPack() should return MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\AbstractAnonymizer but returns MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Core\MultipleColumnAnonymizer.

Check failure on line 160 in src/Anonymization/Anonymizer/AnonymizerRegistry.php

View workflow job for this annotation

GitHub Actions / Static Analysis (8.2)

Instantiated class MakinaCorpus\DbToolsBundle\Anonymization\Anonymizer\Core\MultipleColumnAnonymizer not found.
$config->table,
$config->targetName,
$databaseSession,
// @todo Convert data to an array if an iterable was
// here. Later, change getSample() signature of
// AbstractEnumAnonymizer to accept any iterable.
$options->with([
'columns' => $packAnonymizer->columns,
'sample' => \is_array($packAnonymizer->data) ? $packAnonymizer->data : \iterator_to_array($packAnonymizer->data),
]),
);
}

if ($packAnonymizer instanceof PackEnumGeneratedAnonymizer) {
if (1 !== \count($packAnonymizer->pattern)) {
// @todo
throw new \LogicException("Not implemented yet: pattern anonymizer does not support multiple patterns yet.");
}

return new Core\StringPatternAnonymizer(
$config->table,
$config->targetName,
$databaseSession,
$context,
$options->with([
'pattern' => $packAnonymizer->pattern[0],
]),
);
}

if ($packAnonymizer instanceof PackMultipleColumnGeneratedAnonymizer) {
// @todo
throw new \LogicException("Not implemented yet: missing arbitrary column generator anonymizer.");
}

if ($packAnonymizer instanceof PackFileEnumAnonymizer) {
return new Core\FileEnumAnonymizer(
$config->table,
$config->targetName,
$databaseSession,
$context,
$options->with(['source' => $packAnonymizer->filename]),
);
}

if ($packAnonymizer instanceof PackFileMultipleColumnAnonymizer) {
return new Core\FileMultipleColumnAnonymizer(
$config->table,
$config->targetName,
$databaseSession,
$context,
$options->with([
'columns' => $packAnonymizer->columns,
'source' => $packAnonymizer->filename,
]),
);
}

throw new \LogicException(\sprintf("Pack anonymizer with class '%s' is not implement yet.", \get_class($packAnonymizer)));
}

/**
* Get anonymizer metadata.
*/
Expand Down Expand Up @@ -173,6 +308,12 @@
}
}
}

if ($this->packs) {
foreach ($this->packs as $filename) {
$this->packRegistry->addPack($filename);
}
}
}

/**
Expand Down Expand Up @@ -214,8 +355,10 @@
$path = $directory . '/src/Anonymizer/';
if (\is_dir($path)) {
$this->addPath([$path]);
} elseif (\file_exists($path . '/db_tools.pack.yaml')) {
$this->addPack([$path . '/db_tools.pack.yaml']);
} else {
\trigger_error(\sprintf("Anonymizers pack '%s' in '%s' as no 'src/Anonymizer/' directory and is thus not usable.", $package, $directory), \E_USER_ERROR);
\trigger_error(\sprintf("Anonymizers pack '%s' in '%s' as no 'src/Anonymizer/' directory nor 'db_tools.pack.yaml' file and is thus not usable.", $package, $directory), \E_USER_ERROR);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
character (default is ',').
- 'file_skip_header': when reading any file, set this to true to skip
the first line (default is false).
All other options are key-value pairs, keys are column names as defined in the
'columns' option, values are targetted database column names to anonymize.
TXT
)]
class FileMultipleColumnAnonymizer extends AbstractMultipleColumnAnonymizer
Expand Down
6 changes: 2 additions & 4 deletions src/Anonymization/Anonymizer/Core/StringPatternAnonymizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,10 @@ public function createAnonymizeExpression(Update $update): Expression
// so we need to create as many instances as we have ranges.
$childAnonymizer = $this->getAnonymizer(
'integer',
new Options(
[
new Options([
'min' => $part->start,
'max' => $part->stop,
],
)
]),
);
\assert($childAnonymizer instanceof AbstractSingleColumnAnonymizer);

Expand Down
Loading
Loading