Completed
Pull Request — master (#40)
by Dima
03:24
created

AuditDiff   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 270
Duplicated Lines 11.11 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 24
c 2
b 1
f 0
lcom 1
cbo 9
dl 30
loc 270
ccs 0
cts 109
cp 0
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B main() 0 28 1
B diffTables() 0 15 6
A getDiff() 0 18 4
A listOfTables() 0 6 1
B printDiff() 0 47 6
B resolveCanonicalAuditColumns() 30 30 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\MySql;
4
5
use SetBased\Audit\MySql\Helper\DiffTableHelper;
6
use SetBased\Audit\MySql\Metadata\TableColumnsMetadata;
7
use SetBased\Stratum\MySql\StaticDataLayer;
8
use SetBased\Stratum\Style\StratumStyle;
9
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
//----------------------------------------------------------------------------------------------------------------------
15
/**
16
 * Class for executing auditing actions for tables.
17
 */
18
class AuditDiff
19
{
20
  //--------------------------------------------------------------------------------------------------------------------
21
  /**
22
   * The metadata (additional) audit columns (as stored in the config file).
23
   *
24
   * @var TableColumnsMetadata
25
   */
26
  private $auditColumnsMetadata;
27
28
  /**
29
   * The names of all tables in audit schema.
30
   *
31
   * @var array
32
   */
33
  private $auditSchemaTables;
34
35
  /**
36
   * The content of the configuration file.
37
   *
38
   * @var array
39
   */
40
  private $config;
41
42
  /**
43
   * The names of all tables in data schema.
44
   *
45
   * @var array
46
   */
47
  private $dataSchemaTables;
48
49
  /**
50
   * Array with columns for each table.
51
   * array [
52
   *    table_name [
53
   *            column [
54
   *                    data table type,
55
   *                    audit table type
56
   *                    ],
57
   *                      ...
58
   *               ]
59
   *       ]
60
   *
61
   * @var array[]
62
   */
63
  private $diffColumns;
64
65
  /**
66
   * If set all tables and columns are shown.
67
   *
68
   * @var boolean
69
   */
70
  private $full;
71
72
  /**
73
   * The Input interface.
74
   *
75
   * @var InputInterface
76
   */
77
  private $input;
78
79
  /**
80
   * The Output decorator.
81
   *
82
   * @var StratumStyle
83
   */
84
  private $io;
85
86
  /**
87
   * The Output interface.
88
   *
89
   * @var OutputInterface
90
   */
91
  private $output;
92
93
  //--------------------------------------------------------------------------------------------------------------------
94
  /**
95
   * Object constructor.
96
   *
97
   * @param array[]         $config The content of the configuration file.
98
   * @param StratumStyle    $io     The Output decorator.
99
   * @param InputInterface  $input
100
   * @param OutputInterface $output
101
   */
102
  public function __construct(&$config, $io, $input, $output)
103
  {
104
    $this->io     = $io;
105
    $this->config = &$config;
106
    $this->input  = $input;
107
    $this->output = $output;
108
  }
109
110
  //--------------------------------------------------------------------------------------------------------------------
111
  /**
112
   * The main method: executes the auditing actions for tables.
113
   *
114
   * @return int The exit status.
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
115
   */
116
  public function main()
117
  {
118
    // Style for column names with miss matched column types.
119
    $style = new OutputFormatterStyle(null, 'red');
120
    $this->output->getFormatter()->setStyle('mm_column', $style);
121
122
    // Style for column types of columns with miss matched column types.
123
    $style = new OutputFormatterStyle('yellow');
124
    $this->output->getFormatter()->setStyle('mm_type', $style);
125
126
    // Style for obsolete tables.
127
    $style = new OutputFormatterStyle('yellow');
128
    $this->output->getFormatter()->setStyle('obsolete_table', $style);
129
130
    // Style for missing tables.
131
    $style = new OutputFormatterStyle('red');
132
    $this->output->getFormatter()->setStyle('miss_table', $style);
133
134
    $this->full = $this->input->getOption('full');
135
136
    $this->resolveCanonicalAuditColumns();
137
138
    $this->listOfTables();
139
140
    $this->getDiff();
141
142
    $this->printDiff();
143
  }
144
145
  //--------------------------------------------------------------------------------------------------------------------
146
  /**
147
   * Writes the difference between the audit tables and metadata tables to the output.
148
   */
149
  private function diffTables()
150
  {
151
    foreach ($this->config['tables'] as $tableName => $table)
152
    {
153
      $res = StaticDataLayer::searchInRowSet('table_name', $tableName, $this->auditSchemaTables);
154
      if ($table['audit'] && !isset($res))
155
      {
156
        $this->output->writeln(sprintf('<miss_table>%s</>', $tableName));
157
      }
158
      else if (!$table['audit'] && isset($res))
159
      {
160
        $this->output->writeln(sprintf('<obsolete_table>%s</>', $tableName));
161
      }
162
    }
163
  }
164
165
  //--------------------------------------------------------------------------------------------------------------------
166
  /**
167
   * Computes the difference between data and audit tables.
168
   */
169
  private function getDiff()
170
  {
171
    foreach ($this->dataSchemaTables as $table)
172
    {
173
      if ($this->config['tables'][$table['table_name']]['audit'])
174
      {
175
176
        $res = StaticDataLayer::searchInRowSet('table_name', $table['table_name'], $this->auditSchemaTables);
177
        if (isset($res))
178
        {
179
          $this->diffColumns[$table['table_name']] = new AuditDiffTable($this->config['database']['data_schema'],
180
                                                                        $this->config['database']['audit_schema'],
181
                                                                        $table['table_name'],
182
                                                                        $this->config['audit_columns']);
183
        }
184
      }
185
    }
186
  }
187
188
  //--------------------------------------------------------------------------------------------------------------------
189
  /**
190
   * Getting list of all tables from information_schema of database from config file.
191
   */
192
  private function listOfTables()
193
  {
194
    $this->dataSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['data_schema']);
195
196
    $this->auditSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['audit_schema']);
197
  }
198
199
  //--------------------------------------------------------------------------------------------------------------------
200
  /**
201
   * Writes the difference between the audit and data tables to the output.
202
   */
203
  private function printDiff()
204
  {
205
    $first = true;
206
    if (isset($this->diffColumns))
207
    {
208
      /** @var AuditDiffTable $diffTable */
209
      foreach ($this->diffColumns as $tableName => $diffTable)
210
      {
211
        $columns = $diffTable->getDiffColumns();
0 ignored issues
show
Bug introduced by
The method getDiffColumns cannot be called on $diffTable (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
212
        // Remove matching columns unless the full option is used.
213
        if (!$this->full)
214
        {
215
          $columns = $diffTable->removeMatchingColumns();
0 ignored issues
show
Bug introduced by
The method removeMatchingColumns cannot be called on $diffTable (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
216
        }
217
218
        if (!empty($columns))
219
        {
220
          // Add an empty line between tables.
221
          if ($first)
222
          {
223
            $first = false;
224
          }
225
          else
226
          {
227
            $this->output->writeln('');
228
          }
229
230
          // Write table name.
231
          $this->output->writeln($tableName);
232
233
          // Write table with columns.
234
          $rows = new DiffTableHelper($this->config['database']['data_schema'],
235
                                      $this->config['database']['audit_schema'],
236
                                      $tableName,
237
                                      $this->config['audit_columns'],
238
                                      $this->full);
239
          $rows->appendRows($columns);
240
          $rows->addHighlighting();
241
          $table = new Table($this->output);
242
          $table->setHeaders(['column', 'data table', 'audit table', 'config'])
243
                ->setRows($rows->getRows());
244
          $table->render();
245
        }
246
      }
247
      $this->diffTables();
248
    }
249
  }
250
251
  //--------------------------------------------------------------------------------------------------------------------
252
  /**
253
   * Resolves the canonical column types of the audit table columns.
254
   */
255 View Code Duplication
  private function resolveCanonicalAuditColumns()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
256
  {
257
    if (empty($this->config['audit_columns']))
258
    {
259
      $this->auditColumnsMetadata = new TableColumnsMetadata();
260
    }
261
    else
262
    {
263
      $schema    = $this->config['database']['audit_schema'];
264
      $tableName = '_TMP_'.uniqid();
265
      AuditDataLayer::createTemporaryTable($schema, $tableName, $this->config['audit_columns']);
266
      $columns = AuditDataLayer::getTableColumns($schema, $tableName);
267
      AuditDataLayer::dropTemporaryTable($schema, $tableName);
268
269
      foreach ($this->config['audit_columns'] as $audit_column)
270
      {
271
        $key = StaticDataLayer::searchInRowSet('column_name', $audit_column['column_name'], $columns);
272
        if (isset($audit_column['value_type']))
273
        {
274
          $columns[$key]['value_type'] = $audit_column['value_type'];
275
        }
276
        if (isset($audit_column['expression']))
277
        {
278
          $columns[$key]['expression'] = $audit_column['expression'];
279
        }
280
      }
281
282
      $this->auditColumnsMetadata = new TableColumnsMetadata($columns, 'AuditColumnMetadata');
283
    }
284
  }
285
286
  //--------------------------------------------------------------------------------------------------------------------
287
}
288
289
//----------------------------------------------------------------------------------------------------------------------
290