Completed
Push — master ( 923e5b...e9edfd )
by Stanislav
02:17
created

TableUtils   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 33
c 2
b 0
f 0
lcom 1
cbo 2
dl 0
loc 127
rs 9.3999

7 Methods

Rating   Name   Duplication   Size   Complexity  
B parseFilters() 0 14 6
C parseFilter() 0 27 7
A parseRegexFilter() 0 6 1
A filterRows() 0 18 4
B filterRow() 0 18 8
A sortRowsByColumnNumber() 0 18 3
A printTable() 0 17 4
1
<?php
2
3
namespace Popstas\Transmission\Console\Helpers;
4
5
use Symfony\Component\Console\Helper\Table;
6
use Symfony\Component\Console\Helper\TableSeparator;
7
use Symfony\Component\Console\Output\OutputInterface;
8
9
class TableUtils
10
{
11
    public static function parseFilters(array $filters)
12
    {
13
        foreach ($filters as $columnKey => $filter) {
14
            if (is_array($filter) && !isset($filter['type'])) {
15
                throw new \InvalidArgumentException('Unknown filter type');
16
            }
17
            if (!isset($filter) || !isset($filter['value'])) {
18
                unset($filters[$columnKey]);
19
                continue;
20
            }
21
            $filters = self::parseFilter($filter['type'], $filter['value']) + $filters[$columnKey];
22
        }
23
        return $filters;
24
    }
25
26
    private static function parseFilter($type, $filterString)
27
    {
28
        switch ($type) {
29
            case 'numeric':
30
                $filter = [];
31
                preg_match_all('/([<>])\s?([\d\.]+)/', $filterString, $results, PREG_SET_ORDER);
32
                if ($results) {
33
                    foreach ($results as $result) {
34
                        $operator = $result[1];
35
                        $value = $result[2];
36
                        if ($operator == '<') {
37
                            $filter['max'] = $value;
38
                        }
39
                        if ($operator == '>') {
40
                            $filter['min'] = $value;
41
                        }
42
                    }
43
                }
44
                return $filter;
45
46
            case 'regex':
47
                return ['regex' => str_replace(['/', '.', '*'], ['\/', '\.', '.*?'], $filterString)];
48
49
            default:
50
                throw new \InvalidArgumentException('Unknown filter type');
51
        }
52
    }
53
54
    public static function parseRegexFilter($filterString)
55
    {
56
        $filter = [];
57
        $filter['regex'] = str_replace(['/', '.', '*'], ['\/', '\.', '.*?'], $filterString);
58
        return $filter;
59
    }
60
61
    public static function filterRows(array $rows, $filters)
62
    {
63
        $filters = self::parseFilters($filters);
64
65
        return array_filter($rows, function ($row) use ($filters) {
66
            foreach ($filters as $columnKey => $filter) {
67
                if (!isset($row[$columnKey])) {
68
                    continue;
69
                }
70
                $columnValue = $row[$columnKey];
71
72
                if (!self::filterRow($columnValue, $filter)) {
73
                    return false;
74
                }
75
            }
76
            return true;
77
        });
78
    }
79
80
    private static function filterRow($value, $filter)
81
    {
82
        if ($filter['type'] == 'numeric') {
83
            if ((isset($filter['min']) && $value <= $filter['min']) ||
84
                (isset($filter['max']) && $value >= $filter['max'])
85
            ) {
86
                return false;
87
            }
88
        }
89
90
        if ($filter['type'] == 'regex') {
91
            if (!preg_match('/' . $filter['regex'] . '/i', $value)) {
92
                return false;
93
            }
94
        }
95
96
        return true;
97
    }
98
99
    public static function sortRowsByColumnNumber(array $rows, $columnNumber)
100
    {
101
        $rowsSorted = $rows;
102
        $columnsTotal = count(end($rows));
103
104
        $sortOrder = $columnNumber > 0 ? 1 : -1;
105
106
        $columnIndex = max(1, min(
107
            $columnsTotal,
108
            abs($columnNumber)
109
        )) - 1;
110
111
        usort($rowsSorted, function ($first, $second) use ($columnIndex, $sortOrder) {
112
            return $first[$columnIndex] > $second[$columnIndex] ? $sortOrder : $sortOrder * -1;
113
        });
114
115
        return $rowsSorted;
116
    }
117
118
    public static function printTable(array $tableData, OutputInterface $output, $sortColumnNumber = 1, $limit = 0)
119
    {
120
        $tableData['rows'] = self::sortRowsByColumnNumber($tableData['rows'], $sortColumnNumber);
121
122
        if ($limit && $limit < count($tableData['rows'])) {
123
            $tableData['rows'] = array_slice($tableData['rows'], 0, $limit);
124
        }
125
126
        $table = new Table($output);
127
        $table->setHeaders($tableData['headers']);
128
        $table->setRows($tableData['rows']);
129
        $table->addRow(new TableSeparator());
130
        if (isset($tableData['totals'])) {
131
            $table->addRow($tableData['totals']);
132
        }
133
        $table->render();
134
    }
135
}
136