Completed
Push — master ( 8473a4...434d21 )
by Greg
10s
created

ReorderFields::isRegex()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 0
cts 0
cp 0
rs 8.8571
cc 6
eloc 10
nc 4
nop 1
crap 42
1
<?php
2
namespace Consolidation\OutputFormatters\Transformations;
3
4
use Symfony\Component\Finder\Glob;
5
6
/**
7
 * Reorder the field labels based on the user-selected fields
8
 * to display.
9
 */
10
class ReorderFields
11
{
12
    /**
13
     * Given a simple list of user-supplied field keys or field labels,
14
     * return a reordered version of the field labels matching the
15
     * user selection.
16
     *
17
     * @param string|array $fields The user-selected fields
18
     * @param array $fieldLabels An associative array mapping the field
19
     *   key to the field label
20
     * @param array $data The data that will be rendered.
21
     *
22 7
     * @return array
23
     */
24 7
    public function reorder($fields, $fieldLabels, $data)
25 5
    {
26 5
        if (empty($fieldLabels) && !empty($data)) {
27 5
            $firstRow = reset($data);
28 7
            $fieldLabels = array_combine(array_keys($firstRow), array_map('ucfirst', array_keys($firstRow)));
29 7
        }
30 7
        $fields = $this->getSelectedFieldKeys($fields, $fieldLabels);
31
        if (empty($fields)) {
32 2
            return $fieldLabels;
33
        }
34
        return $this->reorderFieldLabels($fields, $fieldLabels, $data);
35 2
    }
36
37 2
    protected function reorderFieldLabels($fields, $fieldLabels, $data)
38 2
    {
39 2
        $result = [];
40 2
        $firstRow = reset($data);
41 2
        foreach ($fields as $field) {
42 2
            if (array_key_exists($field, $firstRow)) {
43 2
                if (array_key_exists($field, $fieldLabels)) {
44 2
                    $result[$field] = $fieldLabels[$field];
45 2
                }
46 2
            }
47
        }
48
        return $result;
49 7
    }
50
51 7
    protected function getSelectedFieldKeys($fields, $fieldLabels)
52 1
    {
53 1
        if (is_string($fields)) {
54 7
            $fields = explode(',', $fields);
55 7
        }
56 7
        $selectedFields = [];
57 2
        foreach ($fields as $field) {
58 2
            $matchedFields = $this->matchFieldInLabelMap($field, $fieldLabels);
59 2
            $selectedFields = array_merge($selectedFields, $matchedFields);
60 2
        }
61 2
        return $selectedFields;
62 7
    }
63 7
64
    protected function matchFieldInLabelMap($field, $fieldLabels)
65
    {
66
        $fieldRegex = $this->convertToRegex($field);
67
        return
68
            array_filter(
69
                array_keys($fieldLabels),
70
                function ($key) use ($fieldRegex, $fieldLabels) {
71
                    $value = $fieldLabels[$key];
72
                    return preg_match($fieldRegex, $value) || preg_match($fieldRegex, $key);
73
                }
74
            );
75
    }
76
77
    /**
78
     * Convert the provided string into a regex suitable for use in
79
     * preg_match.
80
     *
81
     * Matching occurs in the same way as the Symfony Finder component:
82
     * http://symfony.com/doc/current/components/finder.html#file-name
83
     */
84
    protected function convertToRegex($str)
85
    {
86
        return $this->isRegex($str) ? $str : Glob::toRegex($str);
87
    }
88
89
    /**
90
     * Checks whether the string is a regex.  This function is copied from
91
     * MultiplePcreFilterIterator in the Symfony Finder component.
92
     *
93
     * @param string $str
94
     *
95
     * @return bool Whether the given string is a regex
96
     */
97
    protected function isRegex($str)
98
    {
99
        if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
100
            $start = substr($m[1], 0, 1);
101
            $end = substr($m[1], -1);
102
103
            if ($start === $end) {
104
                return !preg_match('/[*?[:alnum:] \\\\]/', $start);
105
            }
106
107
            foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
108
                if ($start === $delimiters[0] && $end === $delimiters[1]) {
109
                    return true;
110
                }
111
            }
112
        }
113
114
        return false;
115
    }
116
}
117