Completed
Push — master ( c2fd32...a3449e )
by P.R.
06:23
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 1
Bugs 0 Features 0
Metric Value
c 1
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 18
  public function __construct(&$config, &$configMetadata, $io)
74
  {
75 18
    $this->config         = &$config;
76 18
    $this->configMetadata = &$configMetadata;
77 18
    $this->io             = $io;
78 18
  }
79
80
  //--------------------------------------------------------------------------------------------------------------------
81
  /**
82
   * Getting list of all tables from information_schema of database from config file.
83
   */
84 18
  public function listOfTables()
85
  {
86 18
    $this->dataSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['data_schema']);
87
88 18
    $this->auditSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['audit_schema']);
89 18
  }
90
91
  //--------------------------------------------------------------------------------------------------------------------
92
  /**
93
   * The main method: executes the auditing actions for tables.
94
   *
95
   * @return int The exit status.
96
   */
97 18
  public function main()
98
  {
99 18
    if ($this->pruneOption)
100
    {
101
      $this->configMetadata = [];
102
    }
103
104 18
    $this->resolveCanonicalAuditColumns();
105
106 18
    $this->listOfTables();
107
108 18
    $this->unknownTables();
109
110 18
    $this->obsoleteTables();
111
112 18
    $status = $this->knownTables();
113
114 18
    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 18
  public function obsoleteTables()
122
  {
123 18
    foreach ($this->config['tables'] as $tableName => $dummy)
124
    {
125 17
      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 17
        unset($this->config['tables'][$tableName]);
129
      }
130
    }
131 18
  }
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 16
  public function setConfigTableColumns($tableName, $columns)
141
  {
142 16
    $newColumns = [];
143 16
    foreach ($columns->getColumns() as $column)
144
    {
145 16
      $newColumns[] = $column->getProperties();
146
    }
147 16
    $this->configMetadata[$tableName] = $newColumns;
148 16
  }
149
150
  //--------------------------------------------------------------------------------------------------------------------
151
  /**
152
   * Compares the tables listed in the config file and the tables found in the data schema.
153
   */
154 18
  public function unknownTables()
155
  {
156 18
    foreach ($this->dataSchemaTables as $table)
157
    {
158 17
      if (isset($this->config['tables'][$table['table_name']]))
159
      {
160 17
        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 17
          if ($this->config['tables'][$table['table_name']]['audit'])
167
          {
168 17
            if (!isset($this->config['tables'][$table['table_name']]['alias']))
169
            {
170 17
              $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 17
        $this->config['tables'][$table['table_name']] = ['audit' => null,
179
                                                         'alias' => null,
180
                                                         'skip'  => null];
181
      }
182
    }
183 18
  }
184
185
  //--------------------------------------------------------------------------------------------------------------------
186
  /**
187
   * Resolves the canonical column types of the audit table columns.
188
   */
189 18
  protected function resolveCanonicalAuditColumns()
190
  {
191 18
    if (empty($this->config['audit_columns']))
192
    {
193 8
      $this->auditColumnsMetadata = new TableColumnsMetadata();
194
    }
195
    else
196
    {
197 10
      $schema    = $this->config['database']['audit_schema'];
198 10
      $tableName = '_TMP_'.uniqid();
199 10
      AuditDataLayer::createTemporaryTable($schema, $tableName, $this->config['audit_columns']);
200 10
      $columns = AuditDataLayer::getTableColumns($schema, $tableName);
201 10
      AuditDataLayer::dropTemporaryTable($schema, $tableName);
202
203 10
      foreach ($this->config['audit_columns'] as $audit_column)
204
      {
205 10
        $key = AuditDataLayer::searchInRowSet('column_name', $audit_column['column_name'], $columns);
206 10
        if (isset($audit_column['value_type']))
207
        {
208 10
          $columns[$key]['value_type'] = $audit_column['value_type'];
209
        }
210 10
        if (isset($audit_column['expression']))
211
        {
212 10
          $columns[$key]['expression'] = $audit_column['expression'];
213
        }
214
      }
215
216 10
      $this->auditColumnsMetadata = new TableColumnsMetadata($columns, 'AuditColumnMetadata');
217
    }
218 18
  }
219
220
  //--------------------------------------------------------------------------------------------------------------------
221
  /**
222
   * Processed known tables.
223
   *
224
   * @return int The exit status.
225
   */
226 18
  private function knownTables()
227
  {
228 18
    $status = 0;
229
230 18
    foreach ($this->dataSchemaTables as $table)
231
    {
232 17
      if ($this->config['tables'][$table['table_name']]['audit'])
233
      {
234 17
        if (isset($this->configMetadata[$table['table_name']]))
235
        {
236 6
          $tableColumns = $this->configMetadata[$table['table_name']];
237
        }
238
        else
239
        {
240 12
          $tableColumns = [];
241
        }
242
243 17
        $configTable = new TableMetadata($table['table_name'],
244 17
                                         $this->config['database']['data_schema'],
245 17
                                         $tableColumns);
246
247 17
        $currentTable = new AuditTable($this->io,
248 17
                                       $configTable,
249 17
                                       $this->config['database']['audit_schema'],
250 17
                                       $this->auditColumnsMetadata,
251 17
                                       $this->config['tables'][$table['table_name']]['alias'],
252 17
                                       $this->config['tables'][$table['table_name']]['skip']);
253
254
        // Ensure the audit table exists.
255 17
        if (AuditDataLayer::searchInRowSet('table_name', $table['table_name'], $this->auditSchemaTables)===null)
256
        {
257 14
          $currentTable->createAuditTable();
258
        }
259
260
        // Drop and create audit triggers and add new columns to the audit table.
261 17
        $ok = $currentTable->main($this->config['additional_sql']);
262 17
        if ($ok)
263
        {
264 16
          $columns = new TableColumnsMetadata(AuditDataLayer::getTableColumns($this->config['database']['data_schema'],
265 16
                                                                              $table['table_name']));
266 16
          $this->setConfigTableColumns($table['table_name'], $columns);
267
        }
268
        else
269
        {
270 17
          $status += 1;
271
        }
272
      }
273
      else
274
      {
275
        $configTable = new TableMetadata($table['table_name'],
276
                                         $this->config['database']['data_schema'],
277
                                         []);
278
279
        $currentTable = new AuditTable($this->io,
280
                                       $configTable,
281
                                       $this->config['database']['audit_schema'],
282
                                       $this->auditColumnsMetadata,
283
                                       '',
284
                                       '');
285
286 17
        $currentTable->dropAuditTriggers($this->config['database']['data_schema'], $table['table_name']);
287
      }
288
    }
289
290 18
    return $status;
291
  }
292
293
  //--------------------------------------------------------------------------------------------------------------------
294
}
295
296
//----------------------------------------------------------------------------------------------------------------------
297