$value) { if (!isset($value)) { continue; } $operator = _user_relationship_process_query_argument($key, $value); switch ($key) { case 'between': $between_cond = "((ur.requester_id {$operator[0]} AND ur.requestee_id {$operator[1]}) OR ("; //#479486 do not include reverse records of two-way relationships by default if (!isset($include_twoway_reverse)) { $between_cond .= '(ur.approved <> 1 OR urt.is_oneway <> 0) AND '; $twoway_reverse_clause = TRUE; } $between_cond .= "ur.requestee_id {$operator[0]} AND ur.requester_id {$operator[1]}))"; $cond[] = $between_cond; $arguments[] = $value[0]; $arguments[] = $value[1]; $arguments[] = $value[0]; $arguments[] = $value[1]; break; case 'user': //#479486 when showing all user's relationships, do not include reverse records of two-way relationships if (!isset($include_twoway_reverse)) { $cond[] = "(ur.requester_id {$operator} OR ((ur.approved <> 1 OR urt.is_oneway <> 0) AND ur.requestee_id {$operator}))"; $twoway_reverse_clause = TRUE; } else { $cond[] = "(ur.requester_id {$operator} OR ur.requestee_id {$operator})"; } $arguments[] = $value; $arguments[] = $value; break; case 'requester_id': case 'requestee_id': $twoway_reverse_clause = TRUE;//#479486 these columns automatically should exclude duplicates default: $types_cols = array('name', 'plural_name', 'is_oneway', 'is_reciprocal', 'requires_approval', 'expires_val'); $cond[] = "%s.%s {$operator}"; $arguments[] = !in_array($key, $types_cols) ? 'ur' : 'urt'; $arguments[] = $key; //#358669 support having multiple values for a single column - the query already has IN(...) placeholders if (!is_array($value)) { $arguments[] = $value; } else { $arguments = array_merge($arguments, $value); } } } //#479486 add a general clause that removed reverse direction from two-way relationship results, unless it's been addressed above if (!$twoway_reverse_clause && !isset($include_twoway_reverse)) { $cond[] = '(urt.is_oneway <> 0 OR ur.approved <> 1 OR ur.requester_id < ur.requestee_id)'; $twoway_reverse_clause = TRUE; } $selects = array('DISTINCT ur.rid', 'ur.*', 'urt.*'); $joins = array('INNER JOIN {user_relationship_types} urt USING ( rtid )'); // We wont need anything after this point for the count SQL $count_joins = implode(' ', $joins); if (isset($include_user_info) && $include_user_info) { $selects = array_merge($selects, array( 'requesters.name AS requester_name', 'requestees.name AS requestee_name', 'requesters.mail AS requester_mail', 'requestees.mail AS requestee_mail', 'requesters.data AS requester_data', 'requestees.data AS requestee_data', 'requesters.picture AS requester_picture', 'requestees.picture AS requestee_picture', )); $joins = array_merge($joins, array( 'INNER JOIN {users} requesters ON ur.requester_id = requesters.uid', 'INNER JOIN {users} requestees ON ur.requestee_id = requestees.uid' )); } $selects = implode(',', $selects); $joins = implode(' ', $joins); $cond = $cond ? 'WHERE '. implode(' AND ', $cond) : ''; $extra = array(); if (!empty($order)) { $extra[] = "ORDER BY {$order}"; } if (!empty($limit)) { $extra[] = "LIMIT {$limit}"; } $extra = is_array($extra) ? implode(' ', $extra) : $extra; return array( //331692 remove improper GROUP BY rid for Postgre 'query' => "SELECT {$selects} FROM {user_relationships} ur {$joins} {$cond} {$extra}", 'count' => "SELECT COUNT(DISTINCT rid) AS count FROM {user_relationships} ur {$count_joins} {$cond}", 'arguments' => $arguments, ); } /** * Helper function to process the various argument types allowed */ function _user_relationship_process_query_argument($key, &$value) { if ($key == 'between') { return array( _user_relationship_process_query_argument(NULL, $value[0]), _user_relationship_process_query_argument(NULL, $value[1]), ); } if (is_array($value)) { if (count($value) == 1) { $value = array_shift($value); return _user_relationship_process_query_argument($key, $value); } else { $type = is_numeric(current($value)) ? 'int' : 'varchar'; return 'IN ('. db_placeholders($value, $type) .')'; } } elseif (is_numeric($value) || is_bool($value)) { $value = (int)$value; return '= %d'; } elseif (is_float($value)) { return '= %f'; } elseif (preg_match('/([<>=]{1,2})\s*(.+)/', $value, $matches)) { $marker = "'%s'"; $value = $matches[3]; if (is_numeric($value)) { $marker = '%d'; $value = (int)$value; } return "{$matches[1]} {$marker}"; } else { return "= '%s'"; } } /** * hook_perm() */ function user_relationships_api_perm() { return array('can have relationships'); } /** * hook_cron() */ function user_relationships_api_cron() { $now = time(); // only expire relationships once a day $last_cron = variable_get('user_relationships_last_expire', 0); if ($now < $last_cron + 86400) { return FALSE; } $result = db_query( " SELECT ur.rid FROM {user_relationships} ur INNER JOIN {user_relationship_types} urt ON ur.rtid = urt.rtid WHERE ur.approved = 0 AND urt.expires_val > 0 AND ur.updated_at < (%d - (urt.expires_val * 86400)) GROUP BY ur.rid", $now ); $expired_requests = array(); while ($request = db_fetch_object($result)) { $expired_requests[] = $request->rid; } if (count($expired_requests)) { db_query('DELETE FROM {user_relationships} WHERE rid IN ('. db_placeholders($expired_requests) .')', $expired_requests); //FIXME: this will trigger various hook_user_relationships() but will not pass a valid relationship object. E.g. in mailer. _user_relationships_invoke('delete', $expired_requests); } // remember when we last expired relationships variable_set('user_relationships_last_expire', $now); return TRUE; } /** * hook_user() */ function user_relationships_api_user($type, &$edit, &$account, $category = NULL) { if ($type == 'delete') { db_query("DELETE FROM {user_relationships} WHERE requester_id = %d OR requestee_id = %d", $account->uid, $account->uid); } } /** * Wrapper function for tt() if i18nstrings enabled. */ function ur_tt($name, $string, $langcode = NULL, $update = FALSE) { if (module_exists('i18nstrings')) { return tt($name, $string, $langcode, $update); } else { return $string; } } /** * Implementation of hook_user_relationships(). * or * Implementation of hook_trigger_name(). */ function user_relationships_api_user_relationships($op, &$relationship) { if ($op != 'approve' && $op != 'request') { return; } if (module_exists('trigger')) { $aids = _trigger_get_hook_aids('user_relationships_api', $op); $context = array( 'hook' => 'user_relationships_api', 'op' => $op, 'requester' => $relationship->requester, 'requestee' => $relationship->requestee, 'relationship' => $relationship, ); //print_r($relationship); actions_do(array_keys($aids), $relationship, $context); } } /** * Implementation of hook_activity_info(). */ function user_relationships_api_activity_info() { $info = new stdClass(); $info->api = 2; $info->name = 'user_relationships_api'; $info->object_type = 'user_relationships_api'; $info->objects = array('Requester' => 'requester', 'Requestee' => 'requestee', 'Relationship' => 'relationship'); $info->hooks = array('user_relationships_api' => array('approve', 'request')); foreach (user_relationships_types_load() as $type_obj) { $info->realms["user_relationships_" . $type_obj->rtid] = $type_obj->plural_name; } return $info; } /** * Implementation of hook_token_list(). */ function user_relationships_api_token_list($type = 'all') { if ($type == 'requester') { $tokens['user_relationships_api'] = array( 'requester' => t('The user who issued the connection request.'), ); } elseif ($type == 'relationship') { $tokens['user_relationships_api'] = array( 'requestee' => t('The user who approved the connnection request.'), 'relationship-name' => t('The relationship name (singular form)'), ); } return $tokens; } /** * Implementation of hook_token_values(). */ function user_relationships_api_token_values($type, $data = NULL, $options = array()) { if ($type == 'requester') { $r = $data; $token_values = array( 'requester' => theme('username', user_load(array('uid' => $r->uid))), ); } elseif ($type == 'requestee') { $r = $data; $token_values = array( 'requestee' => theme('username', user_load(array('uid' => $r->uid))), ); } elseif ($type == 'relationship') { // http://drupal.org/node/811222 need to unwrap the relationship object from an array sometimes if (is_array($data)) { foreach ($data as $object) { if (is_object($object)) { $r = $object; break; } } } else { $r = $data; } $r_type = user_relationships_type_load((int) $r->rtid); $token_values = array( 'requestee' => theme('username', user_load(array('uid' => $r->requestee_id))), 'requester' => theme('username', user_load(array('uid' => $r->requester_id))), 'relationship-name' => theme('placeholder', $r_type->name), ); } return isset($token_values) ? $token_values : NULL; }