Completed
Push — master ( ca5d76...923e5b )
by Stanislav
02:18
created

TableUtils::parseNumericFilter()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
rs 8.8571
cc 5
eloc 12
nc 2
nop 1
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
            switch ($filter['type']) {
22
                case 'numeric':
23
                    $filters[$columnKey] = self::parseNumericFilter($filter['value'])
24
                        + $filters[$columnKey];
25
                    break;
26
                case 'regex':
27
                    $filters[$columnKey] = self::parseRegexFilter($filter['value'])
28
                        + $filters[$columnKey];
29
                    break;
30
                default:
31
                    throw new \InvalidArgumentException('Unknown filter type');
32
            }
33
        }
34
        return $filters;
35
    }
36
37
    private static function parseNumericFilter($filterString)
38
    {
39
        $filter = [];
40
        preg_match_all('/([<>])\s?([\d\.]+)/', $filterString, $results, PREG_SET_ORDER);
41
        if ($results) {
42
            foreach ($results as $result) {
43
                $operator = $result[1];
44
                $value = $result[2];
45
                if ($operator == '<') {
46
                    $filter['max'] = $value;
47
                }
48
                if ($operator == '>') {
49
                    $filter['min'] = $value;
50
                }
51
            }
52
        }
53
        return $filter;
54
    }
55
56
    public static function parseRegexFilter($filterString)
57
    {
58
        $filter = [];
59
        $filter['regex'] = str_replace(['/', '.', '*'], ['\/', '\.', '.*?'], $filterString);
60
        return $filter;
61
    }
62
63
    public static function filterRows(array $rows, $filters)
64
    {
65
        $filters = self::parseFilters($filters);
66
67
        return array_filter($rows, function ($row) use ($filters) {
68
            foreach ($filters as $columnKey => $filter) {
69
                if (!isset($row[$columnKey])) {
70
                    continue;
71
                }
72
                $columnValue = $row[$columnKey];
73
74
                if (!self::filterRow($columnValue, $filter)) {
75
                    return false;
76
                }
77
            }
78
            return true;
79
        });
80
    }
81
82
    private static function filterRow($value, $filter)
83
    {
84
        if ($filter['type'] == 'numeric') {
85
            if ((isset($filter['min']) && $value <= $filter['min']) ||
86
                (isset($filter['max']) && $value >= $filter['max'])
87
            ) {
88
                return false;
89
            }
90
        }
91
92
        if ($filter['type'] == 'regex') {
93
            if (!preg_match('/' . $filter['regex'] . '/i', $value)) {
94
                return false;
95
            }
96
        }
97
98
        return true;
99
    }
100
101
    public static function sortRowsByColumnNumber(array $rows, $columnNumber)
102
    {
103
        $rowsSorted = $rows;
104
        $columnsTotal = count(end($rows));
105
106
        $sortOrder = $columnNumber > 0 ? 1 : -1;
107
108
        $columnIndex = max(1, min(
109
            $columnsTotal,
110
            abs($columnNumber)
111
        )) - 1;
112
113
        usort($rowsSorted, function ($first, $second) use ($columnIndex, $sortOrder) {
114
            return $first[$columnIndex] > $second[$columnIndex] ? $sortOrder : $sortOrder * -1;
115
        });
116
117
        return $rowsSorted;
118
    }
119
120
    public static function printTable(array $tableData, OutputInterface $output, $sortColumnNumber = 1, $limit = 0)
121
    {
122
        $tableData['rows'] = self::sortRowsByColumnNumber($tableData['rows'], $sortColumnNumber);
123
124
        if ($limit && $limit < count($tableData['rows'])) {
125
            $tableData['rows'] = array_slice($tableData['rows'], 0, $limit);
126
        }
127
128
        $table = new Table($output);
129
        $table->setHeaders($tableData['headers']);
130
        $table->setRows($tableData['rows']);
131
        $table->addRow(new TableSeparator());
132
        if (isset($tableData['totals'])) {
133
            $table->addRow($tableData['totals']);
134
        }
135
        $table->render();
136
    }
137
}
138