annotate vendor/consolidation/output-formatters/src/Transformations/ReorderFields.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 4c8ae668cc8c
children
rev   line source
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@17 60 if (empty($fieldLabels)) {
Chris@17 61 return [];
Chris@17 62 }
Chris@0 63 if (is_string($fields)) {
Chris@0 64 $fields = explode(',', $fields);
Chris@0 65 }
Chris@0 66 $selectedFields = [];
Chris@0 67 foreach ($fields as $field) {
Chris@0 68 $matchedFields = $this->matchFieldInLabelMap($field, $fieldLabels);
Chris@0 69 if (empty($matchedFields)) {
Chris@0 70 throw new UnknownFieldException($field);
Chris@0 71 }
Chris@0 72 $selectedFields = array_merge($selectedFields, $matchedFields);
Chris@0 73 }
Chris@0 74 return $selectedFields;
Chris@0 75 }
Chris@0 76
Chris@0 77 protected function matchFieldInLabelMap($field, $fieldLabels)
Chris@0 78 {
Chris@0 79 $fieldRegex = $this->convertToRegex($field);
Chris@0 80 return
Chris@0 81 array_filter(
Chris@0 82 array_keys($fieldLabels),
Chris@0 83 function ($key) use ($fieldRegex, $fieldLabels) {
Chris@0 84 $value = $fieldLabels[$key];
Chris@0 85 return preg_match($fieldRegex, $value) || preg_match($fieldRegex, $key);
Chris@0 86 }
Chris@0 87 );
Chris@0 88 }
Chris@0 89
Chris@0 90 /**
Chris@0 91 * Convert the provided string into a regex suitable for use in
Chris@0 92 * preg_match.
Chris@0 93 *
Chris@0 94 * Matching occurs in the same way as the Symfony Finder component:
Chris@0 95 * http://symfony.com/doc/current/components/finder.html#file-name
Chris@0 96 */
Chris@0 97 protected function convertToRegex($str)
Chris@0 98 {
Chris@0 99 return $this->isRegex($str) ? $str : Glob::toRegex($str);
Chris@0 100 }
Chris@0 101
Chris@0 102 /**
Chris@0 103 * Checks whether the string is a regex. This function is copied from
Chris@0 104 * MultiplePcreFilterIterator in the Symfony Finder component.
Chris@0 105 *
Chris@0 106 * @param string $str
Chris@0 107 *
Chris@0 108 * @return bool Whether the given string is a regex
Chris@0 109 */
Chris@0 110 protected function isRegex($str)
Chris@0 111 {
Chris@0 112 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
Chris@0 113 $start = substr($m[1], 0, 1);
Chris@0 114 $end = substr($m[1], -1);
Chris@0 115
Chris@0 116 if ($start === $end) {
Chris@0 117 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
Chris@0 118 }
Chris@0 119
Chris@0 120 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
Chris@0 121 if ($start === $delimiters[0] && $end === $delimiters[1]) {
Chris@0 122 return true;
Chris@0 123 }
Chris@0 124 }
Chris@0 125 }
Chris@0 126
Chris@0 127 return false;
Chris@0 128 }
Chris@0 129 }