Completed
Push — master ( e9edfd...c93d1e )
by Stanislav
02:14
created

TableUtils::parseFilter()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 26
rs 8.439
cc 5
eloc 19
nc 4
nop 2
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[$columnKey] = 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
                        $operatorMap = [
37
                            '<' => 'max',
38
                            '>' => 'min',
39
                            '=' => 'equals',
40
                        ];
41
                        $filterCondition = $operatorMap[$operator];
42
                        $filter[$filterCondition] = $value;
43
                    }
44
                }
45
                return $filter;
46
47
            case 'regex':
48
                return ['regex' => str_replace(['/', '.', '*'], ['\/', '\.', '.*?'], $filterString)];
49
        }
50
        throw new \InvalidArgumentException('Unknown filter type');
51
    }
52
53
    public static function filterRows(array $rows, $filters)
54
    {
55
        $filters = self::parseFilters($filters);
56
57
        return array_filter($rows, function ($row) use ($filters) {
58
            foreach ($filters as $columnKey => $filter) {
59
                if (!isset($row[$columnKey])) {
60
                    continue;
61
                }
62
                $columnValue = $row[$columnKey];
63
64
                if (!self::filterRow($columnValue, $filter)) {
65
                    return false;
66
                }
67
            }
68
            return true;
69
        });
70
    }
71
72
    private static function filterRow($value, $filter)
73
    {
74
        if ((isset($filter['min']) && $value <= $filter['min']) ||
75
            (isset($filter['max']) && $value >= $filter['max']) ||
76
            (isset($filter['equals']) && $value != $filter['equals']) ||
77
            (isset($filter['regex']) && !preg_match('/' . $filter['regex'] . '/i', $value))
78
        ) {
79
            return false;
80
        }
81
82
        return true;
83
    }
84
85
    public static function sortRowsByColumnNumber(array $rows, $columnNumber)
86
    {
87
        $rowsSorted = $rows;
88
        $columnsTotal = count(end($rows));
89
90
        $sortOrder = $columnNumber > 0 ? 1 : -1;
91
92
        $columnIndex = max(1, min(
93
            $columnsTotal,
94
            abs($columnNumber)
95
        )) - 1;
96
97
        usort($rowsSorted, function ($first, $second) use ($columnIndex, $sortOrder) {
98
            return $first[$columnIndex] > $second[$columnIndex] ? $sortOrder : $sortOrder * -1;
99
        });
100
101
        return $rowsSorted;
102
    }
103
104
    public static function printTable(array $tableData, OutputInterface $output, $sortColumnNumber = 1, $limit = 0)
105
    {
106
        $tableData['rows'] = self::sortRowsByColumnNumber($tableData['rows'], $sortColumnNumber);
107
108
        if ($limit && $limit < count($tableData['rows'])) {
109
            $tableData['rows'] = array_slice($tableData['rows'], 0, $limit);
110
        }
111
112
        $table = new Table($output);
113
        $table->setHeaders($tableData['headers']);
114
        $table->setRows($tableData['rows']);
115
        $table->addRow(new TableSeparator());
116
        if (isset($tableData['totals'])) {
117
            $table->addRow($tableData['totals']);
118
        }
119
        $table->render();
120
    }
121
}
122