Completed
Pull Request — master (#59)
by Dima
03:22
created

AuditAlter   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 234
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 65.69%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 27
c 1
b 0
f 0
lcom 1
cbo 5
dl 0
loc 234
ccs 67
cts 102
cp 0.6569
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
F createSqlStatement() 0 49 12
A main() 0 6 1
A getDiff() 0 18 4
A listOfTables() 0 6 1
A processData() 0 17 2
B resolveCanonicalAuditColumns() 0 35 6
1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\MySql;
4
5
use SetBased\Audit\MySql\Helper\MySqlAlterTableCodeStore;
6
use SetBased\Audit\MySql\Metadata\ColumnMetadata;
7
use SetBased\Audit\MySql\Metadata\MultiSourceColumnMetadata;
8
use SetBased\Audit\MySql\Metadata\TableColumnsMetadata;
9
10
//----------------------------------------------------------------------------------------------------------------------
11
/**
12
 * Class for executing auditing actions for tables.
13
 */
14
class AuditAlter
15
{
16
  //--------------------------------------------------------------------------------------------------------------------
17
  /**
18
   * The metadata (additional) audit columns (as stored in the config file).
19
   *
20
   * @var \array[]
21
   */
22
  private $auditColumnsMetadata;
23
24
  /**
25
   * The names of all tables in audit schema.
26
   *
27
   * @var array
28
   */
29
  private $auditSchemaTables;
30
31
  /**
32
   * Code store for alter table statement.
33
   *
34
   * @var MySqlAlterTableCodeStore
35
   */
36
  private $codeStore;
37
38
  /**
39
   * The content of the configuration file.
40
   *
41
   * @var array
42
   */
43
  private $config;
44
45
  /**
46
   * Config metadata columns.
47
   *
48
   * @var array
49
   */
50
  private $configMetadata;
51
52
  /**
53
   * The names of all tables in data schema.
54
   *
55
   * @var array
56
   */
57
  private $dataSchemaTables;
58
59
  /**
60
   * Array with columns for each table.
61
   *
62
   * @var array<string,AuditDiffTable>
63
   */
64
  private $diffColumns;
65
66
  //--------------------------------------------------------------------------------------------------------------------
67
  /**
68
   * Object constructor.
69
   *
70
   * @param array[] $config         The content of the configuration file.
71
   * @param array[] $configMetadata The content of the metadata file.
72
   */
73 1
  public function __construct(&$config, $configMetadata)
74
  {
75 1
    $this->config         = &$config;
76 1
    $this->configMetadata = $configMetadata;
77 1
    $this->codeStore      = new MySqlAlterTableCodeStore();
78 1
  }
79
80
  //--------------------------------------------------------------------------------------------------------------------
81
  /**
82
   * Create Sql statement for alter table.
83
   *
84
   * @param string               $tableName The table name.
85
   * @param TableColumnsMetadata $columns   Columns metadata for alter statement.
86
   */
87 1
  public function createSqlStatement($tableName, $columns)
88
  {
89 1
    $editCharSet = false;
90 1
    $charSet     = '';
91 1
    $this->codeStore->append(sprintf('ALTER TABLE %s.`%s` CHANGE', $this->config['database']['audit_schema'], $tableName));
92 1
    $countMax = $columns->getNumberOfColumns();
93 1
    $count    = 1;
94
    /** @var MultiSourceColumnMetadata $rowMetadata */
95 1
    foreach ($columns->getColumns() as $columnName => $rowMetadata)
96
    {
97 1
      $columnProperties = $rowMetadata->getProperties();
98
      /** @var ColumnMetadata $data */
99 1
      $data = isset($columnProperties['data']) ? $columnProperties['data'] : null;
100
      /** @var ColumnMetadata $config */
101 1
      $config = isset($columnProperties['config']) ? $columnProperties['config'] : null;
102
103 1
      $dataMetadata   = isset($data) ? $data->getProperties() : null;
104 1
      $configMetadata = isset($config) ? $config->getProperties() : null;
105
106 1
      if (!isset($dataMetadata))
107 1
      {
108
        if (isset($configMetadata['character_set_name']))
109
        {
110
          $editCharSet = true;
111
          $charSet     = $configMetadata['character_set_name'];
112
        }
113
        $line = sprintf('`%s` `%s` %s', $columnName, $columnName, $configMetadata['column_type']);
114
        if ($count!=$countMax) $line .= ',';
115
        $this->codeStore->append($line);
116
      }
117
      else
118
      {
119 1
        if (isset($dataMetadata['character_set_name']))
120 1
        {
121
          $editCharSet = true;
122
          $charSet     = $dataMetadata['character_set_name'];
123
        }
124 1
        $line = sprintf('`%s` `%s` %s', $columnName, $columnName, $dataMetadata['column_type']);
125 1
        if ($count!=$countMax) $line .= ',';
126 1
        $this->codeStore->append($line);
127
      }
128 1
      $count++;
129 1
    }
130 1
    $this->codeStore->append(';');
131
    if ($editCharSet)
132 1
    {
133
      $this->codeStore->append(sprintf('ALTER TABLE %s.`%s` DEFAULT CHARACTER SET %s;', $this->config['database']['audit_schema'], $tableName, $charSet));
134
    }
135 1
  }
136
137
  //--------------------------------------------------------------------------------------------------------------------
138
  /**
139
   * The main method: executes the create alter table statement actions for tables.
140
   *
141
   * return string
142
   */
143 1
  public function main()
144
  {
145 1
    $this->processData();
146
147 1
    return $this->codeStore->getCode();
148
  }
149
150
  //--------------------------------------------------------------------------------------------------------------------
151
  /**
152
   * Computes the difference between data and audit tables.
153
   */
154 1
  private function getDiff()
155
  {
156 1
    foreach ($this->dataSchemaTables as $table)
157
    {
158 1
      if ($this->config['tables'][$table['table_name']]['audit'])
159 1
      {
160 1
        $res = AuditDataLayer::searchInRowSet('table_name', $table['table_name'], $this->auditSchemaTables);
161 1
        if (isset($res))
162 1
        {
163 1
          $this->diffColumns[$table['table_name']] = new AuditDiffTable($this->config['database']['data_schema'],
164 1
                                                                        $this->config['database']['audit_schema'],
165 1
                                                                        $table['table_name'],
166 1
                                                                        $this->auditColumnsMetadata,
167 1
                                                                        $this->configMetadata[$table['table_name']]);
168 1
        }
169 1
      }
170 1
    }
171 1
  }
172
173
  //--------------------------------------------------------------------------------------------------------------------
174
  /**
175
   * Getting list of all tables from information_schema of database from config file.
176
   */
177 1
  private function listOfTables()
178
  {
179 1
    $this->dataSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['data_schema']);
180
181 1
    $this->auditSchemaTables = AuditDataLayer::getTablesNames($this->config['database']['audit_schema']);
182 1
  }
183
184
  //--------------------------------------------------------------------------------------------------------------------
185
  /**
186
   *  Work on data for each table.
187
   */
188 1
  private function processData()
189
  {
190 1
    $this->resolveCanonicalAuditColumns();
191
192 1
    $this->listOfTables();
193
194 1
    $this->getDiff();
195
196
    /** @var AuditDiffTable $diffTable */
197 1
    foreach ($this->diffColumns as $tableName => $diffTable)
198
    {
199
      // Remove matching columns.
200 1
      $columns = $diffTable->removeMatchingColumns(true);
201
202 1
      $this->createSqlStatement($tableName, $columns);
203 1
    }
204 1
  }
205
206
  //--------------------------------------------------------------------------------------------------------------------
207
  /**
208
   * Resolves the canonical column types of the audit table columns.
209
   */
210 1
  private function resolveCanonicalAuditColumns()
211
  {
212 1
    if (empty($this->config['audit_columns']))
213 1
    {
214 1
      $this->auditColumnsMetadata = [];
215 1
    }
216
    else
217
    {
218
      $schema    = $this->config['database']['audit_schema'];
219
      $tableName = '_TMP_'.uniqid();
220
      AuditDataLayer::createTemporaryTable($schema, $tableName, $this->config['audit_columns']);
221
      $columns = AuditDataLayer::getTableColumns($schema, $tableName);
222
      AuditDataLayer::dropTemporaryTable($schema, $tableName);
223
224
      foreach ($this->config['audit_columns'] as $audit_column)
225
      {
226
        $key = AuditDataLayer::searchInRowSet('column_name', $audit_column['column_name'], $columns);
227
228
        if ($columns[$key]['is_nullable']==='NO')
229
        {
230
          $columns[$key]['column_type'] = sprintf('%s not null', $columns[$key]['column_type']);
231
        }
232
        if (isset($audit_column['value_type']))
233
        {
234
          $columns[$key]['value_type'] = $audit_column['value_type'];
235
        }
236
        if (isset($audit_column['expression']))
237
        {
238
          $columns[$key]['expression'] = $audit_column['expression'];
239
        }
240
      }
241
242
      $this->auditColumnsMetadata = $columns;
243
    }
244 1
  }
245
246
  //--------------------------------------------------------------------------------------------------------------------
247
}
248
249
//----------------------------------------------------------------------------------------------------------------------
250