Completed
Branch master (0ecb66)
by P.R.
04:50
created

Audit::unknownTables()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6.2163

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 30
ccs 9
cts 11
cp 0.8182
rs 8.439
cc 6
eloc 14
nc 6
nop 0
crap 6.2163
1
<?php
2
3
namespace SetBased\Audit\MySql;
4
5
use SetBased\Audit\MySql\Metadata\TableColumnsMetadata;
6
use SetBased\Audit\MySql\Metadata\TableMetadata;
7
use SetBased\Stratum\Style\StratumStyle;
8
9
/**
10
 * Class for executing auditing actions for tables.
11
 */
12
class Audit
13
{
14
  //--------------------------------------------------------------------------------------------------------------------
15
  /**
16
   * The metadata (additional) audit columns (as stored in the config file).
17
   *
18
   * @var TableColumnsMetadata
19
   */
20
  private $auditColumnsMetadata;
21
22
  /**
23
   * The names of all tables in audit schema.
24
   *
25
   * @var array
26
   */
27
  private $auditSchemaTables;
28
29
  /**
30
   * The content of the configuration file.
31
   *
32
   * @var array
33
   */
34
  private $config;
35
36
  /**
37
   * Tables metadata from config file.
38
   *
39
   * @var array
40
   */
41
  private $configMetadata;
42
43
  /**
44
   * The names of all tables in data schema.
45
   *
46
   * @var array
47
   */
48
  private $dataSchemaTables;
49
50
  /**
51
   * The Output decorator.
52
   *
53
   * @var StratumStyle
54
   */
55
  private $io;
56
57
  /**
58
   * If true remove all column information from config file.
59
   *
60
   * @var boolean
61
   */
62
  private $pruneOption;
63
64
  //--------------------------------------------------------------------------------------------------------------------
65
66
  /**
67
   * Object constructor.
68
   *
69
   * @param array[]      $config         The content of the configuration file.
70
   * @param array[]      $configMetadata The content of the metadata file.
71
   * @param StratumStyle $io             The Output decorator.
72
   */
73 26
  public function __construct(&$config, &$configMetadata, $io)
74
  {
75 26
    $this->config         = &$config;
76 26
    $this->configMetadata = &$configMetadata;
77 26
    $this->io             = $io;
78 26
  }
79
80
  //--------------------------------------------------------------------------------------------------------------------
81
  /**
82
   * Getting list of all tables from information_schema of database from config file.
83
   */
84 26
  public function listOfTables()
85
  {
86 26
    $this->dataSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['data_schema']);
87
88 26
    $this->auditSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['audit_schema']);
89 26
  }
90
91
  //--------------------------------------------------------------------------------------------------------------------
92
  /**
93
   * The main method: executes the auditing actions for tables.
94
   *
95
   * @return int The exit status.
96
   */
97 26
  public function main()
98
  {
99 26
    if ($this->pruneOption)
100
    {
101
      $this->configMetadata = [];
102
    }
103
104 26
    $this->resolveCanonicalAuditColumns();
105
106 26
    $this->listOfTables();
107
108 26
    $this->unknownTables();
109
110 26
    $this->obsoleteTables();
111
112 26
    $status = $this->knownTables();
113
114 26
    return $status;
115
  }
116
117
  //--------------------------------------------------------------------------------------------------------------------
118
  /**
119
   * Removes tables listed in the config file that are not longer in the data schema from the config file.
120
   */
121 26
  public function obsoleteTables()
122
  {
123 26
    foreach ($this->config['tables'] as $tableName => $dummy)
124
    {
125 25
      if (AuditDataLayer::searchInRowSet('table_name', $tableName, $this->dataSchemaTables)===null)
126
      {
127 8
        $this->io->writeln(sprintf('<info>Removing obsolete table %s from config file</info>', $tableName));
128 25
        unset($this->config['tables'][$tableName]);
129
      }
130
    }
131 26
  }
132
133
  //--------------------------------------------------------------------------------------------------------------------
134
  /**
135
   * Sets the columns metadata of a table in the configuration file.
136
   *
137
   * @param string               $tableName The name of table.
138
   * @param TableColumnsMetadata $columns   The metadata of the table columns.
139
   */
140 22
  public function setConfigTableColumns($tableName, $columns)
141
  {
142 22
    $newColumns = [];
143 22
    foreach ($columns->getColumns() as $column)
144
    {
145 22
      $newColumns[] = $column->getProperties();
146
    }
147 22
    $this->configMetadata[$tableName] = $newColumns;
148 22
  }
149
150
  //--------------------------------------------------------------------------------------------------------------------
151
  /**
152
   * Compares the tables listed in the config file and the tables found in the data schema.
153
   */
154 26
  public function unknownTables()
155
  {
156 26
    foreach ($this->dataSchemaTables as $table)
157
    {
158 25
      if (isset($this->config['tables'][$table['table_name']]))
159
      {
160 25
        if (!isset($this->config['tables'][$table['table_name']]['audit']))
161
        {
162
          $this->io->writeln(sprintf('<info>Audit not set for table %s</info>', $table['table_name']));
163
        }
164
        else
165
        {
166 25
          if ($this->config['tables'][$table['table_name']]['audit'])
167
          {
168 25
            if (!isset($this->config['tables'][$table['table_name']]['alias']))
169
            {
170 25
              $this->config['tables'][$table['table_name']]['alias'] = AuditTable::getRandomAlias();
171
            }
172
          }
173
        }
174
      }
175
      else
176
      {
177
        $this->io->writeln(sprintf('<info>Found new table %s</info>', $table['table_name']));
178 25
        $this->config['tables'][$table['table_name']] = ['audit' => null,
179
                                                         'alias' => null,
180
                                                         'skip'  => null];
181
      }
182
    }
183 26
  }
184
185
  //--------------------------------------------------------------------------------------------------------------------
186
  /**
187
   * Resolves the canonical column types of the audit table columns.
188
   */
189 26
  protected function resolveCanonicalAuditColumns()
190
  {
191 26
    if (empty($this->config['audit_columns']))
192
    {
193 8
      $this->auditColumnsMetadata = new TableColumnsMetadata();
194
    }
195
    else
196
    {
197 18
      $schema    = $this->config['database']['audit_schema'];
198 18
      $tableName = '_TMP_'.uniqid();
199 18
      AuditDataLayer::createTemporaryTable($schema, $tableName, $this->config['audit_columns']);
200 18
      $columns = AuditDataLayer::getTableColumns($schema, $tableName);
201 18
      AuditDataLayer::dropTemporaryTable($schema, $tableName);
202
203 18
      foreach ($this->config['audit_columns'] as $audit_column)
204
      {
205 18
        $key = AuditDataLayer::searchInRowSet('column_name', $audit_column['column_name'], $columns);
206 18
        if (isset($audit_column['value_type']))
207
        {
208 18
          $columns[$key]['value_type'] = $audit_column['value_type'];
209
        }
210 18
        if (isset($audit_column['expression']))
211
        {
212 18
          $columns[$key]['expression'] = $audit_column['expression'];
213
        }
214
      }
215
216 18
      $this->auditColumnsMetadata = new TableColumnsMetadata($columns, 'AuditColumnMetadata');
217
    }
218 26
  }
219
220
  //--------------------------------------------------------------------------------------------------------------------
221
  /**
222
   * Processed known tables.
223
   *
224
   * @return int The exit status.
225
   */
226 26
  private function knownTables()
227
  {
228 26
    $status = 0;
229
230 26
    foreach ($this->dataSchemaTables as $table)
231
    {
232 25
      if ($this->config['tables'][$table['table_name']]['audit'])
233
      {
234 25
        if (isset($this->configMetadata[$table['table_name']]))
235
        {
236 14
          $tableColumns = $this->configMetadata[$table['table_name']];
237
        }
238
        else
239
        {
240 12
          $tableColumns = [];
241
        }
242
243 25
        $metadata    = AuditDataLayer::getTableOptions($this->config['database']['data_schema'], $table['table_name']);
244 25
        $configTable = new TableMetadata($metadata, $tableColumns);
245
246 25
        $currentTable = new AuditTable($this->io,
247 25
                                       $configTable,
248 25
                                       $this->config['database']['audit_schema'],
249 25
                                       $this->auditColumnsMetadata,
250 25
                                       $this->config['tables'][$table['table_name']]['alias'],
251 25
                                       $this->config['tables'][$table['table_name']]['skip']);
252
253
        // Ensure the audit table exists.
254 25
        if (AuditDataLayer::searchInRowSet('table_name', $table['table_name'], $this->auditSchemaTables)===null)
255
        {
256 22
          $currentTable->createAuditTable();
257
        }
258
259
        // Drop and create audit triggers and add new columns to the audit table.
260 25
        $ok = $currentTable->main($this->config['additional_sql']);
261 25
        if ($ok)
262
        {
263 22
          $columns = new TableColumnsMetadata(AuditDataLayer::getTableColumns($this->config['database']['data_schema'],
264 22
                                                                              $table['table_name']));
265 22
          $this->setConfigTableColumns($table['table_name'], $columns);
266
        }
267
        else
268
        {
269 25
          $status += 1;
270
        }
271
      }
272
      else
273
      {
274
        $metadata    = AuditDataLayer::getTableOptions($this->config['database']['data_schema'], $table['table_name']);
275
        $configTable = new TableMetadata($metadata, []);
276
277
        $currentTable = new AuditTable($this->io,
278
                                       $configTable,
279
                                       $this->config['database']['audit_schema'],
280
                                       $this->auditColumnsMetadata,
281
                                       '',
282
                                       '');
283
284 25
        $currentTable->dropAuditTriggers($this->config['database']['data_schema'], $table['table_name']);
285
      }
286
    }
287
288 26
    return $status;
289
  }
290
291
  //--------------------------------------------------------------------------------------------------------------------
292
}
293
294
//----------------------------------------------------------------------------------------------------------------------
295