Completed
Pull Request — master (#35)
by
unknown
04:01
created

AuditCommand::auditColumnTypes()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5

Importance

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