From 481e706f6785d84cd0a3b8d2db891a15912b6593 Mon Sep 17 00:00:00 2001
From: solotandem <jim@boombatower.com>
Date: Mon, 26 Oct 2015 19:08:02 +0000
Subject: [PATCH] Issue #2600076 by solotandem: Implement tokens declared by
 entity module.

  Refactor code from relation_rules_get_specific_endpoints() as
    relation_get_endpoints_by_endpoint_type() to retrieve the applicable endpoints.
  Add $endpoint_type and $load_entities parameters to relation_get_endpoints().
  Modify relation_get_endpoints() to return an array of entity_ids or entities.
  Update relation_tokens() to process tokens like 'endpoints-(source|target)-(entity_type)'.
---
 relation.module     |   80 ++++++++++++++++++++++++++++++++++++++++-----------
 relation.rules.inc  |   12 +-------
 relation.tokens.inc |   10 +++++++
 3 files changed, 74 insertions(+), 28 deletions(-)

diff --git a/relation.module b/relation.module
index 4674b10..9ff8151 100644
--- a/relation.module
+++ b/relation.module
@@ -753,30 +753,76 @@ function relation_query($entity_type = NULL, $entity_id = NULL, $r_index = NULL)
 }
 
 /**
- * Return endpoint entities.
+ * Returns endpoint entities (or entity IDs).
  *
- * @param $relation
+ * @param object $relation
  *   Full relation object containing the endpoints
+ * @param string $entity_type
+ *   (optional) If set, filter by entity type; else return all endpoints.
+ * @param string $endpoint_type
+ *   (optional) If set, filter by endpoint type, either 'source' or 'target';
+ *   else return all endpoints.
+ * @param boolean $load_entities
+ *   (optional) Whether to return entities or entity IDs.
  *
- * @param $entity_type
- *   (optional) Filter endpoints by entity type. Return all endpoint entities
- *   if empty.
- */
-function relation_get_endpoints($relation, $entity_type = NULL) {
-  $entities = array();
-  foreach ($relation->endpoints[LANGUAGE_NONE] as $endpoint) {
-    if (!empty($entity_type) && $endpoint['entity_type'] != $entity_type) {
-      continue;
+ * @return array
+ *   The endpoint entities (or entity IDs).
+ */
+function relation_get_endpoints($relation, $entity_type = NULL, $endpoint_type = NULL, $load_entities = TRUE) {
+  $items = array();
+  $endpoints = relation_get_endpoints_by_endpoint_type($relation, $endpoint_type);
+  foreach ($endpoints as $endpoint) {
+    if (empty($entity_type) || $endpoint['entity_type'] == $entity_type) {
+      $items[$endpoint['entity_type']][] = $endpoint['entity_id'];
     }
-    $entities[$endpoint['entity_type']][] = $endpoint['entity_id'];
   }
-  if (empty($entities)) {
-    return FALSE;
+
+  if ($load_entities) {
+    foreach ($items as $entity_type => $ids) {
+      $items[$entity_type] = entity_load($entity_type, $ids);
+    }
   }
-  foreach ($entities as $entity_type => $ids) {
-    $entities[$entity_type] = entity_load($entity_type, $ids);
+  return $items;
+}
+
+/**
+ * Returns the endpoints of a specific endpoint type.
+ *
+ * @param object $relation
+ *   A relation object containing the endpoints.
+ * @param string $endpoint_type
+ *   (optional) The endpoint type, either 'source' or 'target'.
+ *
+ * @return array
+ *   The endpoints.
+ */
+function relation_get_endpoints_by_endpoint_type($relation, $endpoint_type = 'source') {
+  if (empty($endpoint_type)) {
+    return $relation->endpoints[LANGUAGE_NONE];
   }
-  return $entities;
+  if (!in_array($endpoint_type, array('source', 'target'))) {
+    return array();
+  }
+
+  $relation_type = relation_type_load($relation->relation_type);
+  $endpoint_type = $relation_type->directional ? $endpoint_type : 'source';
+
+  // At present, relation only supports a 1-to-many directional relation. In
+  // other words, a directional relation may only have one source endpoint; all
+  // other endpoints are target endpoints.
+  if ($endpoint_type == 'source') {
+    if ($relation_type->directional) {
+      $endpoints = array($relation->endpoints[LANGUAGE_NONE][0]);
+    }
+    else {
+      $endpoints = $relation->endpoints[LANGUAGE_NONE];
+    }
+  }
+  else {
+    $endpoints = array_slice($relation->endpoints[LANGUAGE_NONE], 1);
+  }
+
+  return $endpoints;
 }
 
 /**
diff --git a/relation.rules.inc b/relation.rules.inc
index e1213c1..5cc7093 100644
--- a/relation.rules.inc
+++ b/relation.rules.inc
@@ -122,17 +122,7 @@ function relation_rules_get_endpoints($relation, array $options, $property_name,
  * Entity-type specific property getter callback.
  */
 function relation_rules_get_specific_endpoints($relation, array $options, $property_name, $entity_type, $info) {
-  if ($info['endpoint_type'] == 'source') {
-    if ($info['relation_directional']) {
-      $endpoints = array($relation->endpoints[LANGUAGE_NONE][0]);
-    }
-    else {
-      $endpoints = $relation->endpoints[LANGUAGE_NONE];
-    }
-  }
-  else {
-    $endpoints = array_slice($relation->endpoints[LANGUAGE_NONE], 1);
-  }
+  $endpoints = relation_get_endpoints_by_endpoint_type($relation, $info['endpoint_type']);
 
   $array = array();
   foreach ($endpoints as $endpoint) {
diff --git a/relation.tokens.inc b/relation.tokens.inc
index f16449a..8e44f8d 100644
--- a/relation.tokens.inc
+++ b/relation.tokens.inc
@@ -135,6 +135,16 @@ function relation_tokens($type, $tokens, array $data = array(), array $options =
         case 'changed':
           $replacements[$original] = format_date($relation->changed, 'medium', '', NULL, $language_code);
           break;
+
+        default:
+          if (substr($name, 0, 10) == 'endpoints-') {
+            // These tokens are created by entity module from the entity properties.
+            // See relation_entity_property_info_alter().
+            list(, $endpoint_type, $entity_type) = explode('-', $name);
+            $endpoints = relation_get_endpoints_by_endpoint_type($relation, $endpoint_type);
+            $endpoint = array_shift($endpoints);
+            $replacements[$original] = isset($endpoint['entity_id']) ? $endpoint['entity_id'] : 0;
+          }
       }
     }
 
-- 
1.7.10.4

