Audit::unknownTables()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
c 1
b 0
f 0
nc 6
nop 0
dl 0
loc 27
ccs 9
cts 9
cp 1
crap 6
rs 9.2222
1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Audit\Audit;
5
6
use SetBased\Audit\AuditTable;
7
use SetBased\Audit\Metadata\TableColumnsMetadata;
8
use SetBased\Audit\MySql\AuditDataLayer;
9
use SetBased\Audit\Style\AuditStyle;
10
use SetBased\Config\TypedConfig;
11
use SetBased\Stratum\Middle\Helper\RowSetHelper;
12
13
/**
14
 * Class for executing auditing actions for tables.
15
 */
16
class Audit
17
{
18
  //--------------------------------------------------------------------------------------------------------------------
19
  /**
20
   * The metadata of the additional audit columns.
21
   *
22
   * @var TableColumnsMetadata
23
   */
24
  private TableColumnsMetadata $additionalAuditColumns;
25
26
  /**
27
   * The names of all tables in audit schema.
28
   *
29
   * @var array
30
   */
31
  private array $auditSchemaTables;
32
33
  /**
34
   * The strong typed configuration reader and writer.
35
   *
36
   * @var TypedConfig
37
   */
38
  private TypedConfig $config;
39
40
  /**
41
   * The names of all tables in data schema.
42
   *
43
   * @var array
44
   */
45
  private array $dataSchemaTables;
46
47
  /**
48
   * The Output decorator.
49
   *
50
   * @var AuditStyle
51
   */
52
  private AuditStyle $io;
53
54
  //--------------------------------------------------------------------------------------------------------------------
55
  /**
56
   * Object constructor.
57
   *
58
   * @param TypedConfig $config The strong typed configuration reader and writer.
59
   * @param AuditStyle  $io     The Output decorator.
60
   */
61 31
  public function __construct(TypedConfig $config, AuditStyle $io)
62
  {
63 31
    $this->config = $config;
64 31
    $this->io     = $io;
65
66 31
    $this->additionalAuditColumns =
67 31
      AuditDataLayer::$dl->resolveCanonicalAdditionalAuditColumns($this->config->getManString('database.audit_schema'),
68 31
                                                                  $this->config->getManArray('audit_columns'));
69 31
  }
70
71
  //--------------------------------------------------------------------------------------------------------------------
72
  /**
73
   * Getting list of all tables from information_schema of database from config file.
74
   */
75 31
  public function listOfTables(): void
76
  {
77 31
    $this->dataSchemaTables  = AuditDataLayer::$dl->getTablesNames($this->config->getManString('database.data_schema'));
78 31
    $this->auditSchemaTables = AuditDataLayer::$dl->getTablesNames($this->config->getManString('database.audit_schema'));
79 31
  }
80
81
  //--------------------------------------------------------------------------------------------------------------------
82
  /**
83
   * The main method: executes the auditing actions for tables.
84
   */
85 31
  public function main(): void
86
  {
87 31
    $this->listOfTables();
88
    $this->unknownTables();
89 31
    $this->obsoleteTables();
90
    $this->knownTables();
91 31
  }
92
93 31
  //--------------------------------------------------------------------------------------------------------------------
94 31
  /**
95
   * Removes tables listed in the config file that are no longer in the data schema from the config file.
96
   */
97
  public function obsoleteTables(): void
98
  {
99
    foreach ($this->config->getManArray('tables') as $tableName => $dummy)
100 31
    {
101
      if (RowSetHelper::searchInRowSet($this->dataSchemaTables, 'table_name', $tableName)===null)
102 31
      {
103
        $this->io->writeln(sprintf('<info>Removing obsolete table %s from config file</info>', $tableName));
104 30
105
        // Unset table (work a round bug in \Noodlehaus\Config::remove()).
106 8
        $config = $this->config->getConfig();
107
        $tables = $config['tables'];
108
        unset($tables[$tableName]);
109 8
        $config->set('tables', $tables);
110 8
      }
111 8
    }
112 8
  }
113
114
  //--------------------------------------------------------------------------------------------------------------------
115 31
  /**
116
   * Compares the tables listed in the config file and the tables found in the data schema.
117
   */
118
  public function unknownTables(): void
119
  {
120
    foreach ($this->dataSchemaTables as $table)
121 31
    {
122
      if ($this->config->getOptArray('tables.'.$table['table_name'])!==null)
123 31
      {
124
        if ($this->config->getOptBool('tables.'.$table['table_name'].'.audit')===null)
125 30
        {
126
          $this->io->writeln(sprintf('<info>Audit not set for table %s</info>', $table['table_name']));
127 30
        }
128
        else
129 1
        {
130
          if ($this->config->getManBool('tables.'.$table['table_name'].'.audit'))
131
          {
132
            if ($this->config->getOptString('tables.'.$table['table_name'].'.alias')===null)
133 30
            {
134
              $this->config->getConfig()
135 30
                           ->set('tables.'.$table['table_name'].'.alias', AuditTable::getRandomAlias());
136
            }
137 30
          }
138
        }
139
      }
140
      else
141
      {
142
        $this->io->writeln(sprintf('<info>Found new table %s</info>', $table['table_name']));
143
        $config = $this->config->getConfig();
144 1
        $config->set('tables.'.$table['table_name'], ['audit' => null, 'alias' => null, 'skip' => null]);
145 1
      }
146 1
    }
147
  }
148
149 31
  //--------------------------------------------------------------------------------------------------------------------
150
  /**
151
   * Processed known tables.
152
   */
153
  private function knownTables(): void
154
  {
155 31
    foreach ($this->dataSchemaTables as $table)
156
    {
157 31
      $audit = $this->config->getOptBool('tables.'.$table['table_name'].'.audit');
158
      if ($audit===true)
159 30
      {
160 30
        $currentTable = new AuditTable($this->io,
161
                                       $this->config->getManString('database.data_schema'),
162 30
                                       $this->config->getManString('database.audit_schema'),
163 30
                                       $table['table_name'],
164 30
                                       $this->additionalAuditColumns,
165 30
                                       $this->config->getOptString('tables.'.$table['table_name'].'.alias'),
166 30
                                       $this->config->getOptString('tables.'.$table['table_name'].'.skip'));
167 30
168 30
        // Ensure the audit table exists.
169
        if (RowSetHelper::searchInRowSet($this->auditSchemaTables, 'table_name', $table['table_name'])===null)
170
        {
171 30
          $currentTable->createAuditTable();
172
        }
173 27
174
        // Drop and create audit triggers and add new columns to the audit table.
175
        $currentTable->main($this->config->getManArray('additional_sql'));
176
      }
177 30
      elseif ($audit===false)
178
      {
179 2
        AuditTable::dropAuditTriggers($this->io,
180
                                      $this->config->getManString('database.data_schema'),
181 1
                                      $table['table_name']);
182 1
      }
183 1
      else /* $audit===null */
184
      {
185
        $this->io->logVerbose('Ignoring table <dbo>%s</dbo>', $table['table_name']);
186
      }
187 1
    }
188
  }
189
190 31
  //--------------------------------------------------------------------------------------------------------------------
191
}
192
193
//----------------------------------------------------------------------------------------------------------------------
194