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