Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\views;
|
Chris@0
|
4
|
Chris@17
|
5 use Drupal\Component\Render\FormattableMarkup;
|
Chris@0
|
6
|
Chris@0
|
7 /**
|
Chris@0
|
8 * Defines a helper class for stuff related to views data.
|
Chris@0
|
9 */
|
Chris@0
|
10 class ViewsDataHelper {
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * The views data object, containing the cached information.
|
Chris@0
|
14 *
|
Chris@0
|
15 * @var \Drupal\views\ViewsData
|
Chris@0
|
16 */
|
Chris@0
|
17 protected $data;
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * A prepared list of all fields, keyed by base_table and handler type.
|
Chris@0
|
21 *
|
Chris@12
|
22 * @var array
|
Chris@0
|
23 */
|
Chris@0
|
24 protected $fields;
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Constructs a ViewsData object.
|
Chris@0
|
28 *
|
Chris@0
|
29 * @param \Drupal\views\ViewsData $views_data
|
Chris@0
|
30 * The views data object, containing the cached table information.
|
Chris@0
|
31 */
|
Chris@0
|
32 public function __construct(ViewsData $views_data) {
|
Chris@0
|
33 $this->data = $views_data;
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * Fetches a list of all fields available for a given base type.
|
Chris@0
|
38 *
|
Chris@0
|
39 * @param array|string $base
|
Chris@0
|
40 * A list or a single base_table, for example node.
|
Chris@0
|
41 * @param string $type
|
Chris@0
|
42 * The handler type, for example field or filter.
|
Chris@0
|
43 * @param bool $grouping
|
Chris@0
|
44 * Should the result grouping by its 'group' label.
|
Chris@0
|
45 * @param string $sub_type
|
Chris@0
|
46 * An optional sub type. E.g. Allows making an area plugin available for
|
Chris@0
|
47 * header only, instead of header, footer, and empty regions.
|
Chris@0
|
48 *
|
Chris@0
|
49 * @return array
|
Chris@0
|
50 * A keyed array of in the form of 'base_table' => 'Description'.
|
Chris@0
|
51 */
|
Chris@0
|
52 public function fetchFields($base, $type, $grouping = FALSE, $sub_type = NULL) {
|
Chris@0
|
53 if (!$this->fields) {
|
Chris@0
|
54 $data = $this->data->get();
|
Chris@0
|
55 // This constructs this ginormous multi dimensional array to
|
Chris@0
|
56 // collect the important data about fields. In the end,
|
Chris@0
|
57 // the structure looks a bit like this (using nid as an example)
|
Chris@0
|
58 // $strings['nid']['filter']['title'] = 'string'.
|
Chris@0
|
59 //
|
Chris@0
|
60 // This is constructed this way because the above referenced strings
|
Chris@0
|
61 // can appear in different places in the actual data structure so that
|
Chris@0
|
62 // the data doesn't have to be repeated a lot. This essentially lets
|
Chris@0
|
63 // each field have a cheap kind of inheritance.
|
Chris@0
|
64
|
Chris@0
|
65 foreach ($data as $table => $table_data) {
|
Chris@0
|
66 $bases = [];
|
Chris@0
|
67 $strings = [];
|
Chris@0
|
68 $skip_bases = [];
|
Chris@0
|
69 foreach ($table_data as $field => $info) {
|
Chris@0
|
70 // Collect table data from this table
|
Chris@0
|
71 if ($field == 'table') {
|
Chris@0
|
72 // calculate what tables this table can join to.
|
Chris@0
|
73 if (!empty($info['join'])) {
|
Chris@0
|
74 $bases = array_keys($info['join']);
|
Chris@0
|
75 }
|
Chris@0
|
76 // And it obviously joins to itself.
|
Chris@0
|
77 $bases[] = $table;
|
Chris@0
|
78 continue;
|
Chris@0
|
79 }
|
Chris@0
|
80 foreach (['field', 'sort', 'filter', 'argument', 'relationship', 'area'] as $key) {
|
Chris@0
|
81 if (!empty($info[$key])) {
|
Chris@0
|
82 if ($grouping && !empty($info[$key]['no group by'])) {
|
Chris@0
|
83 continue;
|
Chris@0
|
84 }
|
Chris@0
|
85 if ($sub_type && isset($info[$key]['sub_type']) && (!in_array($sub_type, (array) $info[$key]['sub_type']))) {
|
Chris@0
|
86 continue;
|
Chris@0
|
87 }
|
Chris@0
|
88 if (!empty($info[$key]['skip base'])) {
|
Chris@0
|
89 foreach ((array) $info[$key]['skip base'] as $base_name) {
|
Chris@0
|
90 $skip_bases[$field][$key][$base_name] = TRUE;
|
Chris@0
|
91 }
|
Chris@0
|
92 }
|
Chris@0
|
93 elseif (!empty($info['skip base'])) {
|
Chris@0
|
94 foreach ((array) $info['skip base'] as $base_name) {
|
Chris@0
|
95 $skip_bases[$field][$key][$base_name] = TRUE;
|
Chris@0
|
96 }
|
Chris@0
|
97 }
|
Chris@0
|
98 foreach (['title', 'group', 'help', 'base', 'aliases'] as $string) {
|
Chris@0
|
99 // First, try the lowest possible level
|
Chris@0
|
100 if (!empty($info[$key][$string])) {
|
Chris@0
|
101 $strings[$field][$key][$string] = $info[$key][$string];
|
Chris@0
|
102 }
|
Chris@0
|
103 // Then try the field level
|
Chris@0
|
104 elseif (!empty($info[$string])) {
|
Chris@0
|
105 $strings[$field][$key][$string] = $info[$string];
|
Chris@0
|
106 }
|
Chris@0
|
107 // Finally, try the table level
|
Chris@0
|
108 elseif (!empty($table_data['table'][$string])) {
|
Chris@0
|
109 $strings[$field][$key][$string] = $table_data['table'][$string];
|
Chris@0
|
110 }
|
Chris@0
|
111 // We don't have any help provided for this field. If a better
|
Chris@0
|
112 // description should be used for the Views UI you use
|
Chris@0
|
113 // hook_views_data_alter() in module.views.inc or implement a
|
Chris@0
|
114 // custom entity views_data handler.
|
Chris@0
|
115 // @see hook_views_data_alter()
|
Chris@0
|
116 // @see \Drupal\node\NodeViewsData
|
Chris@0
|
117 elseif ($string == 'help') {
|
Chris@0
|
118 $strings[$field][$key][$string] = '';
|
Chris@0
|
119 }
|
Chris@0
|
120 else {
|
Chris@0
|
121 if ($string != 'base') {
|
Chris@17
|
122 $strings[$field][$key][$string] = new FormattableMarkup("Error: missing @component", ['@component' => $string]);
|
Chris@0
|
123 }
|
Chris@0
|
124 }
|
Chris@0
|
125 }
|
Chris@0
|
126 }
|
Chris@0
|
127 }
|
Chris@0
|
128 }
|
Chris@0
|
129 foreach ($bases as $base_name) {
|
Chris@0
|
130 foreach ($strings as $field => $field_strings) {
|
Chris@0
|
131 foreach ($field_strings as $type_name => $type_strings) {
|
Chris@0
|
132 if (empty($skip_bases[$field][$type_name][$base_name])) {
|
Chris@0
|
133 $this->fields[$base_name][$type_name]["$table.$field"] = $type_strings;
|
Chris@0
|
134 }
|
Chris@0
|
135 }
|
Chris@0
|
136 }
|
Chris@0
|
137 }
|
Chris@0
|
138 }
|
Chris@0
|
139 }
|
Chris@0
|
140
|
Chris@0
|
141 // If we have an array of base tables available, go through them
|
Chris@0
|
142 // all and add them together. Duplicate keys will be lost and that's
|
Chris@0
|
143 // Just Fine.
|
Chris@0
|
144 if (is_array($base)) {
|
Chris@0
|
145 $strings = [];
|
Chris@0
|
146 foreach ($base as $base_table) {
|
Chris@0
|
147 if (isset($this->fields[$base_table][$type])) {
|
Chris@0
|
148 $strings += $this->fields[$base_table][$type];
|
Chris@0
|
149 }
|
Chris@0
|
150 }
|
Chris@0
|
151 uasort($strings, ['self', 'fetchedFieldSort']);
|
Chris@0
|
152 return $strings;
|
Chris@0
|
153 }
|
Chris@0
|
154
|
Chris@0
|
155 if (isset($this->fields[$base][$type])) {
|
Chris@0
|
156 uasort($this->fields[$base][$type], [$this, 'fetchedFieldSort']);
|
Chris@0
|
157 return $this->fields[$base][$type];
|
Chris@0
|
158 }
|
Chris@0
|
159 return [];
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 /**
|
Chris@0
|
163 * Sort function for fetched fields.
|
Chris@0
|
164 *
|
Chris@0
|
165 * @param array $a
|
Chris@0
|
166 * First item for comparison. The compared items should be associative arrays
|
Chris@0
|
167 * that include a 'group' and a 'title' key.
|
Chris@0
|
168 * @param array $b
|
Chris@0
|
169 * Second item for comparison.
|
Chris@0
|
170 *
|
Chris@0
|
171 * @return int
|
Chris@0
|
172 * Returns -1 if $a comes before $b, 1 other way round and 0 if it cannot be
|
Chris@0
|
173 * decided.
|
Chris@0
|
174 */
|
Chris@0
|
175 protected static function fetchedFieldSort($a, $b) {
|
Chris@17
|
176 $a_group = mb_strtolower($a['group']);
|
Chris@17
|
177 $b_group = mb_strtolower($b['group']);
|
Chris@0
|
178 if ($a_group != $b_group) {
|
Chris@0
|
179 return $a_group < $b_group ? -1 : 1;
|
Chris@0
|
180 }
|
Chris@0
|
181
|
Chris@17
|
182 $a_title = mb_strtolower($a['title']);
|
Chris@17
|
183 $b_title = mb_strtolower($b['title']);
|
Chris@0
|
184 if ($a_title != $b_title) {
|
Chris@0
|
185 return $a_title < $b_title ? -1 : 1;
|
Chris@0
|
186 }
|
Chris@0
|
187
|
Chris@0
|
188 return 0;
|
Chris@0
|
189 }
|
Chris@0
|
190
|
Chris@0
|
191 }
|