Completed
Push — master ( 1f7a6d...d6c443 )
by P.R.
03:14
created

DiffTable::hasDifferences()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

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