Passed
Push — master ( 9e86dc...6cbe7e )
by P.R.
06:56
created

CreateAuditTrigger::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 19
ccs 10
cts 10
cp 1
crap 1
rs 9.9666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Audit\MySql\Sql;
5
6
use SetBased\Audit\Metadata\TableColumnsMetadata;
7
use SetBased\Audit\MySql\AuditDataLayer;
8
use SetBased\Exception\FallenException;
9
use SetBased\Exception\RuntimeException;
10
use SetBased\Helper\CodeStore\MySqlCompoundSyntaxCodeStore;
11
12
/**
13
 * Class for creating SQL statements for creating audit triggers.
14
 */
15
class CreateAuditTrigger
16
{
17
  //--------------------------------------------------------------------------------------------------------------------
18
  /**
19
   * The metadata of the additional audit columns.
20
   *
21
   * @var TableColumnsMetadata
22
   */
23
  private $additionalAuditColumns;
24
25
  /**
26
   * Additional SQL statements.
27
   *
28
   * @var string[]|null
29
   */
30
  private $additionalSql;
31
32
  /**
33
   * The name of the audit schema.
34
   *
35
   * @var string
36
   */
37
  private $auditSchemaName;
38
39
  /**
40
   * The generated code.
41
   *
42
   * @var MySqlCompoundSyntaxCodeStore
43
   */
44
  private $code;
45
46
  /**
47
   * The name of the data schema.
48
   *
49
   * @var string
50
   */
51
  private $dataSchemaName;
52
53
  /**
54
   * The skip variable.
55
   *
56
   * @var string|null
57
   */
58
  private $skipVariable;
59
60
  /**
61
   * Audit columns from metadata.
62
   *
63
   * @var TableColumnsMetadata
64
   */
65
  private $tableColumns;
66
67
  /**
68
   * The name of the data table.
69
   *
70
   * @var string
71
   */
72
  private $tableName;
73
74
  /**
75
   * The trigger action (i.e. INSERT, UPDATE, or DELETE).
76
   *
77
   * @var string
78
   */
79
  private $triggerAction;
80
81
  /**
82
   * The name of the trigger.
83
   *
84
   * @var string
85
   */
86
  private $triggerName;
87
88
  //--------------------------------------------------------------------------------------------------------------------
89
  /**
90
   * Creates a trigger on a table.
91
   *
92
   * @param string               $dataSchemaName         The name of the data schema.
93
   * @param string               $auditSchemaName        The name of the audit schema.
94
   * @param string               $tableName              The name of the table.
95
   * @param string               $triggerAction          The trigger action (i.e. INSERT, UPDATE, or DELETE).
96
   * @param string               $triggerName            The name of the trigger.
97
   * @param TableColumnsMetadata $additionalAuditColumns The metadata of the additional audit columns.
98
   * @param TableColumnsMetadata $tableColumns           The metadata of the data table columns.
99
   * @param string|null          $skipVariable           The skip variable.
100
   * @param string[]|null        $additionalSql          Additional SQL statements.
101
   */
102 31
  public function __construct(string $dataSchemaName,
103
                              string $auditSchemaName,
104
                              string $tableName,
105
                              string $triggerName,
106
                              string $triggerAction,
107
                              TableColumnsMetadata $additionalAuditColumns,
108
                              TableColumnsMetadata $tableColumns,
109
                              ?string $skipVariable,
110
                              ?array $additionalSql)
111
  {
112 31
    $this->dataSchemaName         = $dataSchemaName;
113 31
    $this->auditSchemaName        = $auditSchemaName;
114 31
    $this->tableName              = $tableName;
115 31
    $this->triggerName            = $triggerName;
116 31
    $this->triggerAction          = $triggerAction;
117 31
    $this->skipVariable           = $skipVariable;
118 31
    $this->additionalAuditColumns = $additionalAuditColumns;
119 31
    $this->tableColumns           = $tableColumns;
120 31
    $this->additionalSql          = $additionalSql;
121 31
  }
122
123
  //--------------------------------------------------------------------------------------------------------------------
124
  /**
125
   * Returns the SQL code for creating an audit trigger.
126
   *
127
   * @return string
128
   *
129
   * @throws FallenException
130
   */
131 31
  public function buildStatement(): string
132
  {
133 31
    $this->code = new MySqlCompoundSyntaxCodeStore();
134
135 31
    $rowState = [];
136 31
    switch ($this->triggerAction)
137
    {
138 31
      case 'INSERT':
139 31
        $rowState[] = 'NEW';
140 31
        break;
141
142 31
      case 'DELETE':
143 31
        $rowState[] = 'OLD';
144 31
        break;
145
146 31
      case 'UPDATE':
147 31
        $rowState[] = 'OLD';
148 31
        $rowState[] = 'NEW';
149 31
        break;
150
151
      default:
152
        throw new FallenException('action', $this->triggerAction);
153
    }
154
155 31
    $this->code->append(sprintf('create trigger `%s`.`%s`', $this->dataSchemaName, $this->triggerName));
156 31
    $this->code->append(sprintf('after %s on `%s`.`%s`',
157 31
                                strtolower($this->triggerAction),
158 31
                                $this->dataSchemaName,
159 31
                                $this->tableName));
160 31
    $this->code->append('for each row');
161 31
    $this->code->append('begin');
162
163 31
    if ($this->skipVariable!==null) $this->code->append(sprintf('if (%s is null) then', $this->skipVariable));
164
165 31
    $this->code->append($this->additionalSql);
166
167 31
    $this->createInsertStatement($rowState[0]);
168 31
    if (count($rowState)==2)
169
    {
170 31
      $this->createInsertStatement($rowState[1]);
171
    }
172
173 31
    if ($this->skipVariable!==null) $this->code->append('end if;');
174 31
    $this->code->append('end');
175
176 31
    return $this->code->getCode();
177
  }
178
179
  //--------------------------------------------------------------------------------------------------------------------
180
  /**
181
   * Adds an insert SQL statement to SQL code for a trigger.
182
   *
183
   * @param string $rowState The row state (i.e. OLD or NEW).
184
   */
185 31
  private function createInsertStatement(string $rowState): void
186
  {
187 31
    $this->createInsertStatementInto();
188 31
    $this->createInsertStatementValues($rowState);
189 31
  }
190
191
  //--------------------------------------------------------------------------------------------------------------------
192
  /**
193
   * Adds the "insert into" part of an insert SQL statement to SQL code for a trigger.
194
   */
195 31
  private function createInsertStatementInto(): void
196
  {
197 31
    $columnNames = '';
198
199
    // First the audit columns.
200 31
    foreach ($this->additionalAuditColumns->getColumns() as $column)
201
    {
202 20
      if ($columnNames) $columnNames .= ',';
203 20
      $columnNames .= sprintf('`%s`', $column->getName());
204
    }
205
206
    // Second the audit columns.
207 31
    foreach ($this->tableColumns->getColumns() as $column)
208
    {
209 31
      if ($columnNames) $columnNames .= ',';
210 31
      $columnNames .= sprintf('`%s`', $column->getName());
211
    }
212
213 31
    $this->code->append(sprintf('insert into `%s`.`%s`(%s)', $this->auditSchemaName, $this->tableName, $columnNames));
214 31
  }
215
216
  //--------------------------------------------------------------------------------------------------------------------
217
  /**
218
   * Adds the "values" part of an insert SQL statement to SQL code for a trigger.
219
   *
220
   * @param string $rowState The row state (i.e. OLD or NEW).
221
   */
222 31
  private function createInsertStatementValues(string $rowState): void
223
  {
224 31
    $values = '';
225
226
    // First the values for the audit columns.
227 31
    foreach ($this->additionalAuditColumns->getColumns() as $column)
228
    {
229 20
      $column = $column->getProperties();
230 20
      if ($values) $values .= ',';
231
232
      switch (true)
233
      {
234 20
        case (isset($column['value_type'])):
235 19
          switch ($column['value_type'])
236
          {
237 19
            case 'ACTION':
238 19
              $values .= AuditDataLayer::$dl->quoteString($this->triggerAction);
239 19
              break;
240
241 19
            case 'STATE':
242 19
              $values .= AuditDataLayer::$dl->quoteString($rowState);
243 19
              break;
244
245
            default:
246
              throw new FallenException('value_type', ($column['value_type']));
247
          }
248 19
          break;
249
250 11
        case (isset($column['expression'])):
251 11
          $values .= $column['expression'];
252 11
          break;
253
254
        default:
255
          throw new RuntimeException('None of value_type and expression are set.');
256
      }
257
    }
258
259
    // Second the values for the audit columns.
260 31
    foreach ($this->tableColumns->getColumns() as $column)
261
    {
262 31
      if ($values) $values .= ',';
263 31
      $values .= sprintf('%s.`%s`', $rowState, $column->getName());
264
    }
265
266 31
    $this->code->append(sprintf('values(%s);', $values));
267 31
  }
268
269
  //--------------------------------------------------------------------------------------------------------------------
270
}
271
272
//----------------------------------------------------------------------------------------------------------------------
273