Completed
Push — master ( 08dfad...a46189 )
by P.R.
04:31
created

DiffTable::rowsEnhanceWithTableOptions()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.3035

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 15
c 1
b 0
f 0
nc 6
nop 0
dl 0
loc 23
ccs 11
cts 15
cp 0.7332
crap 4.3035
rs 9.7666
1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Audit;
5
6
use SetBased\Audit\Metadata\TableMetadata;
7
use SetBased\Audit\Style\AuditStyle;
8
use SetBased\Exception\FallenException;
9
use Symfony\Component\Console\Helper\Table;
10
use Symfony\Component\Console\Helper\TableSeparator;
11
12
/**
13
 * Class for printing the differences between audit and data tables.
14
 */
15
class DiffTable
16
{
17
  //--------------------------------------------------------------------------------------------------------------------
18
  /**
19
   * The audit table.
20
   *
21
   * @var TableMetadata
22
   */
23
  private $auditTable;
24
25
  /**
26
   * The data table.
27
   *
28
   * @var TableMetadata
29
   */
30
  private $dataTable;
31
32
  /**
33
   * The join column names of the audit and data table.
34
   *
35
   * @var array[]
36
   */
37
  private $rows = [];
38
39
  //--------------------------------------------------------------------------------------------------------------------
40
  /**
41
   * Object constructor.
42
   *
43
   * @param TableMetadata $dataTable  The data table.
44
   * @param TableMetadata $auditTable The audit table.
45
   */
46 6
  public function __construct(TableMetadata $dataTable, TableMetadata $auditTable)
47
  {
48 6
    $this->dataTable  = $dataTable;
49 6
    $this->auditTable = $auditTable;
50 6
  }
51
52
  //--------------------------------------------------------------------------------------------------------------------
53
  /**
54
   * @param AuditStyle $io   The IO object.
55
   * @param bool       $full If false and only if only differences are shown.
56
   */
57 6
  public function print(AuditStyle $io, bool $full): void
58
  {
59 6
    $this->rowsEnhanceWithTableColumns();
60 6
    $this->rowsEnhanceWithTableOptions();
61 6
    $this->rowsEnhanceWithDiffIndicator();
62 6
    $this->rowsEnhanceWithColumnTypeInfo();
63 6
    $this->rowsEnhanceWithFormatting();
64
65 6
    if ($full || $this->hasDifferences())
66
    {
67 5
      $io->writeln('<dbo>'.$this->dataTable->getTableName().'</dbo>');
68
69 5
      $table = new Table($io);
70 5
      $table->setHeaders(['column', 'audit table', 'config / data table'])
71 5
            ->setRows($this->getRows($full));
72 5
      $table->render();
73
74 5
      $io->writeln('');
75
    }
76 6
  }
77
78
  //--------------------------------------------------------------------------------------------------------------------
79
  /**
80
   * Returns the rows suitable for Symfony's table.
81
   *
82
   * @param bool $full If false and only if only differences are shown.
83
   *
84
   * @return array[]
85
   */
86 5
  private function getRows(bool $full): array
87
  {
88 5
    $ret     = [];
89 5
    $options = false;
90 5
    foreach ($this->rows as $row)
91
    {
92
      // Add separator between columns and options.
93 5
      if ($options===false && $row['type']=='option')
94
      {
95 5
        if (!empty($ret)) $ret[] = new TableSeparator();
96 5
        $options = true;
97
      }
98
99 5
      if ($full || $row['diff'])
100
      {
101 5
        $ret[] = [$row['name'], $row['audit1'], $row['data1']];
102
103 5
        if ($row['rowspan']==2)
104
        {
105 3
          $ret[] = ['', $row['audit2'], $row['data2']];
106
        }
107
      }
108
    }
109
110 5
    return $ret;
111
  }
112
113
  //--------------------------------------------------------------------------------------------------------------------
114
  /**
115
   * Returns true if and only if the audit and data tables have differences.
116
   *
117
   * @return bool
118
   */
119 6
  private function hasDifferences(): bool
120
  {
121 6
    foreach ($this->rows as &$row)
122
    {
123 6
      if ($row['diff']) return true;
124
    }
125
126 2
    return false;
127
  }
128
129
  //--------------------------------------------------------------------------------------------------------------------
130
  /**
131
   * Enhances rows with column type info.
132
   */
133 6
  private function rowsEnhanceWithColumnTypeInfo(): void
134
  {
135 6
    foreach ($this->rows as &$row)
136
    {
137 6
      if ($row['type']=='column')
138
      {
139 6
        if ($row['data']!==null)
140
        {
141 6
          $row['data1'] = $row['data']->getTypeInfo1();
142 6
          $row['data2'] = $row['data']->getTypeInfo2();
143
        }
144
        else
145
        {
146 1
          $row['data1'] = null;
147 1
          $row['data2'] = null;
148
        }
149
150 6
        if ($row['audit']!==null)
151
        {
152 6
          $row['audit1'] = $row['audit']->getTypeInfo1();
153 6
          $row['audit2'] = $row['audit']->getTypeInfo2();
154
        }
155
        else
156
        {
157 1
          $row['audit1'] = null;
158 1
          $row['audit2'] = null;
159
        }
160
161 6
        $row['rowspan'] = ($row['data2']===null && $row['audit2']===null) ? 1 : 2;
162
      }
163
    }
164 6
  }
165
166
  //--------------------------------------------------------------------------------------------------------------------
167
  /**
168
   * Enhances rows with diff indicator.
169
   */
170 6
  private function rowsEnhanceWithDiffIndicator(): void
171
  {
172 6
    foreach ($this->rows as &$row)
173
    {
174 6
      switch ($row['type'])
175
      {
176 6
        case 'column':
177 6
          $row['diff'] = (isset($row['audit'])!==isset($row['data']) ||
178 6
            $row['audit']->getColumnDefinition()!=$row['data']->getColumnDefinition());
179 6
          break;
180
181 6
        case 'option':
182 6
          $row['diff'] = ($row['audit1']!=$row['data1']);
183 6
          break;
184
185
        default:
186
          throw new FallenException('type', $row['type']);
187
      }
188
    }
189 6
  }
190
191
  //--------------------------------------------------------------------------------------------------------------------
192
  /**
193
   * Enhances rows text with formatting.
194
   */
195 6
  private function rowsEnhanceWithFormatting(): void
196
  {
197 6
    foreach ($this->rows as &$row)
198
    {
199 6
      if ($row['diff'])
200
      {
201 4
        $row['name'] = sprintf('<mm_column>%s</mm_column>', $row['name']);
202
      }
203
204 6
      if ($row['audit1']!=$row['data1'])
205
      {
206 3
        $row['audit1'] = sprintf('<mm_type>%s</mm_type>', $row['audit1']);
207 3
        $row['data1']  = sprintf('<mm_type>%s</mm_type>', $row['data1']);
208
      }
209
210 6
      if ($row['rowspan']==2 && ($row['audit2']!=$row['data2']))
211
      {
212 2
        $row['audit2'] = sprintf('<mm_type>%s</mm_type>', $row['audit2']);
213 2
        $row['data2']  = sprintf('<mm_type>%s</mm_type>', $row['data2']);
214
      }
215
    }
216 6
  }
217
218
  //--------------------------------------------------------------------------------------------------------------------
219
  /**
220
   * Computes the joins columns of the audit and data table.
221
   */
222 6
  private function rowsEnhanceWithTableColumns(): void
223
  {
224 6
    $auditColumns = $this->auditTable->getColumns()->getColumnNames();
225 6
    $dataColumns  = $this->dataTable->getColumns()->getColumnNames();
226
227 6
    $this->rows = [];
228 6
    foreach ($dataColumns as $column)
229
    {
230 6
      if (in_array($column, $auditColumns))
231
      {
232 6
        $this->rows[] = ['name'     => $column,
233 6
                         'audit'    => $this->auditTable->getColumns()->getColumn($column),
234 6
                         'data'     => $this->dataTable->getColumns()->getColumn($column),
235 6
                         'type'     => 'column',
236
                         'new'      => false,
237
                         'obsolete' => false];
238
      }
239
      else
240
      {
241 1
        $this->rows[] = ['name'     => $column,
242
                         'audit'    => null,
243 1
                         'data'     => $this->dataTable->getColumns()->getColumn($column),
244 1
                         'type'     => 'column',
245
                         'new'      => true,
246
                         'obsolete' => false];
247
      }
248
    }
249
250 6
    foreach ($auditColumns as $column)
251
    {
252 6
      if (!in_array($column, $dataColumns))
253
      {
254 1
        $this->rows[] = ['name'     => $column,
255 1
                         'audit'    => $this->auditTable->getColumns()->getColumn($column),
256
                         'data'     => null,
257 1
                         'type'     => 'column',
258
                         'new'      => false,
259
                         'obsolete' => true];
260
      }
261
    }
262 6
  }
263
264
  //--------------------------------------------------------------------------------------------------------------------
265
  /**
266
   * Adds table options to the rows.
267
   */
268 6
  private function rowsEnhanceWithTableOptions(): void
269
  {
270 6
    $auditOptions = array_keys($this->auditTable->getOptions());
271 6
    $dataOptions  = array_keys($this->dataTable->getOptions());
272
273 6
    foreach ($dataOptions as $option)
274
    {
275 6
      $this->rows[] = ['name'    => $option,
276 6
                       'audit1'  => $this->auditTable->getProperty($option),
277 6
                       'data1'   => $this->dataTable->getProperty($option),
278 6
                       'type'    => 'option',
279 6
                       'rowspan' => 1];
280
    }
281
282 6
    foreach ($auditOptions as $option)
283
    {
284 6
      if (!in_array($option, $dataOptions))
285
      {
286
        $this->rows[] = ['name'    => $option,
287
                         'audit1'  => $this->auditTable->getProperty($option),
288
                         'data2'   => null,
289
                         'type'    => 'option',
290
                         'rowspan' => 1];
291
      }
292
    }
293 6
  }
294
295
  //--------------------------------------------------------------------------------------------------------------------
296
}
297
298
//----------------------------------------------------------------------------------------------------------------------
299