Issues (9)

src/Command/AnonymizeCommand.php (2 issues)

1
<?php
2
3
namespace WebnetFr\DatabaseAnonymizerBundle\Command;
4
5
use Doctrine\Common\Annotations\Reader;
6
use Doctrine\DBAL\DBALException;
7
use Doctrine\ORM\Mapping\ClassMetadata;
8
use Symfony\Bridge\Doctrine\RegistryInterface;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Console\Question\ConfirmationQuestion;
14
use WebnetFr\DatabaseAnonymizer\Anonymizer;
15
use WebnetFr\DatabaseAnonymizer\Command\AnonymizeCommandTrait;
16
use WebnetFr\DatabaseAnonymizer\Config\TargetFactory;
17
use WebnetFr\DatabaseAnonymizer\GeneratorFactory\GeneratorFactoryInterface;
18
use WebnetFr\DatabaseAnonymizerBundle\Config\AnnotationConfigFactory;
19
20
/**
21
 * @author Vlad Riabchenko <[email protected]>
22
 */
23
class AnonymizeCommand extends Command
24
{
25
    use AnonymizeCommandTrait;
26
27
    protected static $defaultName = 'webnet-fr:anonymizer:anonymize';
28
29
    /**
30
     * @var GeneratorFactoryInterface
31
     */
32
    private $generatorFactory;
33
34
    /**
35
     * Default anonymizer configuration usually defined in webnet_fr_database_anonymizer.yaml.
36
     *
37
     * @var array
38
     */
39
    private $defaultConfig;
40
41
    /**
42
     * @var RegistryInterface
43
     */
44
    private $registry;
45
46
    /**
47
     * @var AnnotationConfigFactory
48
     */
49
    private $annotationConfigFactory;
50
51
    /**
52
     * @param GeneratorFactoryInterface $generatorFactory
53
     */
54
    public function __construct(GeneratorFactoryInterface $generatorFactory)
55
    {
56
        parent::__construct();
57
58
        $this->generatorFactory = $generatorFactory;
59
    }
60
61
    /**
62
     * Set Doctrine registry.
63
     *
64
     * @param RegistryInterface $registry
65
     */
66
    public function setRegistry(RegistryInterface $registry)
67
    {
68
        $this->registry = $registry;
69
    }
70
71
    /**
72
     * Enable annotations.
73
     *
74
     * @param AnnotationConfigFactory $annotationConfigFactory
75
     */
76
    public function enableAnnotations(AnnotationConfigFactory $annotationConfigFactory)
77
    {
78
        $this->annotationConfigFactory = $annotationConfigFactory;
79
    }
80
81
    /**
82
     * Set default anonymizer configuration.
83
     *
84
     * @param array $defaultConfig
85
     *
86
     * @return $this
87
     */
88
    public function setDefaultConfig(array $defaultConfig)
89
    {
90
        $this->defaultConfig = $defaultConfig;
91
92
        return $this;
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    protected function configure()
99
    {
100
        parent::configure();
101
102
        $this
103
            ->setName('webnet-fr:anonymizer:anonymize')
104
            ->setDescription('Anoymize database.')
105
            ->setHelp('Anoymize database according to GDPR (General Data Protection Regulation).')
106
            ->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Configuration file.')
107
            ->addOption('url', 'U', InputOption::VALUE_REQUIRED, 'Database connection string.')
108
            ->addOption('type', 't', InputOption::VALUE_REQUIRED, 'Database type.')
109
            ->addOption('host', 'H', InputOption::VALUE_REQUIRED, 'Database host.')
110
            ->addOption('port', 'P', InputOption::VALUE_REQUIRED, 'Database port.')
111
            ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'Database name.')
112
            ->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'User.')
113
            ->addOption('password', 'p', InputOption::VALUE_REQUIRED, 'Password.')
114
            ->addOption('connection', 'C', InputOption::VALUE_REQUIRED, 'Name of the connection to database.')
115
            ->addOption('annotations', 'a', InputOption::VALUE_NONE, 'Use annotations. "em" option must be provided.')
116
            ->addOption('em', null, InputOption::VALUE_REQUIRED, 'Entity manager.')
117
        ;
118
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123
    protected function execute(InputInterface $input, OutputInterface $output)
124
    {
125
        $questionHelper = $this->getHelper('question');
126
        $question = new ConfirmationQuestion('Are you sure you want to anonymize your database?', true);
127
128
        if (!$questionHelper->ask($input, $output, $question)) {
129
            return;
130
        }
131
132
        $em = null;
133
        $connection = null;
0 ignored issues
show
The assignment to $connection is dead and can be removed.
Loading history...
134
        $configName = null;
135
136
137
        try {
138
            $connection = $this->getConnectionFromInput($input);
139
        } catch (DBALException $e) {
140
            $connection = null;
141
        }
142
143
        // Retrieve database connection.
144
        if ($connection) {
145
            $configName = 'default';
146
        } elseif ($emName = $input->getOption('em')) {
147
            $em = $this->registry->getEntityManager($emName);
148
            $connection = $em->getConnection();
149
            $configName = (string) $emName;
150
        } else {
151
            if (!$this->registry) {
152
                throw new \LogicException('You must activete doctrine dbal component');
153
            }
154
155
            $configName = $input->getOption('connection');
156
            if (!$configName) {
157
                $configName = $this->registry->getDefaultConnectionName();
158
            }
159
160
            $connection = $this->registry->getConnection($configName);
161
        }
162
163
        if (!$connection) {
164
            throw new \LogicException('Cannot find or crete connection');
165
        }
166
167
        // Retrieve anonymizer configuration.
168
        if ($input->getOption('annotations')) {
169
            if (!$em) {
170
                $output->writeln('<error>You must pass entity manager name in "--em" option. Pass "--em=default" if there is only one entity manager.</error>');
171
172
                return;
173
            }
174
175
            if (!$this->annotationConfigFactory) {
176
                $output->writeln('<error>You must enable Doctrine annotations: "annotations.reader" service is required.</error>');
177
178
                return;
179
            }
180
181
            $config = $this->annotationConfigFactory->getConfig($em->getMetadataFactory()->getAllMetadata());
182
        } elseif ($configFile = $input->getOption('config')) {
183
            $configFilePath = realpath($input->getOption('config'));
184
            if (!is_file($configFilePath)) {
185
                $output->writeln(sprintf('<error>Configuration file "%s" does not exist.</error>', $configFile));
186
187
                return;
188
            }
189
190
            $config = $this->getConfigFromFile($configFilePath);
191
        } elseif (!empty($this->defaultConfig)) {
192
            if (!array_key_exists($configName, $this->defaultConfig['connections'])) {
193
                throw new \LogicException('You must configure anonymizer for "'.$configName.'" connection');
0 ignored issues
show
Are you sure $configName of type string|string[]|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

193
                throw new \LogicException('You must configure anonymizer for "'./** @scrutinizer ignore-type */ $configName.'" connection');
Loading history...
194
            };
195
196
            $config = $this->defaultConfig['connections'][$configName];
197
        } else {
198
            throw new \InvalidArgumentException('You must either provide the path of configuration file or confiqure the bundle or define annotations.');
199
        }
200
201
        $targetFactory = new TargetFactory($this->generatorFactory);
202
        $targetFactory->setConnection($connection);
203
        $targetTables = $targetFactory->createTargets($config);
204
205
        $anonymizer = new Anonymizer();
206
        $anonymizer->anonymize($connection, $targetTables);
207
    }
208
}
209