| Commit | Line | Data |
|---|---|---|
| 8c89308c KN |
1 | <?php |
| 2 | ||
| 0cbf252c | 3 | /** |
| 4 | * @file | |
| 5 | * Relation endpoints field. | |
| 6 | */ | |
| 7 | ||
| df43f0b1 | 8 | /** |
| 9 | * Implements hook_field_info(). | |
| 10 | */ | |
| d21cffce | 11 | function relation_endpoint_field_info() { |
| 8c89308c KN |
12 | return array( |
| 13 | 'relation_endpoint' => array( | |
| 14 | 'label' => t('Relation endpoint'), | |
| 15 | 'description' => t('This field contains the endpoints of the relation'), | |
| 16 | 'default_widget' => 'relation_endpoint', | |
| 17 | 'default_formatter' => 'relation_endpoint', | |
| 18 | 'entity types' => array('relation'), | |
| a1ea1e19 | 19 | 'no_ui' => TRUE, |
| 8c89308c KN |
20 | ), |
| 21 | ); | |
| 22 | } | |
| 23 | ||
| df43f0b1 | 24 | /** |
| 25 | * Implements hook_field_validate(). | |
| 26 | */ | |
| d21cffce | 27 | function relation_endpoint_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { |
| eec23b0d | 28 | $relation_type = relation_type_load($entity->relation_type); |
| 29 | // Check that relation_type exists. | |
| 8c89308c | 30 | if (!$relation_type) { |
| e385f283 | 31 | $errors[] = array( |
| 32 | 'error' => 'relation_nonexistent_type', | |
| 322db8be | 33 | 'message' => t("The !relation_type relation type does not exist.", array('!relation_type' => $entity->relation_type)), |
| e385f283 | 34 | ); |
| 8c89308c | 35 | } |
| a654ce80 KN |
36 | // Check if the relation type is unique and if so, check if a relation between |
| 37 | // those items exist already. | |
| 322db8be | 38 | if ($relation_type->r_unique) { |
| a654ce80 KN |
39 | $rids = relation_relation_exists($items, $entity->relation_type); |
| 40 | if ($rids && (!isset($entity->rid) || !isset($rids[$entity->rid]))) { | |
| 322db8be KN |
41 | $errors[] = array( |
| 42 | 'error' => 'relation_already_exists', | |
| 43 | 'message' => t("The !relation_type is unique but the relation already exists.", array('!relation_type' => $entity->relation_type)), | |
| 44 | ); | |
| 45 | } | |
| 46 | } | |
| 8c89308c KN |
47 | // Check that arity is within acceptable bounds. |
| 48 | if (count($items) < $relation_type->min_arity && empty($entity->in_progress)) { | |
| e385f283 | 49 | $errors[] = array( |
| 50 | 'error' => 'relation_too_few_endpoints', | |
| 51 | 'message' => t("Relation has too few end points (:relation_type min arity :min_arity)", array(':relation_type' => $entity->relation_type, ':min_arity' => $relation_type->min_arity)), | |
| 52 | ); | |
| 8c89308c KN |
53 | } |
| 54 | if ($relation_type->max_arity && count($items) > $relation_type->max_arity) { | |
| e385f283 | 55 | $errors[] = array( |
| 56 | 'error' => 'relation_too_many_endpoints', | |
| 57 | 'message' => t("Relation has too many end points (:relation_type max arity :max_arity)", array(':relation_type' => $entity->relation_type, ':max_arity' => $relation_type->max_arity)), | |
| 58 | ); | |
| 8c89308c KN |
59 | } |
| 60 | //Check that each entity is has acceptable bundle type and index. | |
| 61 | foreach ($items as $delta => $item) { | |
| 62 | $acceptable = FALSE; | |
| 63 | $directional = $relation_type->directional; | |
| 64 | $endpoint = ($directional && ($delta > 0)) ? 'target' : 'source'; | |
| 65 | $end_bundles = $endpoint . '_bundles'; | |
| 66 | foreach ($relation_type->$end_bundles as $relation_bundle) { | |
| 67 | if (!isset($item['entity_bundle'])) { | |
| 135f9897 KN |
68 | $endpoint_entities = entity_load($item['entity_type'], array($item['entity_id'])); |
| 69 | $endpoint_entity = reset($endpoint_entities); | |
| 9c9094a8 | 70 | list(, , $item['entity_bundle']) = entity_extract_ids($item['entity_type'], $endpoint_entity); |
| 8c89308c KN |
71 | } |
| 72 | $relation_bundle_array = explode(':', $relation_bundle, 2); | |
| 73 | if (($relation_bundle == $item['entity_type'] . ':' . $item['entity_bundle']) || (($item['entity_type'] == $relation_bundle_array[0]) && ($relation_bundle_array[1] == '*'))) { | |
| 74 | $acceptable = TRUE; | |
| 75 | break; | |
| 76 | } | |
| 77 | } | |
| 78 | if (!$acceptable) { | |
| eec23b0d | 79 | $t_arguments = array('%relation_type' => $entity->relation_type, '@bundle' => $item['entity_bundle']); |
| 8c89308c KN |
80 | if ($relation_type->directional) { |
| 81 | if ($endpoint == 'target') { | |
| e385f283 | 82 | $errors[] = array( |
| 83 | 'error' => 'relation_unsupported_target', | |
| 84 | 'message' => t("The %relation_type relation type does not allow @bundle entities as target.", $t_arguments), | |
| 85 | ); | |
| 8c89308c KN |
86 | } |
| 87 | else { | |
| e385f283 | 88 | $errors[] = array( |
| 89 | 'error' => 'relation_unsupported_source', | |
| 90 | 'message' => t("The %relation_type relation type does not allow @bundle entities as source.", $t_arguments), | |
| 91 | ); | |
| 8c89308c KN |
92 | } |
| 93 | } | |
| 94 | else { | |
| e385f283 | 95 | $errors[] = array( |
| 96 | 'error' => 'relation_unsupported_endpoint', | |
| 97 | 'message' => t("The %relation_type relation type does not allow @bundle entities as an endpoint.", $t_arguments), | |
| 98 | ); | |
| 8c89308c KN |
99 | } |
| 100 | } | |
| 101 | } | |
| 102 | } | |
| 103 | ||
| feb3e358 KN |
104 | /** |
| 105 | * Implements hook_field_presave(). | |
| 106 | */ | |
| d21cffce | 107 | function relation_endpoint_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) { |
| feb3e358 | 108 | // We need r_index here because EntityFieldQuery can't query on deltas. |
| 8c89308c KN |
109 | foreach ($items as $delta => &$item) { |
| 110 | $item['r_index'] = $delta; | |
| 111 | } | |
| 112 | } | |
| 113 | ||
| 114 | /** | |
| 115 | * Implements hook_field_update(). | |
| 116 | */ | |
| d21cffce | 117 | function relation_endpoint_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) { |
| 8c89308c KN |
118 | // We do not update. |
| 119 | } | |
| 120 | ||
| 121 | /** | |
| 122 | * Implements hook_field_is_empty(). | |
| 123 | */ | |
| d21cffce | 124 | function relation_endpoint_field_is_empty($item, $field) { |
| 8c89308c KN |
125 | // We are never empty. |
| 126 | return FALSE; | |
| 127 | } | |
| 128 | ||
| feb3e358 KN |
129 | /** |
| 130 | * Helper to create an HTML table representing a relation. | |
| 131 | */ | |
| d21cffce | 132 | function _relation_endpoint_field_create_html_table($endpoints) { |
| 8c89308c | 133 | $list_items = array(); |
| feb3e358 KN |
134 | foreach ($endpoints as $delta => $endpoint) { |
| 135 | $entities = entity_load($endpoint['entity_type'], array($endpoint['entity_id'])); | |
| 8c89308c | 136 | $entity = reset($entities); |
| feb3e358 KN |
137 | $label = entity_label($endpoint['entity_type'], $entity); |
| 138 | $uri = entity_uri($endpoint['entity_type'], $entity); | |
| 139 | $list_items[$delta] = array(l($label, $uri['path'], $uri['options']), $endpoint['entity_type']); | |
| 8c89308c | 140 | } |
| 189bccd7 KN |
141 | $headers = array( |
| 142 | 'Entity', | |
| 143 | array('width' => '22%', 'data' => 'Entity_type'), | |
| 144 | ); | |
| 8c89308c KN |
145 | return array( |
| 146 | '#theme' => 'table', | |
| 8c89308c KN |
147 | '#header' => $headers, |
| 148 | '#rows' => $list_items, | |
| 149 | ); | |
| 150 | } | |
| 151 | ||
| df43f0b1 | 152 | /** |
| edf9822d | 153 | * Implements hook_field_widget_info(). |
| df43f0b1 | 154 | */ |
| edf9822d | 155 | function relation_endpoint_field_widget_info() { |
| 8c89308c KN |
156 | return array( |
| 157 | 'relation_endpoint' => array( | |
| a1ea1e19 KN |
158 | 'label' => t('Endpoints table'), |
| 159 | 'field types' => array('relation_endpoint'), | |
| edf9822d KN |
160 | 'behaviors' => array( |
| 161 | 'multiple values' => FIELD_BEHAVIOR_CUSTOM, | |
| 162 | ), | |
| 61461a15 | 163 | ), |
| 8c89308c KN |
164 | ); |
| 165 | } | |
| 166 | ||
| df43f0b1 | 167 | /** |
| edf9822d | 168 | * Implements hook_field_formatter_info(). |
| df43f0b1 | 169 | */ |
| edf9822d KN |
170 | function relation_endpoint_field_formatter_info() { |
| 171 | $info = array( | |
| 8c89308c | 172 | 'relation_endpoint' => array( |
| a1ea1e19 KN |
173 | 'label' => t('Endpoints table'), |
| 174 | 'field types' => array('relation_endpoint'), | |
| edf9822d KN |
175 | ), |
| 176 | 'relation_endpoint_full' => array( | |
| 177 | 'label' => t('Full entities list'), | |
| 178 | 'field types' => array('relation_endpoint'), | |
| e012f5e6 | 179 | ), |
| 8c89308c | 180 | ); |
| edf9822d KN |
181 | foreach (entity_get_info() as $entity_type => $data) { |
| 182 | $info['relation_endpoint_full']['settings']['view_modes'][$entity_type] = 'default'; | |
| 183 | } | |
| 184 | return $info; | |
| 185 | } | |
| 186 | ||
| 187 | /** | |
| 188 | * Implements hook_field_formatter_settings_form(). | |
| 189 | */ | |
| 190 | function relation_endpoint_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) { | |
| 191 | $view_modes_settings = $instance['display'][$view_mode]['settings']['view_modes']; | |
| 192 | foreach (_relation_endpoint_get_endpoint_entity_types($instance) as $endpoint_entity_type => $v) { | |
| 193 | $entity_info = entity_get_info($endpoint_entity_type); | |
| 194 | $options = array(); | |
| 195 | foreach ($entity_info['view modes'] as $entity_view_mode => $data) { | |
| 196 | $options[$entity_view_mode] = $data['label']; | |
| 197 | } | |
| 7c99466d KN |
198 | $element['#tree'] = TRUE; |
| 199 | $element['view_modes'][$endpoint_entity_type] = array( | |
| edf9822d KN |
200 | '#title' => t('@endpoint_entity_type view mode', array('@endpoint_entity_type' => $endpoint_entity_type)), |
| 201 | '#type' => 'select', | |
| 202 | '#default_value' => $view_modes_settings[$endpoint_entity_type], | |
| 203 | '#options' => $options, | |
| 204 | ); | |
| 205 | } | |
| 206 | return $element; | |
| 207 | } | |
| 208 | ||
| 209 | /** | |
| 210 | * Implements hook_field_formatter_settings_summary(). | |
| 211 | */ | |
| 212 | function relation_endpoint_field_formatter_settings_summary($field, $instance, $view_mode) { | |
| 213 | $view_modes_settings = $instance['display'][$view_mode]['settings']['view_modes']; | |
| 214 | foreach (_relation_endpoint_get_endpoint_entity_types($instance) as $endpoint_entity_type => $v) { | |
| 215 | $items[] = "$endpoint_entity_type: " . $view_modes_settings[$endpoint_entity_type]; | |
| 216 | } | |
| 217 | return theme('item_list', array('items' => $items)); | |
| 218 | } | |
| 219 | ||
| 220 | /** | |
| 221 | * Helper getting endpoint entity types for the bundle specified in $instance. | |
| 222 | */ | |
| 223 | function _relation_endpoint_get_endpoint_entity_types($instance) { | |
| 224 | $relation_type = relation_type_load($instance['bundle']); | |
| 225 | $bundles = $relation_type->source_bundles + $relation_type->target_bundles; | |
| 226 | foreach ($bundles as $bundle_key) { | |
| 227 | list($endpoint_entity_type) = explode(':', $bundle_key); | |
| 228 | $endpoint_entity_types[$endpoint_entity_type] = TRUE; | |
| 229 | } | |
| 230 | return $endpoint_entity_types; | |
| 8c89308c KN |
231 | } |
| 232 | ||
| df43f0b1 | 233 | /** |
| 234 | * Implements hook_field_formatter_view(). | |
| 235 | */ | |
| d21cffce | 236 | function relation_endpoint_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { |
| 61461a15 KN |
237 | switch ($display['type']) { |
| 238 | case 'relation_endpoint': | |
| 02a386ac | 239 | $build['table'] = _relation_endpoint_field_create_html_table($items); |
| 61461a15 | 240 | case 'relation_endpoint_full': |
| edf9822d | 241 | $view_modes_settings = $display['settings']['view_modes']; |
| 61461a15 KN |
242 | $list_items = array(); |
| 243 | $endpoint_entity_type = ''; | |
| 244 | $multiple = TRUE; | |
| 245 | foreach ($items as $delta => $endpoint) { | |
| 246 | if (!$endpoint_entity_type) { | |
| 247 | $endpoint_entity_type = $endpoint['entity_type']; | |
| 248 | } | |
| 249 | if ($endpoint_entity_type == $endpoint['entity_type']) { | |
| 250 | $entity_ids[] = $endpoint['entity_id']; | |
| 251 | } | |
| 252 | else { | |
| 253 | $multiple = FALSE; | |
| 254 | break; | |
| 255 | } | |
| 256 | } | |
| 61461a15 KN |
257 | if ($multiple) { |
| 258 | $entities = entity_load($endpoint_entity_type, $entity_ids); | |
| edf9822d | 259 | if (function_exists('entity_view')) { |
| d155ee9f | 260 | return array(entity_view($endpoint_entity_type, $entities, $view_modes_settings[$endpoint_entity_type])); |
| edf9822d KN |
261 | } |
| 262 | $function = $endpoint_entity_type . '_view_multiple'; | |
| 61461a15 | 263 | if (function_exists($function)) { |
| edf9822d | 264 | return array($function($entities, $view_modes_settings[$endpoint_entity_type])); |
| 61461a15 KN |
265 | } |
| 266 | } | |
| 267 | $build = array(); | |
| 268 | $function = $endpoint_entity_type . '_view'; | |
| 269 | foreach ($endpoints as $delta => $endpoint) { | |
| 270 | if ($multiple) { | |
| 271 | $entity = $entities[$endpoint['entity_id']]; | |
| 272 | } | |
| 273 | else { | |
| 274 | $entities = entity_load($endpoint['entity_type'], array($endpoint['entity_id'])); | |
| 275 | $entity = reset($entities); | |
| 276 | } | |
| edf9822d | 277 | $build[$delta] = $function($entity, $view_modes_settings[$endpoint_entity_type]); |
| 61461a15 | 278 | } |
| 61461a15 | 279 | } |
| 02a386ac | 280 | return $build; |
| 8c89308c KN |
281 | } |
| 282 | ||
| df43f0b1 | 283 | /** |
| 284 | * Implements hook_field_widget_form(). | |
| 285 | */ | |
| d21cffce | 286 | function relation_endpoint_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { |
| 8c89308c KN |
287 | foreach ($items as $delta => $item) { |
| 288 | foreach (array('entity_type', 'entity_id') as $column) { | |
| 289 | $element[$delta][$column] = array( | |
| 290 | '#type' => 'value', | |
| 291 | '#value' => $item[$column], | |
| 292 | ); | |
| 293 | } | |
| 294 | } | |
| d21cffce | 295 | $element['link_list'] = _relation_endpoint_field_create_html_table($items); |
| 8c89308c KN |
296 | return $element; |
| 297 | } | |
| a1ea1e19 KN |
298 | |
| 299 | /** | |
| 300 | * Implements hook_form_field_ui_field_overview_form_alter(). | |
| 301 | */ | |
| d21cffce | 302 | function relation_endpoint_form_field_ui_field_overview_form_alter(&$form, $form_state) { |
| a1ea1e19 KN |
303 | // Deleting endpoints would make the module useless. |
| 304 | if ($form['#entity_type'] == 'relation') { | |
| 305 | $form['fields']['endpoints']['delete'] = array( | |
| 306 | '#type' => 'markup', | |
| 307 | '#markup' => ' ', | |
| 308 | ); | |
| 309 | } | |
| 310 | } |