Chris@0: data = $views_data; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Fetches a list of all fields available for a given base type. Chris@0: * Chris@0: * @param array|string $base Chris@0: * A list or a single base_table, for example node. Chris@0: * @param string $type Chris@0: * The handler type, for example field or filter. Chris@0: * @param bool $grouping Chris@0: * Should the result grouping by its 'group' label. Chris@0: * @param string $sub_type Chris@0: * An optional sub type. E.g. Allows making an area plugin available for Chris@0: * header only, instead of header, footer, and empty regions. Chris@0: * Chris@0: * @return array Chris@0: * A keyed array of in the form of 'base_table' => 'Description'. Chris@0: */ Chris@0: public function fetchFields($base, $type, $grouping = FALSE, $sub_type = NULL) { Chris@0: if (!$this->fields) { Chris@0: $data = $this->data->get(); Chris@0: // This constructs this ginormous multi dimensional array to Chris@0: // collect the important data about fields. In the end, Chris@0: // the structure looks a bit like this (using nid as an example) Chris@0: // $strings['nid']['filter']['title'] = 'string'. Chris@0: // Chris@0: // This is constructed this way because the above referenced strings Chris@0: // can appear in different places in the actual data structure so that Chris@0: // the data doesn't have to be repeated a lot. This essentially lets Chris@0: // each field have a cheap kind of inheritance. Chris@0: Chris@0: foreach ($data as $table => $table_data) { Chris@0: $bases = []; Chris@0: $strings = []; Chris@0: $skip_bases = []; Chris@0: foreach ($table_data as $field => $info) { Chris@0: // Collect table data from this table Chris@0: if ($field == 'table') { Chris@0: // calculate what tables this table can join to. Chris@0: if (!empty($info['join'])) { Chris@0: $bases = array_keys($info['join']); Chris@0: } Chris@0: // And it obviously joins to itself. Chris@0: $bases[] = $table; Chris@0: continue; Chris@0: } Chris@0: foreach (['field', 'sort', 'filter', 'argument', 'relationship', 'area'] as $key) { Chris@0: if (!empty($info[$key])) { Chris@0: if ($grouping && !empty($info[$key]['no group by'])) { Chris@0: continue; Chris@0: } Chris@0: if ($sub_type && isset($info[$key]['sub_type']) && (!in_array($sub_type, (array) $info[$key]['sub_type']))) { Chris@0: continue; Chris@0: } Chris@0: if (!empty($info[$key]['skip base'])) { Chris@0: foreach ((array) $info[$key]['skip base'] as $base_name) { Chris@0: $skip_bases[$field][$key][$base_name] = TRUE; Chris@0: } Chris@0: } Chris@0: elseif (!empty($info['skip base'])) { Chris@0: foreach ((array) $info['skip base'] as $base_name) { Chris@0: $skip_bases[$field][$key][$base_name] = TRUE; Chris@0: } Chris@0: } Chris@0: foreach (['title', 'group', 'help', 'base', 'aliases'] as $string) { Chris@0: // First, try the lowest possible level Chris@0: if (!empty($info[$key][$string])) { Chris@0: $strings[$field][$key][$string] = $info[$key][$string]; Chris@0: } Chris@0: // Then try the field level Chris@0: elseif (!empty($info[$string])) { Chris@0: $strings[$field][$key][$string] = $info[$string]; Chris@0: } Chris@0: // Finally, try the table level Chris@0: elseif (!empty($table_data['table'][$string])) { Chris@0: $strings[$field][$key][$string] = $table_data['table'][$string]; Chris@0: } Chris@0: // We don't have any help provided for this field. If a better Chris@0: // description should be used for the Views UI you use Chris@0: // hook_views_data_alter() in module.views.inc or implement a Chris@0: // custom entity views_data handler. Chris@0: // @see hook_views_data_alter() Chris@0: // @see \Drupal\node\NodeViewsData Chris@0: elseif ($string == 'help') { Chris@0: $strings[$field][$key][$string] = ''; Chris@0: } Chris@0: else { Chris@0: if ($string != 'base') { Chris@17: $strings[$field][$key][$string] = new FormattableMarkup("Error: missing @component", ['@component' => $string]); Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: foreach ($bases as $base_name) { Chris@0: foreach ($strings as $field => $field_strings) { Chris@0: foreach ($field_strings as $type_name => $type_strings) { Chris@0: if (empty($skip_bases[$field][$type_name][$base_name])) { Chris@0: $this->fields[$base_name][$type_name]["$table.$field"] = $type_strings; Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: // If we have an array of base tables available, go through them Chris@0: // all and add them together. Duplicate keys will be lost and that's Chris@0: // Just Fine. Chris@0: if (is_array($base)) { Chris@0: $strings = []; Chris@0: foreach ($base as $base_table) { Chris@0: if (isset($this->fields[$base_table][$type])) { Chris@0: $strings += $this->fields[$base_table][$type]; Chris@0: } Chris@0: } Chris@0: uasort($strings, ['self', 'fetchedFieldSort']); Chris@0: return $strings; Chris@0: } Chris@0: Chris@0: if (isset($this->fields[$base][$type])) { Chris@0: uasort($this->fields[$base][$type], [$this, 'fetchedFieldSort']); Chris@0: return $this->fields[$base][$type]; Chris@0: } Chris@0: return []; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Sort function for fetched fields. Chris@0: * Chris@0: * @param array $a Chris@0: * First item for comparison. The compared items should be associative arrays Chris@0: * that include a 'group' and a 'title' key. Chris@0: * @param array $b Chris@0: * Second item for comparison. Chris@0: * Chris@0: * @return int Chris@0: * Returns -1 if $a comes before $b, 1 other way round and 0 if it cannot be Chris@0: * decided. Chris@0: */ Chris@0: protected static function fetchedFieldSort($a, $b) { Chris@17: $a_group = mb_strtolower($a['group']); Chris@17: $b_group = mb_strtolower($b['group']); Chris@0: if ($a_group != $b_group) { Chris@0: return $a_group < $b_group ? -1 : 1; Chris@0: } Chris@0: Chris@17: $a_title = mb_strtolower($a['title']); Chris@17: $b_title = mb_strtolower($b['title']); Chris@0: if ($a_title != $b_title) { Chris@0: return $a_title < $b_title ? -1 : 1; Chris@0: } Chris@0: Chris@0: return 0; Chris@0: } Chris@0: Chris@0: }