Version 1
[yaffs-website] / vendor / consolidation / output-formatters / src / Transformations / ReorderFields.php
diff --git a/vendor/consolidation/output-formatters/src/Transformations/ReorderFields.php b/vendor/consolidation/output-formatters/src/Transformations/ReorderFields.php
new file mode 100644 (file)
index 0000000..ca1ee7c
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+namespace Consolidation\OutputFormatters\Transformations;
+
+use Symfony\Component\Finder\Glob;
+use Consolidation\OutputFormatters\Exception\UnknownFieldException;
+
+/**
+ * Reorder the field labels based on the user-selected fields
+ * to display.
+ */
+class ReorderFields
+{
+    /**
+     * Given a simple list of user-supplied field keys or field labels,
+     * return a reordered version of the field labels matching the
+     * user selection.
+     *
+     * @param string|array $fields The user-selected fields
+     * @param array $fieldLabels An associative array mapping the field
+     *   key to the field label
+     * @param array $data The data that will be rendered.
+     *
+     * @return array
+     */
+    public function reorder($fields, $fieldLabels, $data)
+    {
+        $firstRow = reset($data);
+        if (!$firstRow) {
+            $firstRow = $fieldLabels;
+        }
+        if (empty($fieldLabels) && !empty($data)) {
+            $fieldLabels = array_combine(array_keys($firstRow), array_map('ucfirst', array_keys($firstRow)));
+        }
+        $fields = $this->getSelectedFieldKeys($fields, $fieldLabels);
+        if (empty($fields)) {
+            return array_intersect_key($fieldLabels, $firstRow);
+        }
+        return $this->reorderFieldLabels($fields, $fieldLabels, $data);
+    }
+
+    protected function reorderFieldLabels($fields, $fieldLabels, $data)
+    {
+        $result = [];
+        $firstRow = reset($data);
+        if (!$firstRow) {
+            $firstRow = $fieldLabels;
+        }
+        foreach ($fields as $field) {
+            if (array_key_exists($field, $firstRow)) {
+                if (array_key_exists($field, $fieldLabels)) {
+                    $result[$field] = $fieldLabels[$field];
+                }
+            }
+        }
+        return $result;
+    }
+
+    protected function getSelectedFieldKeys($fields, $fieldLabels)
+    {
+        if (is_string($fields)) {
+            $fields = explode(',', $fields);
+        }
+        $selectedFields = [];
+        foreach ($fields as $field) {
+            $matchedFields = $this->matchFieldInLabelMap($field, $fieldLabels);
+            if (empty($matchedFields)) {
+                throw new UnknownFieldException($field);
+            }
+            $selectedFields = array_merge($selectedFields, $matchedFields);
+        }
+        return $selectedFields;
+    }
+
+    protected function matchFieldInLabelMap($field, $fieldLabels)
+    {
+        $fieldRegex = $this->convertToRegex($field);
+        return
+            array_filter(
+                array_keys($fieldLabels),
+                function ($key) use ($fieldRegex, $fieldLabels) {
+                    $value = $fieldLabels[$key];
+                    return preg_match($fieldRegex, $value) || preg_match($fieldRegex, $key);
+                }
+            );
+    }
+
+    /**
+     * Convert the provided string into a regex suitable for use in
+     * preg_match.
+     *
+     * Matching occurs in the same way as the Symfony Finder component:
+     * http://symfony.com/doc/current/components/finder.html#file-name
+     */
+    protected function convertToRegex($str)
+    {
+        return $this->isRegex($str) ? $str : Glob::toRegex($str);
+    }
+
+    /**
+     * Checks whether the string is a regex.  This function is copied from
+     * MultiplePcreFilterIterator in the Symfony Finder component.
+     *
+     * @param string $str
+     *
+     * @return bool Whether the given string is a regex
+     */
+    protected function isRegex($str)
+    {
+        if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
+            $start = substr($m[1], 0, 1);
+            $end = substr($m[1], -1);
+
+            if ($start === $end) {
+                return !preg_match('/[*?[:alnum:] \\\\]/', $start);
+            }
+
+            foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
+                if ($start === $delimiters[0] && $end === $delimiters[1]) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+}