Completed
Push — master ( 742dfe...5d62cd )
by P.R.
03:28
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
            if(!isset($this->config['tables'][$table['table_name']]['alias']))
97
            {
98
              $this->config['tables'][$table['table_name']]['alias'] = Table::getRandomAlias();
99
            }
100
          }
101
        }
102
      }
103
      else
104
      {
105
        $this->io->writeln(sprintf('<info>Found new table %s</info>', $table['table_name']));
106
        $this->config['tables'][$table['table_name']] = ['audit' => false,
107
                                                         'alias' => null,
108
                                                         'skip'  => null];
109
      }
110
    }
111
  }
112
113
  //--------------------------------------------------------------------------------------------------------------------
114
  /**
115
   * {@inheritdoc}
116
   */
117
  protected function configure()
118
  {
119
    $this->setName('audit')
120
         ->setDescription('Create (missing) audit table and (re)creates audit triggers')
121
         ->addArgument('config file', InputArgument::OPTIONAL, 'The audit configuration file', 'etc/audit.json');
122
  }
123
124
  //--------------------------------------------------------------------------------------------------------------------
125
  /**
126
   * {@inheritdoc}
127
   */
128
  protected function execute(InputInterface $input, OutputInterface $output)
129
  {
130
    $this->io = new StratumStyle($input, $output);
131
132
    $this->configFileName = $input->getArgument('config file');
133
    $this->readConfigFile();
134
135
    // Create database connection with params from config file
136
    $this->connect($this->config);
137
138
    $this->auditColumnTypes();
139
140
    $this->listOfTables();
141
142
    $this->unknownTables();
143
144
    foreach ($this->dataSchemaTables as $table)
145
    {
146
      if ($this->config['tables'][$table['table_name']]['audit'])
147
      {
148
        $tableColumns = [];
149
        if (isset($this->config['table_columns'][$table['table_name']]))
150
        {
151
          $tableColumns = $this->config['table_columns'][$table['table_name']];
152
        }
153
        $currentTable = new Table($this->io,
154
                                  $table['table_name'],
155
                                  $this->config['database']['data_schema'],
156
                                  $this->config['database']['audit_schema'],
157
                                  $tableColumns,
158
                                  $this->config['audit_columns'],
159
                                  $this->config['tables'][$table['table_name']]['alias'],
160
                                  $this->config['tables'][$table['table_name']]['skip']);
161
        $res          = StaticDataLayer::searchInRowSet('table_name', $currentTable->getTableName(), $this->auditSchemaTables);
162
        if (!isset($res))
163
        {
164
          $currentTable->createMissingAuditTable();
165
        }
166
167
        $columns        = $currentTable->main($this->config['additional_sql']);
168
        $alteredColumns = $columns['altered_columns']->getColumns();
169
        if (empty($alteredColumns))
170
        {
171
          $this->getColumns($currentTable->getTableName(), $columns['full_columns']);
172
        }
173
      }
174
    }
175
176
    // Drop database connection
177
    DataLayer::disconnect();
178
179
    $this->rewriteConfig();
180
  }
181
182
  //--------------------------------------------------------------------------------------------------------------------
183
  /**
184
   * Get canonical column types for audit columns.
185
   */
186
  protected function auditColumnTypes()
187
  {
188
    $schema = $this->config['database']['audit_schema'];
189
    $table  = 'temp';
190
    DataLayer::createTempTable($schema, $this->config['audit_columns']);
191
    $auditColumns = DataLayer::getTableColumns($schema, $table);
192
    foreach ($auditColumns as $column)
193
    {
194
      $key = StaticDataLayer::searchInRowSet('column_name', $column['column_name'], $this->config['audit_columns']);
195
      if (isset($key))
196
      {
197
        $this->config['audit_columns'][$key]['column_type'] = $column['column_type'];
198
        if ($column['is_nullable']==='NO')
199
        {
200
          $this->config['audit_columns'][$key]['column_type'] = sprintf('%s not null', $this->config['audit_columns'][$key]['column_type']);
201
        }
202
      }
203
    }
204
    DataLayer::dropTable($schema, $table);
205
  }
206
207
  //--------------------------------------------------------------------------------------------------------------------
208
  /**
209
   * Write new data to config file.
210
   */
211
  private function rewriteConfig()
212
  {
213
    $this->writeTwoPhases($this->configFileName, json_encode($this->config, JSON_PRETTY_PRINT));
214
  }
215
216
  //--------------------------------------------------------------------------------------------------------------------
217
}
218
219
//----------------------------------------------------------------------------------------------------------------------
220