Test Failed
Push — master ( d02081...898276 )
by P.R.
04:01
created

DiffTable   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 276
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 276
rs 8.295
c 0
b 0
f 0
wmc 42

9 Methods

Rating   Name   Duplication   Size   Complexity  
A hasDifferences() 0 8 3
A print() 0 18 3
B rowsEnhanceWithDiffIndicator() 0 17 5
C rowsEnhanceWithColumnTypeInfo() 0 29 7
C getRows() 0 25 8
A __construct() 0 4 1
B rowsEnhanceWithTableColumns() 0 38 5
B rowsEnhanceWithFormatting() 0 19 6
B rowsEnhanceWithTableOptions() 0 23 4

How to fix   Complexity   

Complex Class

Complex classes like DiffTable often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DiffTable, and based on these observations, apply Extract Interface, too.

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