comparison core/modules/views/src/ViewsDataHelper.php @ 0:c75dbcec494b

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