diff --git a/ctools/relationships/entity_from_entityreference_field.inc b/ctools/relationships/entity_from_entityreference_field.inc new file mode 100644 index 0000000..fe92491 --- /dev/null +++ b/ctools/relationships/entity_from_entityreference_field.inc @@ -0,0 +1,155 @@ + t('Entity reference'), + 'description' => t('Creates an entity context from a an entity reference field.'), + 'context' => 'entity_from_entityreference_field_context', + 'edit form' => 'entity_from_entityreference_field_edit_form', + 'get child' => 'entity_from_entityreference_field_get_child', + 'get children' => 'entity_from_entityreference_field_get_children', + 'defaults' => array('delta' => 0), +); + +function entity_from_entityreference_field_get_child($plugin, $parent, $child) { + $plugins = entity_from_entityreference_field_get_children($plugin, $parent); + return $plugins[$parent . ':' . $child]; +} + +function entity_from_entityreference_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'); + $plugins = array(); + + foreach (field_info_fields() as $field_name => $field_info) { + if ($field_info['type'] != 'entityreference') { + continue; + } + + // Different entity types can refer a single entity type, per field. + $from_entities = array_keys($field_info['bundles']); + $to_entity = $field_info['settings']['target_type']; + $to_entity_info = entity_get_info($to_entity); + + foreach ($from_entities as $from_entity) { + $name = $field_name . ':' . $from_entity . ':' . $to_entity; + $plugin_id = $parent . ':' . $name; + + // We check for every bundle; this plugin may already have + // been created, so don't recreate it. + if (!empty($plugins[$plugin_id])) { + continue; + } + + $from_entity_info = entity_get_info($from_entity); + $bundles = array_keys($field_info['bundles'][$from_entity]); + + $plugin = $parent_plugin; + $replacements = array( + '@to_entity' => $to_entity_info['label'], + '@from_entity' => $from_entity_info['label'], + '@field_name' => ctools_field_label($field_name), + ); + $plugin['title'] = t('@to_entity from @from_entity (on @from_entity: @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['parent'] = $parent; + $plugin['required context'] = new ctools_context_required($from_entity_info['label'], 'entity:' . $from_entity, array('type' => $bundles)); + + $plugins[$plugin_id] = $plugin; + } + } + + $cache[$cid] = $plugins; + return $plugins; +} + +/** + * Return a new context based on an existing context. + */ +function entity_from_entityreference_field_context($context, $conf) { + $delta = !empty($conf['delta']) ? $conf['delta'] : 0; + $plugin = $conf['name']; + list($plugin, $plugin_name) = explode(':', $plugin, 2); + 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); + } + + $entity_info_id = $entity_info['entity keys']['id']; + if (isset($context->data->{$entity_info_id})) { + // Load the entity. + $from_entity_id = $context->data->{$entity_info_id}; + $wrapper = entity_metadata_wrapper($from_entity, $from_entity_id); + + if (!isset($wrapper->{$field_name})) { + // No such field, bail out. + return; + } + + $field_info = field_info_field($field_name); + + $return = NULL; + if ($field_info['cardinality'] != 1 && $wrapper->{$field_name}->count() >= $delta) { + $return = $wrapper->{$field_name}->get($delta)->value(array('identifier' => TRUE)); + } + elseif ($field_info['cardinality'] == 1) { + $return = $wrapper->{$field_name}->value(array('identifier' => TRUE)); + } + + // Send it to ctools with the ID of the "to entity" ID or NULL. + return ctools_context_create('entity:' . $to_entity, $return); + } +} + +/** + * Edit form. + */ +function entity_from_entityreference_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, + '#element_validate' => array('element_validate_integer'), + '#required' => TRUE, + ); + } + 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(0, $field['cardinality'] - 1), + '#default_value' => !empty($conf['delta']) ? $conf['delta'] : 0, + ); + } + } + + return $form; +} diff --git a/entityreference.module b/entityreference.module index 60230a7..b5b0cd9 100644 --- a/entityreference.module +++ b/entityreference.module @@ -7,6 +7,9 @@ function entityreference_ctools_plugin_directory($module, $plugin) { if ($module == 'entityreference') { return $plugin; } + elseif ($module == 'ctools') { + return 'ctools/' . $plugin; + } } /**