+
+ /**
+ * Filter a list of contact_ids by the ones that the
+ * currently active user as a permissioned relationship with
+ *
+ * @param array $contact_ids
+ * List of contact IDs to be filtered
+ *
+ * @return array
+ * List of contact IDs that the user has permissions for
+ */
+ public static function relationshipList($contact_ids) {
+ $result_set = array();
+
+ // no processing empty lists (avoid SQL errors as well)
+ if (empty($contact_ids)) {
+ return $result_set;
+ }
+
+ // get the currently logged in user
+ $session = CRM_Core_Session::singleton();
+ $contactID = (int) $session->get('userID');
+ if (empty($contactID)) {
+ return $result_set;
+ }
+
+ // compile a list of queries (later to UNION)
+ $queries = array();
+ $contact_id_list = implode(',', $contact_ids);
+
+
+ // add a select for each direection
+ $directions = array(array('from' => 'a', 'to' => 'b'), array('from' => 'b', 'to' => 'a'));
+ foreach ($directions as $direction) {
+ $user_id_column = "contact_id_{$direction['from']}";
+ $contact_id_column = "contact_id_{$direction['to']}";
+
+ // add clause for deleted contacts, if the user doesn't have the permission to access them
+ $LEFT_JOIN_DELETED = $CAN_ACCESS_DELETED = '';
+ if (!CRM_Core_Permission::check('access deleted contacts')) {
+ $LEFT_JOIN_DELETED = 'LEFT JOIN civicrm_contact ON civicrm_contact.id = {$contact_id_column}';
+ $AND_CAN_ACCESS_DELETED = 'AND civicrm_contact.is_deleted = 0';
+ }
+
+ $queries[] = "
+SELECT DISTINCT(civicrm_relationship.{$contact_id_column}) AS contact_id
+ FROM civicrm_relationship
+ {$LEFT_JOIN_DELETED}
+ WHERE civicrm_relationship.{$user_id_column} = {$contactID}
+ AND civicrm_relationship.{$contact_id_column} IN ({$contact_id_list})
+ AND civicrm_relationship.is_active = 1
+ AND civicrm_relationship.is_permission_{$direction['from']}_{$direction['to']} = 1
+ $AND_CAN_ACCESS_DELETED";
+ }
+
+ // add second degree relationship support
+ if ($config->secondDegRelPermissions) {
+ foreach ($directions as $first_direction) {
+ foreach ($directions as $second_direction) {
+ // add clause for deleted contacts, if the user doesn't have the permission to access them
+ $LEFT_JOIN_DELETED = $CAN_ACCESS_DELETED = '';
+ if (!CRM_Core_Permission::check('access deleted contacts')) {
+ $LEFT_JOIN_DELETED = 'LEFT JOIN civicrm_contact ON civicrm_contact.id = {$contact_id_column}';
+ $AND_CAN_ACCESS_DELETED = 'AND civicrm_contact.is_deleted = 0';
+ }
+
+ $queries[] = "
+SELECT DISTINCT(civicrm_relationship.{$contact_id_column}) AS contact_id
+ FROM civicrm_relationship first_degree_relationship
+ LEFT JOIN civicrm_relationship second_degree_relationship ON first_degree_relationship.contact_id_{$first_direction['to']} = second_degree_relationship.contact_id_{$first_direction['from']}
+ {$LEFT_JOIN_DELETED}
+ WHERE first_degree_relationship.contact_id_{$first_direction['from']} = {$contactID}
+ AND second_degree_relationship.contact_id_{$second_direction['to']} IN ({$contact_id_list})
+ AND first_degree_relationship.is_active = 1
+ AND first_degree_relationship.is_permission_{$first_direction['from']}_{$first_direction['to']} = 1
+ AND second_degree_relationship.is_active = 1
+ AND second_degree_relationship.is_permission_{$second_direction['from']}_{$second_direction['to']} = 1
+ $AND_CAN_ACCESS_DELETED";
+ }
+ }
+ }
+
+ // finally UNION the queries and call
+ $query = "(" . implode(")\nUNION (", $queries) . ")";
+ $result = CRM_Core_DAO::executeQuery($query);
+ while ($result->fetch()) {
+ $result_set[] = (int) $result->contact_id;
+ }
+
+ return $result_set;
+ }
+
+
+
+