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