From 809699cf8e36263a6470246ed5faec2f13ee7b87 Mon Sep 17 00:00:00 2001
From: Moritz Strohm <strohm@data-quest.de>
Date: Fri, 28 Sep 2018 13:07:18 +0200
Subject: [PATCH] started work on ticket 7, re #7

---
 classes/TandemMatching.class.php | 125 ++++++++++++++++---------------
 1 file changed, 63 insertions(+), 62 deletions(-)

diff --git a/classes/TandemMatching.class.php b/classes/TandemMatching.class.php
index a828b94..f4f3b6c 100644
--- a/classes/TandemMatching.class.php
+++ b/classes/TandemMatching.class.php
@@ -21,12 +21,12 @@ require_once(__DIR__ . '/../models/TandemUserMotherLanguage.class.php');
  */
 class TandemMatching
 {
-    
+
     /**
      * Helper method for building the SQL query for findMatches and countMatches.
      * Since both methods use the same query and differ only in the result
      * the query can be built in this helper method.
-     * 
+     *
      * @return Array Associative array with two attributes:
      *     - 'query': The SQL query
      *     - 'params': Parameters for the SQL query
@@ -35,9 +35,9 @@ class TandemMatching
     {
         //if the gender attribute is set we must convert its value to
         //the Stud.IP system values: 1 = male, 2 = female, 0 = unspecified:
-        
+
         $request_gender = null;
-        
+
         if($tandem_request->gender and TandemPlugin::isGenderSearchEnabled()) {
             //If gender search is enabled and a gender preference is set
             //we must filter for those settings.
@@ -47,92 +47,93 @@ class TandemMatching
                 $request_gender = 2;
             }
         }
-        
-        
+
+
         $sql = 'INNER JOIN tandem_user_mother_languages as tuml
                 ON tuml.user_id = tandem_profiles.user_id ';
-        
+
         if($request_gender) {
             //If the gender attribute from the request was converted correctly
             //we must also search for the gender information using the user_info table.
             $sql .= 'INNER JOIN user_info
                     ON tuml.user_id = user_info.user_id ';
         }
-                
+
         $sql .= 'WHERE tuml.language_id = :target_language_id
-            AND tuml.user_id <> :user_id 
+            AND tuml.user_id <> :user_id
             AND tandem_profiles.target_language_id IN ( :request_user_mother_language_ids ) ';
-        
-        
+
+
         //We must check, if there are tandem pairs. Profiles in tandem pairs
         //with pair status 1 (accepted) and 0 (requested) are filtered out.
         //Also all profiles where a tandem request was made to are filtered out.
-        
+
         $pairs_exist = (TandemPair::countBySql('TRUE') > 0);
-        
+
         if($pairs_exist) {
             //QUERY EXPLAINATION:
             // tandem_profiles.id NOT IN:
             //     We must filter all profiles that are bound to a pair matching
             //     the following criteria.
-            //     
-            // SELECT request_profile_id FROM tandem_pairs WHERE status > '-1' 
+            //
+            // SELECT request_profile_id FROM tandem_pairs WHERE status > '-1'
             // AND request_profile_id = :profile_id:
             //     The profile-ID of the profile we're searching matches for
-            //     must match either the request_profile_id or the 
-            //     offer_profile_id. The latter filters out all requests 
+            //     must match either the request_profile_id or the
+            //     offer_profile_id. The latter filters out all requests
             //     and established pairs that have been made with that profile.
-            // 
+            //
             // SELECT offer_profile_id FROM tandem_pairs WHERE status > '-1':
             //     The same as with request_profile_id but here we're selecting
             //     the offer_profile_ids and use them in a UNION.
-            // 
+            //
             // SELECT request_profile_id FROM tandem_pairs WHERE status = '1'
             // and
             // SELECT offer_profile_id FROM tandem_pairs WHERE status = '1':
             //     We select the request_profile_ids and offer_profile_ids
             //     of all established pairs.
             // )
-            
+
             $sql .= "AND tandem_profiles.id NOT IN (
-                SELECT request_profile_id FROM tandem_pairs WHERE request_profile_id = :profile_id OR offer_profile_id = :profile_id
+                SELECT request_profile_id AS id FROM tandem_pairs WHERE request_profile_id = :profile_id OR offer_profile_id = :profile_id
                 UNION
-                SELECT offer_profile_id FROM tandem_pairs WHERE offer_profile_id = :profile_id OR request_profile_id = :profile_id
+                SELECT offer_profile_id AS id FROM tandem_pairs WHERE offer_profile_id = :profile_id OR request_profile_id = :profile_id
                 UNION
-                SELECT request_profile_id FROM tandem_pairs WHERE status = '1'
+                SELECT request_profile_id AS id FROM tandem_pairs WHERE status = '1'
                 UNION
-                SELECT offer_profile_id FROM tandem_pairs WHERE status = '1'
+                SELECT offer_profile_id AS id FROM tandem_pairs WHERE status = '1'
+                GROUP BY id
             ) ";
         }
-        
-        
+
+
         $request_user_mother_language_ids = [];
         $rumls = TandemUserMotherLanguage::findBySql(
             'user_id = :user_id',
             ['user_id' => $tandem_request->user_id]
         );
-        
+
         foreach($rumls as $ruml) {
             $request_user_mother_language_ids[] = $ruml->language_id;
         }
-        
-        
+
+
         $sql_params = [
             'target_language_id' => $tandem_request->target_language_id,
             'user_id' => $tandem_request->user_id,
             'request_user_mother_language_ids' => $request_user_mother_language_ids
         ];
-        
+
         if($request_gender) {
             //The offere must have the gender the requester wishes.
             $sql .= 'AND user_info.geschlecht = :request_gender ';
             $sql_params['request_gender'] = $request_gender;
         }
-        
+
         if(TandemPlugin::isGenderSearchEnabled()) {
             //The requester must have the gender the offerer wishes.
             $requester_gender = $tandem_request->user->geschlecht;
-            
+
             //convert Stud.IP gender to TandemPlugin gender:
             if($requester_gender == '1') {
                 $requester_gender = 'm';
@@ -141,7 +142,7 @@ class TandemMatching
             } else {
                 $requester_gender = '';
             }
-            
+
             if($requester_gender != '') {
                 //In cases where the gender is relevant
                 //we must extend the SQL query and check if the offerer
@@ -154,42 +155,42 @@ class TandemMatching
                 $sql .= "AND tandem_profiles.gender = '' ";
             }
         }
-        
-        
+
+
         if($offer_user_id != null) {
             $sql .= 'AND tandem_profiles.user_id = :offer_user_id ';
             $sql_params['offer_user_id'] = $offer_user_id;
         }
-        
-        
+
+
         if($pairs_exist) {
             $sql_params['profile_id'] = $tandem_request->id;
         }
-        
+
         $sql .= ' GROUP BY tandem_profiles.id, tandem_profiles.user_id ';
-        
-        
+
+
         if($limit > 0) {
             $sql .= 'LIMIT :limit';
             $sql_params['limit'] = $limit;
         }
-        
-        
+
+
         return [
             'query' => $sql,
             'params' => $sql_params
         ];
     }
-    
-    
+
+
     /**
      * Finds matches for a given tandem request.
-     * 
+     *
      * @param TandemProfile $tandem_request A tandem profile
      *     that shall be checked for matches.
      * @param int $limit Limits the number of matches.
      * @param string $offer_user_id Limits the search for profiles for one offerer.
-     * 
+     *
      * @return TandemProfile[] List of tandem profiles that match the criteria
      *     specified in $tandem_request.
      */
@@ -204,21 +205,21 @@ class TandemMatching
                 'profile_id' => $tandem_request->id
             ]
         );
-        
+
         if($pair_count > 0) {
             //We don't look for matches if there is already a pair!
             return [];
         }
-        
+
         $query = self::buildMatchSqlQuery($tandem_request, $limit, $offer_user_id);
-        
+
         return TandemProfile::findBySql($query['query'], $query['params']);
     }
-    
-    
+
+
     /**
      * Counts matches for a given tandem profile.
-     * 
+     *
      * @param TandemProfile $tandem_request A tandem profile
      *     that shall be checked for matches.
      * @param string $offer_user_id Limits the search for profiles for one offerer.
@@ -236,36 +237,36 @@ class TandemMatching
                 'profile_id' => $tandem_request->id
             ]
         );
-        
+
         if($pair_count > 0) {
             //We don't count matches if there is already a pair!
             return 0;
         }
-        
+
         $query = self::buildMatchSqlQuery($tandem_request, 0, $offer_user_id);
-        
+
         return TandemProfile::countBySql($query['query'], $query['params']);
     }
-    
-    
-    
+
+
+
     static public function matchesExist(Array $profiles = [])
     {
         if(!$profiles) {
             //Empty array means we can't look for matches!
             return false;
         }
-        
-        
+
+
         foreach($profiles as $profile) {
             $count_result = self::countMatches($profile);
-            
+
             if($count_result > 0) {
                 //We have found one match: That's enough to see if a match exists:
                 return true;
             }
         }
-        
+
         //No matches found:
         return false;
     }
-- 
GitLab