array( 'label' => t('Relation endpoint'), 'description' => t('This field contains the endpoints of the relation'), 'default_widget' => 'relation_endpoint', 'default_formatter' => 'relation_endpoint', 'entity types' => array('relation'), 'no_ui' => TRUE, ), ); } /** * Implements hook_field_validate(). */ function relation_endpoint_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { $relation_type = relation_type_load($entity->relation_type); // Check that relation_type exists. if (!$relation_type) { $errors[] = array( 'error' => 'relation_nonexistent_type', 'message' => t("The !relation_type relation type does not exist.", array('!relation_type' => $entity->relation_type)), ); } // Check for unique flag. if ($relation_type->r_unique) { if (relation_relation_exists($items, $relation_type->relation_type)) { $errors[] = array( 'error' => 'relation_already_exists', 'message' => t("The !relation_type is unique but the relation already exists.", array('!relation_type' => $entity->relation_type)), ); } } // Check that arity is within acceptable bounds. if (count($items) < $relation_type->min_arity && empty($entity->in_progress)) { $errors[] = array( 'error' => 'relation_too_few_endpoints', '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)), ); } if ($relation_type->max_arity && count($items) > $relation_type->max_arity) { $errors[] = array( 'error' => 'relation_too_many_endpoints', '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)), ); } //Check that each entity is has acceptable bundle type and index. foreach ($items as $delta => $item) { $acceptable = FALSE; $directional = $relation_type->directional; $endpoint = ($directional && ($delta > 0)) ? 'target' : 'source'; $end_bundles = $endpoint . '_bundles'; foreach ($relation_type->$end_bundles as $relation_bundle) { if (!isset($item['entity_bundle'])) { $endpoint_entities = entity_load($item['entity_type'], array($item['entity_id'])); $endpoint_entity = reset($endpoint_entities); list(, , $item['entity_bundle']) = entity_extract_ids($item['entity_type'], $endpoint_entity); } $relation_bundle_array = explode(':', $relation_bundle, 2); if (($relation_bundle == $item['entity_type'] . ':' . $item['entity_bundle']) || (($item['entity_type'] == $relation_bundle_array[0]) && ($relation_bundle_array[1] == '*'))) { $acceptable = TRUE; break; } } if (!$acceptable) { $t_arguments = array('%relation_type' => $entity->relation_type, '@bundle' => $item['entity_bundle']); if ($relation_type->directional) { if ($endpoint == 'target') { $errors[] = array( 'error' => 'relation_unsupported_target', 'message' => t("The %relation_type relation type does not allow @bundle entities as target.", $t_arguments), ); } else { $errors[] = array( 'error' => 'relation_unsupported_source', 'message' => t("The %relation_type relation type does not allow @bundle entities as source.", $t_arguments), ); } } else { $errors[] = array( 'error' => 'relation_unsupported_endpoint', 'message' => t("The %relation_type relation type does not allow @bundle entities as an endpoint.", $t_arguments), ); } } } } /** * Implements hook_field_presave(). */ function relation_endpoint_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) { // We need r_index here because EntityFieldQuery can't query on deltas. foreach ($items as $delta => &$item) { $item['r_index'] = $delta; } } /** * Implements hook_field_update(). */ function relation_endpoint_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) { // We do not update. } /** * Implements hook_field_is_empty(). */ function relation_endpoint_field_is_empty($item, $field) { // We are never empty. return FALSE; } /** * Helper to create an HTML table representing a relation. */ function _relation_endpoint_field_create_html_table($endpoints) { $list_items = array(); foreach ($endpoints as $delta => $endpoint) { $entities = entity_load($endpoint['entity_type'], array($endpoint['entity_id'])); $entity = reset($entities); $label = entity_label($endpoint['entity_type'], $entity); $uri = entity_uri($endpoint['entity_type'], $entity); $list_items[$delta] = array(l($label, $uri['path'], $uri['options']), $endpoint['entity_type']); } $headers = array( 'Entity', array('width' => '22%', 'data' => 'Entity_type'), ); return array( '#theme' => 'table', '#header' => $headers, '#rows' => $list_items, ); } /** * Implements hook_field_formatter_info(). */ function relation_endpoint_field_formatter_info() { return array( 'relation_endpoint' => array( 'label' => t('Endpoints table'), 'field types' => array('relation_endpoint'), ), ); } /** * Implements hook_field_widget_info(). */ function relation_endpoint_field_widget_info() { return array( 'relation_endpoint' => array( 'label' => t('Endpoints table'), 'field types' => array('relation_endpoint'), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_CUSTOM, ), ), ); } /** * Implements hook_field_formatter_view(). */ function relation_endpoint_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { return array(_relation_endpoint_field_create_html_table($items)); } /** * Implements hook_field_widget_form(). */ function relation_endpoint_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { foreach ($items as $delta => $item) { foreach (array('entity_type', 'entity_id') as $column) { $element[$delta][$column] = array( '#type' => 'value', '#value' => $item[$column], ); } } $element['link_list'] = _relation_endpoint_field_create_html_table($items); return $element; } /** * Implements hook_form_field_ui_field_overview_form_alter(). */ function relation_endpoint_form_field_ui_field_overview_form_alter(&$form, $form_state) { // Deleting endpoints would make the module useless. if ($form['#entity_type'] == 'relation') { $form['fields']['endpoints']['delete'] = array( '#type' => 'markup', '#markup' => ' ', ); } }