Completed
Pull Request — master (#30)
by
unknown
02:31
created

AuditCommand::auditColumnTypes()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 20
rs 9.2
cc 4
eloc 12
nc 4
nop 0
1
<?php
2
//----------------------------------------------------------------------------------------------------------------------
3
namespace SetBased\Audit\MySql\Command;
4
5
use SetBased\Audit\Columns;
6
use SetBased\Audit\MySql\DataLayer;
7
use SetBased\Audit\Table;
8
use SetBased\Stratum\MySql\StaticDataLayer;
9
use SetBased\Stratum\Style\StratumStyle;
10
use Symfony\Component\Console\Input\InputArgument;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
//----------------------------------------------------------------------------------------------------------------------
15
/**
16
 * Command for creating audit tables and audit triggers.
17
 */
18
class AuditCommand extends MySqlCommand
19
{
20
  //--------------------------------------------------------------------------------------------------------------------
21
  /**
22
   * All tables in the in the audit schema.
23
   *
24
   * @var array
25
   */
26
  protected $auditSchemaTables;
27
28
  /**
29
   * Array of tables from data schema.
30
   *
31
   * @var array
32
   */
33
  protected $dataSchemaTables;
34
35
  /**
36
   * If true remove all column information from config file.
37
   *
38
   * @var boolean
39
   */
40
  private $pruneOption;
41
42
  //--------------------------------------------------------------------------------------------------------------------
43
  /**
44
   * Compares the tables listed in the config file and the tables found in the audit schema
45
   *
46
   * @param string  $tableName Name of table
47
   * @param Columns $columns   The table columns.
48
   */
49
  public function getColumns($tableName, $columns)
50
  {
51
    $newColumns = [];
52
    foreach ($columns->getColumns() as $column)
53
    {
54
      $newColumns[] = ['column_name' => $column['column_name'],
55
                       'column_type' => $column['column_type']];
56
    }
57
    $this->config['table_columns'][$tableName] = $newColumns;
58
59
    if ($this->pruneOption)
60
    {
61
      $this->config['table_columns'] = [];
62
    }
63
  }
64
65
  //--------------------------------------------------------------------------------------------------------------------
66
  /**
67
   * Getting list of all tables from information_schema of database from config file.
68
   */
69
  public function listOfTables()
70
  {
71
    $this->dataSchemaTables = DataLayer::getTablesNames($this->config['database']['data_schema']);
72
73
    $this->auditSchemaTables = DataLayer::getTablesNames($this->config['database']['audit_schema']);
74
  }
75
76
  //--------------------------------------------------------------------------------------------------------------------
77
  /**
78
   * Found tables in config file
79
   *
80
   * Compares the tables listed in the config file and the tables found in the data schema
81
   */
82
  public function unknownTables()
83
  {
84
    foreach ($this->dataSchemaTables as $table)
85
    {
86
      if (isset($this->config['tables'][$table['table_name']]))
87
      {
88
        if (!isset($this->config['tables'][$table['table_name']]['audit']))
89
        {
90
          $this->io->writeln(sprintf('<info>AuditApplication flag is not set in table %s</info>', $table['table_name']));
91
        }
92
        else
93
        {
94
          if ($this->config['tables'][$table['table_name']]['audit'])
95
          {
96
            $this->config['tables'][$table['table_name']]['alias'] = Table::getRandomAlias();
97
          }
98
        }
99
      }
100
      else
101
      {
102
        $this->io->writeln(sprintf('<info>Found new table %s</info>', $table['table_name']));
103
        $this->config['tables'][$table['table_name']] = ['audit' => false,
104
                                                         'alias' => null,
105
                                                         'skip'  => null];
106
      }
107
    }
108
  }
109
110
  //--------------------------------------------------------------------------------------------------------------------
111
  /**
112
   * {@inheritdoc}
113
   */
114
  protected function configure()
115
  {
116
    $this->setName('audit')
117
         ->setDescription('Create (missing) audit table and (re)creates audit triggers')
118
         ->addArgument('config file', InputArgument::OPTIONAL, 'The audit configuration file', 'etc/audit.json');
119
  }
120
121
  //--------------------------------------------------------------------------------------------------------------------
122
  /**
123
   * {@inheritdoc}
124
   */
125
  protected function execute(InputInterface $input, OutputInterface $output)
126
  {
127
    $this->io = new StratumStyle($input, $output);
128
129
    $this->configFileName = $input->getArgument('config file');
130
    $this->readConfigFile();
131
132
    // Create database connection with params from config file
133
    $this->connect($this->config);
134
135
    $this->auditColumnTypes();
136
137
    $this->listOfTables();
138
139
    $this->unknownTables();
140
141
    foreach ($this->dataSchemaTables as $table)
142
    {
143
      if ($this->config['tables'][$table['table_name']]['audit'])
144
      {
145
        $tableColumns = [];
146
        if (isset($this->config['table_columns'][$table['table_name']]))
147
        {
148
          $tableColumns = $this->config['table_columns'][$table['table_name']];
149
        }
150
        $currentTable = new Table($this->io,
151
                                  $table['table_name'],
152
                                  $this->config['database']['data_schema'],
153
                                  $this->config['database']['audit_schema'],
154
                                  $tableColumns,
155
                                  $this->config['audit_columns'],
156
                                  $this->config['tables'][$table['table_name']]['alias'],
157
                                  $this->config['tables'][$table['table_name']]['skip']);
158
        $res          = StaticDataLayer::searchInRowSet('table_name', $currentTable->getTableName(), $this->auditSchemaTables);
159
        if (!isset($res))
160
        {
161
          $currentTable->createMissingAuditTable();
162
        }
163
164
        $columns        = $currentTable->main($this->config['additional_sql']);
165
        $alteredColumns = $columns['altered_columns']->getColumns();
166
        if (empty($alteredColumns))
167
        {
168
          $this->getColumns($currentTable->getTableName(), $columns['full_columns']);
169
        }
170
      }
171
    }
172
173
    // Drop database connection
174
    DataLayer::disconnect();
175
176
    $this->rewriteConfig();
177
  }
178
179
  //--------------------------------------------------------------------------------------------------------------------
180
  /**
181
   * Get canonical column types for audit columns.
182
   */
183
  protected function auditColumnTypes()
184
  {
185
    $schema = $this->config['database']['audit_schema'];
186
    $table  = 'temp';
187
    DataLayer::createTempTable($schema, $this->config['audit_columns']);
188
    $auditColumns = DataLayer::getTableColumns($schema, $table);
189
    foreach ($auditColumns as $column)
190
    {
191
      $key = StaticDataLayer::searchInRowSet('column_name', $column['column_name'], $this->config['audit_columns']);
192
      if (isset($key))
193
      {
194
        $this->config['audit_columns'][$key]['column_type'] = $column['column_type'];
195
        if ($column['is_nullable']==='NO')
196
        {
197
          $this->config['audit_columns'][$key]['column_type'] = sprintf('%s not null', $this->config['audit_columns'][$key]['column_type']);
198
        }
199
      }
200
    }
201
    DataLayer::dropTable($schema, $table);
202
  }
203
204
  //--------------------------------------------------------------------------------------------------------------------
205
  /**
206
   * Write new data to config file.
207
   */
208
  private function rewriteConfig()
209
  {
210
    $this->writeTwoPhases($this->configFileName, json_encode($this->config, JSON_PRETTY_PRINT));
211
  }
212
213
  //--------------------------------------------------------------------------------------------------------------------
214
}
215
216
//----------------------------------------------------------------------------------------------------------------------
217