Completed
Pull Request — master (#57)
by Dima
02:53
created

AuditAlter::main()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
246
    }
247
  }
248
249
  //--------------------------------------------------------------------------------------------------------------------
250
}
251
252
//----------------------------------------------------------------------------------------------------------------------
253