entity_from_field.inc
9.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<?php
/**
* @file
* Plugin to provide an relationship handler for an entity from a field.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
'title' => t('Entity'),
'description' => t('Creates an entity context from a foreign key on a field.'),
'context' => 'ctools_entity_from_field_context',
'edit form' => 'ctools_entity_from_field_edit_form',
'get child' => 'ctools_entity_from_field_get_child',
'get children' => 'ctools_entity_from_field_get_children',
'defaults' => array('delta' => 0),
);
function ctools_entity_from_field_get_child($plugin, $parent, $child) {
$plugins = ctools_entity_from_field_get_children($plugin, $parent);
return $plugins[$parent . ':' . $child];
}
function ctools_entity_from_field_get_children($parent_plugin, $parent) {
$cid = $parent_plugin['name'] . ':' . $parent;
$cache = &drupal_static(__FUNCTION__);
if (!empty($cache[$cid])) {
return $cache[$cid];
}
ctools_include('fields');
$entities = entity_get_info();
$plugins = array();
$context_types = array();
// Get the schema information for every field.
$fields_info = field_info_fields();
foreach ($fields_info as $field_name => $field) {
foreach ($field['bundles'] as $from_entity => $bundles) {
foreach ($bundles as $bundle) {
// There might be fields attached to bundles that are disabled (e.g. a
// module that declared a node's content type, is now disabled), but the
// field instance is still shown.
if (!empty($entities[$from_entity]['bundles'][$bundle])) {
$foreign_keys = ctools_field_foreign_keys($field_name);
foreach ($foreign_keys as $key => $info) {
if (isset($info['table'])) {
foreach ($entities as $to_entity => $to_entity_info) {
$from_entity_info = $entities[$from_entity];
// If somehow the bundle doesn't exist on the to-entity,
// skip.
if (!isset($from_entity_info['bundles'][$bundle])) {
continue;
}
if (isset($to_entity_info['base table']) && $to_entity_info['base table'] == $info['table'] && array_keys($info['columns'], $to_entity_info['entity keys']['id'])) {
$name = $field_name . '-' . $from_entity . '-' . $to_entity;
$plugin_id = $parent . ':' . $name;
// Record the bundle for later.
$context_types[$plugin_id]['types'][$bundle] = $from_entity_info['bundles'][$bundle]['label'];
// We check for every bundle; this plugin may already have
// been created, so don't recreate it.
if (!isset($plugins[$plugin_id])) {
$plugin = $parent_plugin;
$replacements = array(
'@to_entity' => $to_entity_info['label'],
'@from_entity' => $from_entity_info['label'],
'@field_name' => $field_name,
'@field_label' => ctools_field_label($field_name),
);
$plugin['title'] = t('@to_entity from @from_entity (on @from_entity: @field_label [@field_name])', $replacements);
$plugin['keyword'] = $to_entity;
$plugin['context name'] = $name;
$plugin['name'] = $plugin_id;
$plugin['description'] = t('Creates a @to_entity context from @from_entity using the @field_name field on @from_entity.', $replacements);
$plugin['from entity'] = $from_entity;
$plugin['to entity'] = $to_entity;
$plugin['field name'] = $field_name;
$plugin['join key'] = $key;
$plugin['source key'] = current(array_keys($info['columns']));
$plugin['parent'] = $parent;
$plugins[$plugin_id] = $plugin;
/*
-- commented out until I figure out how to actually load the reverse properly.
// Build the reverse
$plugin = $parent_plugin;
$name = $field_name . '-' . $from_entity . '-' . $to_entity . '-reverse';
$plugin_id = $parent . ':' . $name;
$plugin['title'] = t('@from_entity from @to_entity (on @from_entity: @field_name)', $replacements);
$plugin['keyword'] = $to_entity;
$plugin['context name'] = $name;
$plugin['name'] = $plugin_id;
$plugin['description'] = t('Creates a @from_entity context from @to_entity using the @field_name field on @from_entity.', $replacements);
$plugin['from entity'] = $from_entity;
$plugin['to entity'] = $to_entity;
$plugin['field name'] = $field_name;
$plugin['reverse'] = TRUE;
$plugin['parent'] = $parent;
// Since we can't apply restrictions on the reverse relationship
// we just add the required context here.
$plugin['required context'] = new ctools_context_required($to_entity_info['label'], $to_entity);
$plugin_entities = array(
'to' => array($from_entity => $from_entity_info),
'from' => array($to_entity => $to_entity_info)
);
drupal_alter('ctools_entity_context', $plugin, $plugin_entities, $plugin_id);
$plugins[$plugin_id] = $plugin;
*/
}
}
}
}
}
}
}
}
}
foreach ($context_types as $key => $context) {
list($parent, $plugin_name) = explode(':', $key);
list($field_name, $from_entity, $to_entity) = explode('-', $plugin_name);
$from_entity_info = $entities[$from_entity];
$to_entity_info = $entities[$to_entity];
$plugins[$key]['required context'] = new ctools_context_required($from_entity_info['label'], $from_entity, array('type' => array_keys($context['types'])));
$plugin_entities = array(
'to' => array($to_entity => $to_entity_info),
'from' => array($from_entity => $from_entity_info)
);
drupal_alter('ctools_entity_context', $plugins[$key], $plugin_entities, $key);
}
drupal_alter('ctools_entity_contexts', $plugins);
$cache[$cid] = $plugins;
return $plugins;
}
/**
* Return a new context based on an existing context.
*/
function ctools_entity_from_field_context($context, $conf) {
$delta = !empty($conf['delta']) ? intval($conf['delta']) : 0;
$plugin = $conf['name'];
list($plugin, $plugin_name) = explode(':', $plugin);
list($field_name, $from_entity, $to_entity) = explode('-', $plugin_name);
// If unset it wants a generic, unfilled context, which is just NULL.
$entity_info = entity_get_info($from_entity);
if (empty($context->data) || !isset($context->data->{$entity_info['entity keys']['id']})) {
return ctools_context_create_empty('entity:' . $to_entity, NULL);
}
if (isset($context->data->{$entity_info['entity keys']['id']})) {
// Load the entity.
$id = $context->data->{$entity_info['entity keys']['id']};
$entity = entity_load($from_entity, array($id));
$entity = $entity[$id];
if ($items = field_get_items($from_entity, $entity, $field_name)) {
if (isset($items[$delta])) {
ctools_include('fields');
$to_entity_info = entity_get_info($to_entity);
$plugin_info = ctools_get_relationship($conf['name']);
$to_entity_id = $items[$delta][$plugin_info['source key']];
$loaded_to_entity = array_shift(entity_load($to_entity, array($to_entity_id)));
if(function_exists($to_entity_info['access callback']) && !call_user_func($to_entity_info['access callback'], 'view', $loaded_to_entity)) {
return ctools_context_create_empty('entity:' . $to_entity, NULL);
}
else {
// Send it to ctools.
return ctools_context_create('entity:' . $to_entity, $to_entity_id);
}
}
else {
// In case that delta was empty.
return ctools_context_create_empty('entity:' . $to_entity, NULL);
}
}
}
}
function ctools_entity_from_field_edit_form($form, &$form_state) {
$field = field_info_field($form_state['plugin']['field name']);
$conf = $form_state['conf'];
if ($field && $field['cardinality'] != 1) {
if ($field['cardinality'] == -1) {
$form['delta'] = array(
'#type' => 'textfield',
'#title' => t('Delta'),
'#description' => t('The relationship can only create one context, but multiple items can be related. Please select which one. Since this can have unlimited items, type in the number you want. The first one will be 0.'),
'#default_value' => !empty($conf['delta']) ? $conf['delta'] : 0,
);
}
else {
$form['delta'] = array(
'#type' => 'select',
'#title' => t('Delta'),
'#description' => t('The relationship can only create one context, but multiple items can be related. Please select which one.'),
'#options' => range(1, $field['cardinality']),
'#default_value' => !empty($conf['delta']) ? $conf['delta'] : 0,
);
}
}
return $form;
}