0

I am using the Drupal 7 Rules and Relation modules. I have a relation between a user entity and a node content type (membership). The relation has an added field (relationship type). I was able to define a rule to create a new relation entity and set the relationship type field when creating a new membership node.

Now I am trying to write a rule with a condition that checks the value of the relationship type field at the time some event referencing a user or membership entity fires. The Relation module provides actions to fetch endpoint entities, but I cannot find a way to fetch the relation entity itself. What I'm searching for is a way to load that relation entity, tell Rules the relation type to expect, then be able to access the field (relationship type) on that relation.

Thanks in advance for any advise.

1

I believe Rules lets you write custom php. Relation has an API. You can query for a relation directly using relation_load and giving it a relation_id. You can also search for a relation by supplying 1 endpoint and the type of relation you are looking for (or empty to return all relations of that endpoint, using the relation_query() function.

/**
 * Returns a query object to find related entities.
 *
 * @param $entity_type
 *   (optional) The entity type of one of the endpoints.
 * @param $entity_id
 *   (optional) The entity id of one of the endpoints. Can also be an array of
 *   entity IDs.
 * @param $r_index
 *   (optional) The index of the search entity in the relation to be found
 *   (0 = source, 1 = target).
 *
 * @return RelationQuery
 *   The query object itself.
 */
function relation_query($entity_type = NULL, $entity_id = NULL, $r_index = NULL) {
  return new RelationQuery($entity_type, $entity_id, $r_index);
}

The RelationQuery is simply a small custom extension of the core EntityFieldQuery. You can use relation_query() and pass it a UID and a NID as the endpoints -- relation_query will return the Relation ids (RIDs) for those objects. You can inspect the relations further by calling relation_load($rid).

You can then do whatever you need to with the relation(s). A small example. In my app students have surveys assigned to them to complete; using Relations. When they're done with a survey I want to change a flag on the Relation that the survey is completed ...

function _mark_student_survey_as_completed($user_id, $survey_id) {
  // using relation query we want to search for a $user and a
  // specific survey they should have been assigned. Many arguments
  // to relation_query are optional, you can more results; like
  // if you just supply a UID, you'll get all relations that use
  // that UID as an endpoint.
  $relation_ids = relation_query('user', $user_id)
      ->related('custom_survey',$survey_id)
      ->execute();
  $relations = entity_load('relation', array_keys($relation_ids));
  if (count($relations) == 1) {
    $relation = reset($relations);
    // survey_is_completed is an attached field, to the Relation;
    // not an endpoint.
    $relation->survey_is_completed[LANGUAGE_NONE][0]['value'] = 1;
    // Save our field change on the parent relation.
    relation_save($relation);
  } else {
    watchdog('survey_check', 'Duplicate Survey!'.$user_id.'::'.$survey_id.'::'.print_r(array_keys($relation_ids), TRUE), WATCHDOG_ERROR);
 }

Lastly, since RelationQuery is just a class ... I've seen people extend it to make custom "relation logic" more easy, or even Views-like listing easily. Look at this blog post for such ideas (not my blog post): http://www.phase2technology.com/blog/building-energy-gov-without-views/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.