Completed
Push — master ( 1f7a6d...d6c443 )
by P.R.
03:14
created

Diff::missingAuditTables()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Audit\Audit;
5
6
use SetBased\Audit\DiffTable;
7
use SetBased\Audit\Metadata\TableColumnsMetadata;
8
use SetBased\Audit\MySql\AuditDataLayer;
9
use SetBased\Audit\MySql\Metadata\TableMetadata;
10
use SetBased\Audit\Style\AuditStyle;
11
use SetBased\Config\TypedConfig;
12
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
16
/**
17
 * Class for executing auditing actions for tables.
18
 */
19
class Diff
20
{
21
  //--------------------------------------------------------------------------------------------------------------------
22
  /**
23
   * The metadata of the additional audit columns.
24
   *
25
   * @var TableColumnsMetadata
26
   */
27
  private $additionalAuditColumns;
28
29
  /**
30
   * The strong typed configuration reader and writer.
31
   *
32
   * @var TypedConfig
33
   */
34
  private $config;
35
36
  /**
37
   * The Input interface.
38
   *
39
   * @var InputInterface
40
   */
41
  private $input;
42
43
  /**
44
   * The Output decorator.
45
   *
46
   * @var AuditStyle
47
   */
48
  private $io;
49
50
  /**
51
   * The Output interface.
52
   *
53
   * @var OutputInterface
54
   */
55
  private $output;
56
57
  //--------------------------------------------------------------------------------------------------------------------
58
  /**
59
   * Object constructor.
60
   *
61
   * @param TypedConfig     $config The strong typed configuration reader and writer.
62
   * @param AuditStyle      $io     The Output decorator.
63
   * @param InputInterface  $input
64
   * @param OutputInterface $output
65
   */
66 6
  public function __construct(TypedConfig $config, AuditStyle $io, InputInterface $input, OutputInterface $output)
67
  {
68 6
    $this->io     = $io;
69 6
    $this->config = $config;
70 6
    $this->input  = $input;
71 6
    $this->output = $output;
72
73 6
    $this->additionalAuditColumns =
74 6
      AuditDataLayer::resolveCanonicalAdditionalAuditColumns($this->config->getManString('database.audit_schema'),
75 6
                                                             $this->config->getManArray('audit_columns'));
76 6
  }
77
78
  //--------------------------------------------------------------------------------------------------------------------
79
  /**
80
   * The main method: executes the auditing actions for tables.
81
   */
82 6
  public function main(): void
83
  {
84
    // Style for column names with miss matched column types.
85 6
    $style = new OutputFormatterStyle(null, 'red');
86 6
    $this->output->getFormatter()->setStyle('mm_column', $style);
87
88
    // Style for column types of columns with miss matched column types.
89 6
    $style = new OutputFormatterStyle('yellow');
90 6
    $this->output->getFormatter()->setStyle('mm_type', $style);
91
92
    // Style for obsolete tables.
93 6
    $style = new OutputFormatterStyle('yellow');
94 6
    $this->output->getFormatter()->setStyle('obsolete_table', $style);
95
96
    // Style for missing tables.
97 6
    $style = new OutputFormatterStyle('red');
98 6
    $this->output->getFormatter()->setStyle('miss_table', $style);
99
100 6
    $lists = $this->getTableLists();
101
102 6
    $this->currentAuditTables($lists['current']);
103
104 6
    $this->missingAuditTables($lists['missing']);
105
106 6
    $this->obsoleteAuditTables($lists['obsolete']);
107 6
  }
108
109
  //--------------------------------------------------------------------------------------------------------------------
110
  /**
111
   * Prints the difference between a data and and its audit table.
112
   *
113
   * @param string $tableName The table name.
114
   */
115 6
  private function currentAuditTable(string $tableName): void
116
  {
117 6
    $columns           = AuditDataLayer::getTableColumns($this->config->getManString('database.data_schema'), $tableName);
118 6
    $dataTableColumns  = new TableColumnsMetadata($columns);
119 6
    $columns           = AuditDataLayer::getTableColumns($this->config->getManString('database.audit_schema'), $tableName);
120 6
    $auditTableColumns = new TableColumnsMetadata($columns, 'AuditColumnMetadata');
121
122
    // In the audit table columns coming from the data table are always nullable.
123 6
    $dataTableColumns->makeNullable();
124 6
    $dataTableColumns->unsetDefaults();
125 6
    $dataTableColumns = TableColumnsMetadata::combine($this->additionalAuditColumns, $dataTableColumns);
126
127
    // In the audit table columns coming from the data table don't have defaults.
128 6
    foreach ($auditTableColumns->getColumns() as $column)
129
    {
130 6
      if (!in_array($column->getName(), $this->additionalAuditColumns->getColumnNames()))
131
      {
132 6
        $column->unsetDefault();
133
      }
134
    }
135
136 6
    $dataTableOptions  = AuditDataLayer::getTableOptions($this->config->getManString('database.data_schema'), $tableName);
137 6
    $auditTableOptions = AuditDataLayer::getTableOptions($this->config->getManString('database.audit_schema'), $tableName);
138
139 6
    $dataTable  = new TableMetadata($dataTableOptions, $dataTableColumns);
140 6
    $auditTable = new TableMetadata($auditTableOptions, $auditTableColumns);
141
142 6
    $helper = new DiffTable($dataTable, $auditTable);
143 6
    $helper->print($this->io, $this->input->getOption('full'));
144 6
  }
145
146
  //--------------------------------------------------------------------------------------------------------------------
147
  /**
148
   * Prints the difference between data and audit tables.
149
   *
150
   * @param string[] $tableNames The names of the current tables.
151
   */
152 6
  private function currentAuditTables(array $tableNames): void
153
  {
154 6
    foreach ($tableNames as $tableName)
155
    {
156 6
      $this->currentAuditTable($tableName);
157
    }
158 6
  }
159
160
  //--------------------------------------------------------------------------------------------------------------------
161
  /**
162
   * Returns the names of the tables that must be compared.
163
   *
164
   * @return array[]
165
   */
166 6
  private function getTableLists(): array
167
  {
168 6
    $tables1 = [];
169 6
    foreach ($this->config->getManArray('tables') as $tableName => $config)
170
    {
171 6
      if ($config['audit'])
172
      {
173 6
        $tables1[] = $tableName;
174
      }
175
    }
176
177 6
    $tables  = AuditDataLayer::getTablesNames($this->config->getManString('database.data_schema'));
178 6
    $tables2 = [];
179 6
    foreach ($tables as $table)
180
    {
181 6
      $tables2[] = $table['table_name'];
182
    }
183
184 6
    $tables  = AuditDataLayer::getTablesNames($this->config->getManString('database.audit_schema'));
185 6
    $tables3 = [];
186 6
    foreach ($tables as $table)
187
    {
188 6
      $tables3[] = $table['table_name'];
189
    }
190
191 6
    return ['current'  => array_intersect($tables1, $tables2, $tables3),
192 6
            'obsolete' => array_diff($tables3, $tables1),
193 6
            'missing'  => array_diff($tables1, $tables3)];
194
  }
195
196
  //--------------------------------------------------------------------------------------------------------------------
197
  /**
198
   * Prints the missing audit tables.
199
   *
200
   * @param string[] $tableNames The names of the obsolete tables.
201
   */
202 6
  private function missingAuditTables(array $tableNames): void
203
  {
204 6
    if (empty($tableNames)) return;
205
206 1
    $this->io->title('Missing Audit Tables');
207 1
    $this->io->listing($tableNames);
208 1
  }
209
210
  //--------------------------------------------------------------------------------------------------------------------
211
  /**
212
   * Prints the obsolete audit tables.
213
   *
214
   * @param string[] $tableNames The names of the obsolete tables.
215
   */
216 6
  private function obsoleteAuditTables(array $tableNames): void
217
  {
218 6
    if (empty($tableNames) || !$this->input->getOption('full')) return;
219
220 1
    $this->io->title('Obsolete Audit Tables');
221 1
    $this->io->listing($tableNames);
222 1
  }
223
224
  //--------------------------------------------------------------------------------------------------------------------
225
}
226
227
//----------------------------------------------------------------------------------------------------------------------
228